forked from Mirror/frr
Merge pull request #15259 from dmytroshytyi-6WIND/nexthop_resolution
zebra: add LSP entry to nexthop via recursive (part 2)
This commit is contained in:
commit
add56c61dd
|
@ -4634,7 +4634,22 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
|
||||||
if (aspath_get_last_as(attr->aspath) == bgp->as)
|
if (aspath_get_last_as(attr->aspath) == bgp->as)
|
||||||
do_loop_check = 0;
|
do_loop_check = 0;
|
||||||
|
|
||||||
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
|
/* When using bgp ipv4 labeled session, the local prefix is
|
||||||
|
* received by a peer, and finds out that the proposed prefix
|
||||||
|
* and its next-hop are the same. To avoid a route loop locally,
|
||||||
|
* no nexthop entry is referenced for that prefix, and the route
|
||||||
|
* will not be selected.
|
||||||
|
*
|
||||||
|
* As it has been done for ipv4-unicast, apply the following fix
|
||||||
|
* for labeled address families: when the received peer is
|
||||||
|
* a route reflector, the prefix has to be selected, even if the
|
||||||
|
* route can not be installed locally.
|
||||||
|
*/
|
||||||
|
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT) ||
|
||||||
|
(safi == SAFI_UNICAST && !peer->afc[afi][safi] &&
|
||||||
|
peer->afc[afi][SAFI_LABELED_UNICAST] &&
|
||||||
|
CHECK_FLAG(peer->af_flags[afi][SAFI_LABELED_UNICAST],
|
||||||
|
PEER_FLAG_REFLECTOR_CLIENT)))
|
||||||
bgp_nht_param_prefix = NULL;
|
bgp_nht_param_prefix = NULL;
|
||||||
else
|
else
|
||||||
bgp_nht_param_prefix = p;
|
bgp_nht_param_prefix = p;
|
||||||
|
|
|
@ -815,6 +815,16 @@ Allocated label chunks table can be dumped using the command
|
||||||
range is configured, static label requests that match that
|
range is configured, static label requests that match that
|
||||||
range are not accepted.
|
range are not accepted.
|
||||||
|
|
||||||
|
FEC nexthop entry resolution over MPLS networks
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
The LSP associated with a BGP labeled route is normally restricted to
|
||||||
|
directly-connected nexthops. If connected nexthops are not available,
|
||||||
|
the LSP entry will not be installed. This command permits the use of
|
||||||
|
recursive resolution for LSPs, similar to that available for IP routes.
|
||||||
|
|
||||||
|
.. clicmd:: mpls fec nexthop-resolution
|
||||||
|
|
||||||
.. _zebra-srv6:
|
.. _zebra-srv6:
|
||||||
|
|
||||||
Segment-Routing IPv6
|
Segment-Routing IPv6
|
||||||
|
|
|
@ -713,6 +713,15 @@ struct nexthop *nexthop_next(const struct nexthop *nexthop)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct nexthop *nexthop_next_resolution(const struct nexthop *nexthop,
|
||||||
|
bool nexthop_resolution)
|
||||||
|
{
|
||||||
|
if (nexthop_resolution)
|
||||||
|
return nexthop_next(nexthop);
|
||||||
|
/* no resolution attempt */
|
||||||
|
return nexthop->next;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the next nexthop in the tree that is resolved and active */
|
/* Return the next nexthop in the tree that is resolved and active */
|
||||||
struct nexthop *nexthop_next_active_resolved(const struct nexthop *nexthop)
|
struct nexthop *nexthop_next_active_resolved(const struct nexthop *nexthop)
|
||||||
{
|
{
|
||||||
|
|
|
@ -225,6 +225,8 @@ extern bool nexthop_labels_match(const struct nexthop *nh1,
|
||||||
extern const char *nexthop2str(const struct nexthop *nexthop,
|
extern const char *nexthop2str(const struct nexthop *nexthop,
|
||||||
char *str, int size);
|
char *str, int size);
|
||||||
extern struct nexthop *nexthop_next(const struct nexthop *nexthop);
|
extern struct nexthop *nexthop_next(const struct nexthop *nexthop);
|
||||||
|
extern struct nexthop *nexthop_next_resolution(const struct nexthop *nexthop,
|
||||||
|
bool nexthop_resolution);
|
||||||
extern struct nexthop *
|
extern struct nexthop *
|
||||||
nexthop_next_active_resolved(const struct nexthop *nexthop);
|
nexthop_next_active_resolved(const struct nexthop *nexthop);
|
||||||
extern unsigned int nexthop_level(const struct nexthop *nexthop);
|
extern unsigned int nexthop_level(const struct nexthop *nexthop);
|
||||||
|
|
24
tests/topotests/zebra_fec_nexthop_resolution/r1/bgpd.conf
Normal file
24
tests/topotests/zebra_fec_nexthop_resolution/r1/bgpd.conf
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
!
|
||||||
|
router bgp 65500
|
||||||
|
bgp router-id 192.0.2.1
|
||||||
|
neighbor 192.0.2.3 remote-as 65500
|
||||||
|
neighbor 192.0.2.3 update-source lo
|
||||||
|
neighbor 192.0.2.7 remote-as 65500
|
||||||
|
neighbor 192.0.2.7 ttl-security hops 10
|
||||||
|
neighbor 192.0.2.7 disable-connected-check
|
||||||
|
neighbor 192.0.2.7 update-source lo
|
||||||
|
!
|
||||||
|
address-family ipv4 unicast
|
||||||
|
network 192.0.2.1/32
|
||||||
|
no neighbor 192.0.2.3 activate
|
||||||
|
neighbor 192.0.2.7 activate
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
address-family ipv4 labeled-unicast
|
||||||
|
neighbor 192.0.2.3 activate
|
||||||
|
neighbor 192.0.2.3 route-reflector-client
|
||||||
|
neighbor 192.0.2.3 next-hop-self force
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
exit
|
||||||
|
!
|
|
@ -0,0 +1,25 @@
|
||||||
|
log stdout
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip ospf passive
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r1-eth0
|
||||||
|
ip ospf network point-to-point
|
||||||
|
ip ospf hello-interval 1
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
router ospf
|
||||||
|
ospf router-id 192.0.2.1
|
||||||
|
network 192.0.2.1/32 area 0.0.0.0
|
||||||
|
network 192.168.1.0/24 area 0.0.0.0
|
||||||
|
passive-interface lo
|
||||||
|
capability opaque
|
||||||
|
mpls-te on
|
||||||
|
mpls-te router-address 192.0.2.1
|
||||||
|
segment-routing on
|
||||||
|
segment-routing global-block 1000 10000 local-block 32000 32999
|
||||||
|
segment-routing node-msd 8
|
||||||
|
segment-routing prefix 192.0.2.1/32 index 11
|
||||||
|
exit
|
||||||
|
!
|
13
tests/topotests/zebra_fec_nexthop_resolution/r1/zebra.conf
Normal file
13
tests/topotests/zebra_fec_nexthop_resolution/r1/zebra.conf
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
interface lo
|
||||||
|
ip address 192.0.2.1/32
|
||||||
|
mpls enable
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r1-eth0
|
||||||
|
ip address 192.168.1.1/24
|
||||||
|
mpls enable
|
||||||
|
link-params
|
||||||
|
enable
|
||||||
|
exit-link-params
|
||||||
|
exit
|
||||||
|
!
|
23
tests/topotests/zebra_fec_nexthop_resolution/r2/bgpd.conf
Normal file
23
tests/topotests/zebra_fec_nexthop_resolution/r2/bgpd.conf
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
router bgp 65500
|
||||||
|
bgp router-id 192.0.2.2
|
||||||
|
neighbor 192.0.2.1 remote-as 65500
|
||||||
|
neighbor 192.0.2.1 update-source lo
|
||||||
|
neighbor 192.0.2.3 remote-as 65500
|
||||||
|
neighbor 192.0.2.3 update-source lo
|
||||||
|
!
|
||||||
|
address-family ipv4 unicast
|
||||||
|
network 192.0.2.2/32
|
||||||
|
no neighbor 192.0.2.1 activate
|
||||||
|
no neighbor 192.0.2.3 activate
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
address-family ipv4 labeled-unicast
|
||||||
|
neighbor 192.0.2.1 activate
|
||||||
|
neighbor 192.0.2.1 route-reflector-client
|
||||||
|
neighbor 192.0.2.1 next-hop-self force
|
||||||
|
neighbor 192.0.2.3 activate
|
||||||
|
neighbor 192.0.2.3 route-reflector-client
|
||||||
|
neighbor 192.0.2.3 next-hop-self force
|
||||||
|
exit-address-family
|
||||||
|
exit
|
||||||
|
!
|
25
tests/topotests/zebra_fec_nexthop_resolution/r2/isisd.conf
Normal file
25
tests/topotests/zebra_fec_nexthop_resolution/r2/isisd.conf
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip router isis 1
|
||||||
|
isis hello-interval 1
|
||||||
|
isis hello-multiplier 3
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r2-eth1
|
||||||
|
ip router isis 2
|
||||||
|
isis hello-interval 1
|
||||||
|
isis hello-multiplier 3
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
router isis 1
|
||||||
|
is-type level-1
|
||||||
|
net 49.0000.0007.e901.2223.00
|
||||||
|
lsp-timers gen-interval 1 refresh-interval 900 max-lifetime 1200
|
||||||
|
mpls-te on
|
||||||
|
mpls-te router-address 192.0.2.2
|
||||||
|
segment-routing on
|
||||||
|
segment-routing global-block 11000 20000 local-block 36000 36999
|
||||||
|
segment-routing node-msd 8
|
||||||
|
segment-routing prefix 192.0.2.2/32 index 22 no-php-flag
|
||||||
|
exit
|
||||||
|
!
|
|
@ -0,0 +1,32 @@
|
||||||
|
log stdout
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip ospf network point-to-point
|
||||||
|
ip ospf passive
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r2-eth0
|
||||||
|
ip ospf network point-to-point
|
||||||
|
ip ospf hello-interval 1
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r2-eth1
|
||||||
|
ip ospf network point-to-point
|
||||||
|
ip ospf hello-interval 1
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
router ospf
|
||||||
|
ospf router-id 192.0.2.2
|
||||||
|
network 192.0.2.2/32 area 0.0.0.0
|
||||||
|
network 192.168.1.0/24 area 0.0.0.0
|
||||||
|
network 192.168.2.0/24 area 0.0.0.0
|
||||||
|
passive-interface lo
|
||||||
|
capability opaque
|
||||||
|
mpls-te on
|
||||||
|
mpls-te router-address 192.0.2.2
|
||||||
|
segment-routing on
|
||||||
|
segment-routing global-block 1000 10000 local-block 36000 36999
|
||||||
|
segment-routing node-msd 8
|
||||||
|
segment-routing prefix 192.0.2.2/32 index 22
|
||||||
|
exit
|
||||||
|
!
|
16
tests/topotests/zebra_fec_nexthop_resolution/r2/zebra.conf
Normal file
16
tests/topotests/zebra_fec_nexthop_resolution/r2/zebra.conf
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip address 192.0.2.2/32
|
||||||
|
mpls enable
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r2-eth0
|
||||||
|
ip address 192.168.1.2/24
|
||||||
|
mpls enable
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r2-eth1
|
||||||
|
ip address 192.168.2.2/24
|
||||||
|
mpls enable
|
||||||
|
exit
|
||||||
|
!
|
23
tests/topotests/zebra_fec_nexthop_resolution/r3/bgpd.conf
Normal file
23
tests/topotests/zebra_fec_nexthop_resolution/r3/bgpd.conf
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
router bgp 65500
|
||||||
|
bgp router-id 192.0.2.3
|
||||||
|
neighbor 192.0.2.1 remote-as 65500
|
||||||
|
neighbor 192.0.2.1 update-source lo
|
||||||
|
neighbor 192.0.2.5 remote-as 65500
|
||||||
|
neighbor 192.0.2.5 update-source lo
|
||||||
|
!
|
||||||
|
address-family ipv4 unicast
|
||||||
|
network 192.0.2.3/32
|
||||||
|
no neighbor 192.0.2.1 activate
|
||||||
|
no neighbor 192.0.2.5 activate
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
address-family ipv4 labeled-unicast
|
||||||
|
neighbor 192.0.2.1 activate
|
||||||
|
neighbor 192.0.2.1 route-reflector-client
|
||||||
|
neighbor 192.0.2.1 next-hop-self force
|
||||||
|
neighbor 192.0.2.5 activate
|
||||||
|
neighbor 192.0.2.5 route-reflector-client
|
||||||
|
neighbor 192.0.2.5 next-hop-self force
|
||||||
|
exit-address-family
|
||||||
|
exit
|
||||||
|
!
|
25
tests/topotests/zebra_fec_nexthop_resolution/r3/isisd.conf
Normal file
25
tests/topotests/zebra_fec_nexthop_resolution/r3/isisd.conf
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip router isis 1
|
||||||
|
isis hello-interval 1
|
||||||
|
isis hello-multiplier 3
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r3-eth1
|
||||||
|
ip router isis 1
|
||||||
|
isis hello-interval 1
|
||||||
|
isis hello-multiplier 3
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
router isis 1
|
||||||
|
is-type level-1
|
||||||
|
net 49.0000.0007.e901.3333.00
|
||||||
|
lsp-timers gen-interval 1 refresh-interval 900 max-lifetime 1200
|
||||||
|
mpls-te on
|
||||||
|
mpls-te router-address 192.0.2.3
|
||||||
|
segment-routing on
|
||||||
|
segment-routing global-block 11000 12000 local-block 36000 36999
|
||||||
|
segment-routing node-msd 8
|
||||||
|
segment-routing prefix 192.0.2.3/32 index 33
|
||||||
|
exit
|
||||||
|
!
|
|
@ -0,0 +1,26 @@
|
||||||
|
log stdout
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip ospf network point-to-point
|
||||||
|
ip ospf passive
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r3-eth0
|
||||||
|
ip ospf network point-to-point
|
||||||
|
ip ospf hello-interval 1
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
router ospf
|
||||||
|
ospf router-id 192.0.2.3
|
||||||
|
network 192.0.2.3/32 area 0.0.0.0
|
||||||
|
network 192.168.2.0/24 area 0.0.0.0
|
||||||
|
passive-interface lo
|
||||||
|
capability opaque
|
||||||
|
mpls-te on
|
||||||
|
mpls-te router-address 192.0.2.3
|
||||||
|
segment-routing on
|
||||||
|
segment-routing global-block 1000 10000 local-block 30000 30999
|
||||||
|
segment-routing node-msd 8
|
||||||
|
segment-routing prefix 192.0.2.3/32 index 33
|
||||||
|
exit
|
||||||
|
!
|
19
tests/topotests/zebra_fec_nexthop_resolution/r3/zebra.conf
Normal file
19
tests/topotests/zebra_fec_nexthop_resolution/r3/zebra.conf
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip address 192.0.2.3/32
|
||||||
|
mpls enable
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r3-eth0
|
||||||
|
ip address 192.168.2.3/24
|
||||||
|
mpls enable
|
||||||
|
link-params
|
||||||
|
enable
|
||||||
|
exit-link-params
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r3-eth1
|
||||||
|
ip address 192.168.3.3/24
|
||||||
|
mpls enable
|
||||||
|
exit
|
||||||
|
!
|
24
tests/topotests/zebra_fec_nexthop_resolution/r4/bgpd.conf
Normal file
24
tests/topotests/zebra_fec_nexthop_resolution/r4/bgpd.conf
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
!
|
||||||
|
router bgp 65500
|
||||||
|
bgp router-id 192.0.2.4
|
||||||
|
neighbor 192.0.2.1 remote-as 65500
|
||||||
|
neighbor 192.0.2.1 ttl-security hops 10
|
||||||
|
neighbor 192.0.2.1 disable-connected-check
|
||||||
|
neighbor 192.0.2.1 update-source lo
|
||||||
|
neighbor 192.0.2.3 remote-as 65500
|
||||||
|
neighbor 192.0.2.3 update-source lo
|
||||||
|
!
|
||||||
|
address-family ipv4 unicast
|
||||||
|
network 192.0.2.4/32
|
||||||
|
neighbor 192.0.2.1 activate
|
||||||
|
no neighbor 192.0.2.3 activate
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
address-family ipv4 labeled-unicast
|
||||||
|
neighbor 192.0.2.3 activate
|
||||||
|
neighbor 192.0.2.3 route-reflector-client
|
||||||
|
neighbor 192.0.2.3 next-hop-self force
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
exit
|
||||||
|
!
|
31
tests/topotests/zebra_fec_nexthop_resolution/r4/isisd.conf
Normal file
31
tests/topotests/zebra_fec_nexthop_resolution/r4/isisd.conf
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip router isis 1
|
||||||
|
isis hello-interval 1
|
||||||
|
isis hello-multiplier 3
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r4-eth0
|
||||||
|
ip router isis 1
|
||||||
|
isis hello-interval 1
|
||||||
|
isis hello-multiplier 3
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r4-eth1
|
||||||
|
ip router isis 1
|
||||||
|
isis hello-interval 1
|
||||||
|
isis hello-multiplier 3
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
router isis 1
|
||||||
|
is-type level-1
|
||||||
|
net 49.0000.0007.e901.4444.00
|
||||||
|
lsp-timers gen-interval 1 refresh-interval 900 max-lifetime 1200
|
||||||
|
mpls-te on
|
||||||
|
mpls-te router-address 192.0.2.4
|
||||||
|
segment-routing on
|
||||||
|
segment-routing global-block 11000 12000 local-block 37000 37999
|
||||||
|
segment-routing node-msd 8
|
||||||
|
segment-routing prefix 192.0.2.4/32 index 44
|
||||||
|
exit
|
||||||
|
!
|
19
tests/topotests/zebra_fec_nexthop_resolution/r4/ospfd.conf
Normal file
19
tests/topotests/zebra_fec_nexthop_resolution/r4/ospfd.conf
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip ospf area 0
|
||||||
|
ip ospf passive
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r4-eth0
|
||||||
|
ip ospf area 0
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
router ospf
|
||||||
|
mpls-te on
|
||||||
|
mpls-te router-address 192.0.2.4
|
||||||
|
segment-routing on
|
||||||
|
segment-routing global-block 21000 29000 local-block 31000 31999
|
||||||
|
segment-routing node-msd 8
|
||||||
|
segment-routing prefix 192.0.2.4/32 index 44 no-php-flag
|
||||||
|
exit
|
||||||
|
!
|
16
tests/topotests/zebra_fec_nexthop_resolution/r4/zebra.conf
Normal file
16
tests/topotests/zebra_fec_nexthop_resolution/r4/zebra.conf
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip address 192.0.2.4/32
|
||||||
|
mpls enable
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r4-eth0
|
||||||
|
ip address 192.168.3.4/24
|
||||||
|
mpls enable
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r4-eth1
|
||||||
|
ip address 192.168.4.4/24
|
||||||
|
mpls enable
|
||||||
|
exit
|
||||||
|
!
|
23
tests/topotests/zebra_fec_nexthop_resolution/r5/bgpd.conf
Normal file
23
tests/topotests/zebra_fec_nexthop_resolution/r5/bgpd.conf
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
router bgp 65500
|
||||||
|
bgp router-id 192.0.2.5
|
||||||
|
neighbor 192.0.2.3 remote-as 65500
|
||||||
|
neighbor 192.0.2.3 update-source lo
|
||||||
|
neighbor 192.0.2.7 remote-as 65500
|
||||||
|
neighbor 192.0.2.7 update-source lo
|
||||||
|
!
|
||||||
|
address-family ipv4 unicast
|
||||||
|
network 192.0.2.5/32
|
||||||
|
no neighbor 192.0.2.3 activate
|
||||||
|
no neighbor 192.0.2.7 activate
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
address-family ipv4 labeled-unicast
|
||||||
|
neighbor 192.0.2.3 activate
|
||||||
|
neighbor 192.0.2.3 route-reflector-client
|
||||||
|
neighbor 192.0.2.3 next-hop-self force
|
||||||
|
neighbor 192.0.2.7 activate
|
||||||
|
neighbor 192.0.2.7 route-reflector-client
|
||||||
|
neighbor 192.0.2.7 next-hop-self force
|
||||||
|
exit-address-family
|
||||||
|
exit
|
||||||
|
!
|
26
tests/topotests/zebra_fec_nexthop_resolution/r5/isisd.conf
Normal file
26
tests/topotests/zebra_fec_nexthop_resolution/r5/isisd.conf
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip router isis 1
|
||||||
|
isis hello-interval 1
|
||||||
|
isis hello-multiplier 3
|
||||||
|
isis passive
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r5-eth0
|
||||||
|
ip router isis 1
|
||||||
|
isis hello-interval 1
|
||||||
|
isis hello-multiplier 3
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
router isis 1
|
||||||
|
is-type level-1
|
||||||
|
net 49.0000.0007.e901.5555.00
|
||||||
|
lsp-timers gen-interval 1 refresh-interval 900 max-lifetime 1200
|
||||||
|
mpls-te on
|
||||||
|
mpls-te router-address 192.0.2.5
|
||||||
|
segment-routing on
|
||||||
|
segment-routing global-block 11000 12000 local-block 33000 33999
|
||||||
|
segment-routing node-msd 8
|
||||||
|
segment-routing prefix 192.0.2.5/32 index 55
|
||||||
|
exit
|
||||||
|
!
|
|
@ -0,0 +1,26 @@
|
||||||
|
log stdout
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip ospf network point-to-point
|
||||||
|
ip ospf passive
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r5-eth1
|
||||||
|
ip ospf network point-to-point
|
||||||
|
ip ospf hello-interval 1
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
router ospf
|
||||||
|
ospf router-id 192.0.2.5
|
||||||
|
network 192.0.2.5/32 area 0.0.0.0
|
||||||
|
network 192.168.5.0/24 area 0.0.0.0
|
||||||
|
passive-interface lo
|
||||||
|
capability opaque
|
||||||
|
mpls-te on
|
||||||
|
mpls-te router-address 192.0.2.5
|
||||||
|
segment-routing on
|
||||||
|
segment-routing global-block 21000 22000 local-block 35000 35999
|
||||||
|
segment-routing node-msd 8
|
||||||
|
segment-routing prefix 192.0.2.5/32 index 55
|
||||||
|
exit
|
||||||
|
!
|
19
tests/topotests/zebra_fec_nexthop_resolution/r5/zebra.conf
Normal file
19
tests/topotests/zebra_fec_nexthop_resolution/r5/zebra.conf
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip address 192.0.2.5/32
|
||||||
|
mpls enable
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r5-eth0
|
||||||
|
ip address 192.168.4.5/24
|
||||||
|
mpls enable
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r5-eth1
|
||||||
|
ip address 192.168.5.5/24
|
||||||
|
mpls enable
|
||||||
|
link-params
|
||||||
|
enable
|
||||||
|
exit-link-params
|
||||||
|
exit
|
||||||
|
!
|
|
@ -0,0 +1,32 @@
|
||||||
|
log stdout
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip ospf network point-to-point
|
||||||
|
ip ospf passive
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r6-eth0
|
||||||
|
ip ospf network point-to-point
|
||||||
|
ip ospf hello-interval 1
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r6-eth1
|
||||||
|
ip ospf network point-to-point
|
||||||
|
ip ospf hello-interval 1
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
router ospf
|
||||||
|
ospf router-id 192.0.2.6
|
||||||
|
segment-routing on
|
||||||
|
segment-routing global-block 21000 22000 local-block 38000 38999
|
||||||
|
network 192.0.2.6/32 area 0.0.0.0
|
||||||
|
network 192.168.5.0/24 area 0.0.0.0
|
||||||
|
network 192.168.6.0/24 area 0.0.0.0
|
||||||
|
passive-interface lo
|
||||||
|
capability opaque
|
||||||
|
mpls-te on
|
||||||
|
mpls-te router-address 192.0.2.6
|
||||||
|
segment-routing node-msd 8
|
||||||
|
segment-routing prefix 192.0.2.6/32 index 66
|
||||||
|
exit
|
||||||
|
!
|
22
tests/topotests/zebra_fec_nexthop_resolution/r6/zebra.conf
Normal file
22
tests/topotests/zebra_fec_nexthop_resolution/r6/zebra.conf
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip address 192.0.2.6/32
|
||||||
|
mpls enable
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r6-eth0
|
||||||
|
ip address 192.168.5.6/24
|
||||||
|
mpls enable
|
||||||
|
link-params
|
||||||
|
enable
|
||||||
|
exit-link-params
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r6-eth1
|
||||||
|
ip address 192.168.6.6/24
|
||||||
|
mpls enable
|
||||||
|
link-params
|
||||||
|
enable
|
||||||
|
exit-link-params
|
||||||
|
exit
|
||||||
|
!
|
24
tests/topotests/zebra_fec_nexthop_resolution/r7/bgpd.conf
Normal file
24
tests/topotests/zebra_fec_nexthop_resolution/r7/bgpd.conf
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
!
|
||||||
|
router bgp 65500
|
||||||
|
bgp router-id 192.0.2.7
|
||||||
|
neighbor 192.0.2.1 remote-as 65500
|
||||||
|
neighbor 192.0.2.1 ttl-security hops 10
|
||||||
|
neighbor 192.0.2.1 disable-connected-check
|
||||||
|
neighbor 192.0.2.1 update-source lo
|
||||||
|
neighbor 192.0.2.5 remote-as 65500
|
||||||
|
neighbor 192.0.2.5 update-source lo
|
||||||
|
!
|
||||||
|
address-family ipv4 unicast
|
||||||
|
network 192.0.2.7/32
|
||||||
|
neighbor 192.0.2.1 activate
|
||||||
|
no neighbor 192.0.2.5 activate
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
address-family ipv4 labeled-unicast
|
||||||
|
neighbor 192.0.2.5 activate
|
||||||
|
neighbor 192.0.2.5 route-reflector-client
|
||||||
|
neighbor 192.0.2.5 next-hop-self force
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
exit
|
||||||
|
!
|
|
@ -0,0 +1,26 @@
|
||||||
|
log stdout
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip ospf network point-to-point
|
||||||
|
ip ospf passive
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r7-eth0
|
||||||
|
ip ospf network point-to-point
|
||||||
|
ip ospf hello-interval 1
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
router ospf
|
||||||
|
ospf router-id 192.0.2.7
|
||||||
|
network 192.0.2.7/32 area 0.0.0.0
|
||||||
|
network 192.168.6.0/24 area 0.0.0.0
|
||||||
|
passive-interface lo
|
||||||
|
capability opaque
|
||||||
|
mpls-te on
|
||||||
|
mpls-te router-address 192.0.2.7
|
||||||
|
segment-routing on
|
||||||
|
segment-routing global-block 21000 22000 local-block 31000 31999
|
||||||
|
segment-routing node-msd 8
|
||||||
|
segment-routing prefix 192.0.2.7/32 index 77
|
||||||
|
exit
|
||||||
|
!
|
14
tests/topotests/zebra_fec_nexthop_resolution/r7/zebra.conf
Normal file
14
tests/topotests/zebra_fec_nexthop_resolution/r7/zebra.conf
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip address 192.0.2.7/32
|
||||||
|
mpls enable
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
interface r7-eth0
|
||||||
|
ip address 192.168.6.7/24
|
||||||
|
mpls enable
|
||||||
|
link-params
|
||||||
|
enable
|
||||||
|
exit-link-params
|
||||||
|
exit
|
||||||
|
!
|
|
@ -0,0 +1,259 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2022 6WIND S.A.
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and/or distribute this software
|
||||||
|
# for any purpose with or without fee is hereby granted, provided
|
||||||
|
# that the above copyright notice and this permission notice appear
|
||||||
|
# in all copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
|
||||||
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
|
||||||
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||||
|
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||||
|
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
# OF THIS SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Check if fec nexthop resolution works correctly.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import pytest
|
||||||
|
import functools
|
||||||
|
|
||||||
|
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
sys.path.append(os.path.join(CWD, "../"))
|
||||||
|
|
||||||
|
# pylint: disable=C0413
|
||||||
|
from lib import topotest
|
||||||
|
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||||
|
from lib.common_config import step
|
||||||
|
|
||||||
|
pytestmark = [pytest.mark.bgpd]
|
||||||
|
|
||||||
|
|
||||||
|
def build_topo(tgen):
|
||||||
|
"""
|
||||||
|
r1 ---- r2 ---- r3 ---- r4 ----- r5 ---- r6 ---- r7
|
||||||
|
<--- ospf ----> <---- isis -----> <--- ospf ---->
|
||||||
|
"""
|
||||||
|
for routern in range(1, 8):
|
||||||
|
tgen.add_router("r{}".format(routern))
|
||||||
|
|
||||||
|
switch1 = tgen.add_switch("s1")
|
||||||
|
switch1.add_link(tgen.gears["r1"])
|
||||||
|
switch1.add_link(tgen.gears["r2"])
|
||||||
|
|
||||||
|
switch2 = tgen.add_switch("s2")
|
||||||
|
switch2.add_link(tgen.gears["r2"])
|
||||||
|
switch2.add_link(tgen.gears["r3"])
|
||||||
|
|
||||||
|
switch3 = tgen.add_switch("s3")
|
||||||
|
switch3.add_link(tgen.gears["r3"])
|
||||||
|
switch3.add_link(tgen.gears["r4"])
|
||||||
|
|
||||||
|
switch4 = tgen.add_switch("s4")
|
||||||
|
switch4.add_link(tgen.gears["r4"])
|
||||||
|
switch4.add_link(tgen.gears["r5"])
|
||||||
|
|
||||||
|
switch5 = tgen.add_switch("s5")
|
||||||
|
switch5.add_link(tgen.gears["r5"])
|
||||||
|
switch5.add_link(tgen.gears["r6"])
|
||||||
|
|
||||||
|
switch6 = tgen.add_switch("s6")
|
||||||
|
switch6.add_link(tgen.gears["r6"])
|
||||||
|
switch6.add_link(tgen.gears["r7"])
|
||||||
|
|
||||||
|
|
||||||
|
def setup_module(mod):
|
||||||
|
tgen = Topogen(build_topo, mod.__name__)
|
||||||
|
tgen.start_topology()
|
||||||
|
|
||||||
|
router_list = tgen.routers()
|
||||||
|
|
||||||
|
def _enable_mpls_misc(router):
|
||||||
|
router.run("modprobe mpls_router")
|
||||||
|
router.run("echo 100000 > /proc/sys/net/mpls/platform_labels")
|
||||||
|
router.run("echo 1 > /proc/sys/net/mpls/conf/lo/input")
|
||||||
|
|
||||||
|
router = tgen.gears["r1"]
|
||||||
|
_enable_mpls_misc(router)
|
||||||
|
|
||||||
|
router = tgen.gears["r2"]
|
||||||
|
_enable_mpls_misc(router)
|
||||||
|
|
||||||
|
router = tgen.gears["r3"]
|
||||||
|
_enable_mpls_misc(router)
|
||||||
|
|
||||||
|
router = tgen.gears["r4"]
|
||||||
|
_enable_mpls_misc(router)
|
||||||
|
|
||||||
|
router = tgen.gears["r5"]
|
||||||
|
_enable_mpls_misc(router)
|
||||||
|
|
||||||
|
router = tgen.gears["r6"]
|
||||||
|
_enable_mpls_misc(router)
|
||||||
|
|
||||||
|
router = tgen.gears["r7"]
|
||||||
|
_enable_mpls_misc(router)
|
||||||
|
|
||||||
|
for i, (rname, router) in enumerate(router_list.items(), 1):
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
|
||||||
|
)
|
||||||
|
if rname in ("r1", "r3", "r5", "r7"):
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
|
||||||
|
)
|
||||||
|
if rname in ("r3", "r4", "r5"):
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
|
||||||
|
)
|
||||||
|
if rname in ("r1", "r2", "r3", "r5", "r6", "r7"):
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
|
||||||
|
)
|
||||||
|
|
||||||
|
tgen.start_router()
|
||||||
|
|
||||||
|
|
||||||
|
def teardown_module(mod):
|
||||||
|
tgen = get_topogen()
|
||||||
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
|
||||||
|
# There are some startup issued when initialising OSPF
|
||||||
|
# To avoid those issues, load the ospf configuration after zebra started
|
||||||
|
def test_zebra_fec_nexthop_resolution_finalise_ospf_config():
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
topotest.sleep(2)
|
||||||
|
|
||||||
|
tgen.net["r1"].cmd("vtysh -f {}/r1/ospfd.conf.after".format(CWD))
|
||||||
|
tgen.net["r2"].cmd("vtysh -f {}/r2/ospfd.conf.after".format(CWD))
|
||||||
|
tgen.net["r3"].cmd("vtysh -f {}/r3/ospfd.conf.after".format(CWD))
|
||||||
|
tgen.net["r5"].cmd("vtysh -f {}/r5/ospfd.conf.after".format(CWD))
|
||||||
|
tgen.net["r6"].cmd("vtysh -f {}/r6/ospfd.conf.after".format(CWD))
|
||||||
|
tgen.net["r7"].cmd("vtysh -f {}/r7/ospfd.conf.after".format(CWD))
|
||||||
|
|
||||||
|
|
||||||
|
def test_zebra_fec_nexthop_resolution_bgp():
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
def _check_bgp_session():
|
||||||
|
r1 = tgen.gears["r1"]
|
||||||
|
|
||||||
|
tgen.gears["r3"].vtysh_cmd("config \n no mpls fec nexthop-resolution \n end")
|
||||||
|
tgen.gears["r3"].vtysh_cmd("config \n mpls fec nexthop-resolution \n end")
|
||||||
|
tgen.gears["r5"].vtysh_cmd("config \n no mpls fec nexthop-resolution \n end")
|
||||||
|
tgen.gears["r5"].vtysh_cmd("config \n mpls fec nexthop-resolution \n end")
|
||||||
|
output = json.loads(r1.vtysh_cmd("show bgp summary json"))
|
||||||
|
|
||||||
|
if output["ipv4Unicast"]["peers"]["192.0.2.7"]["state"] == "Established":
|
||||||
|
return None
|
||||||
|
return False
|
||||||
|
|
||||||
|
test_func1 = functools.partial(_check_bgp_session)
|
||||||
|
_, result1 = topotest.run_and_expect(test_func1, None, count=60, wait=0.5)
|
||||||
|
assert result1 is None, "Failed to verify the fec_nexthop_resolution: bgp session"
|
||||||
|
|
||||||
|
|
||||||
|
def test_zebra_fec_nexthop_resolution_ping():
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
def _check_ping_launch():
|
||||||
|
r1 = tgen.gears["r1"]
|
||||||
|
|
||||||
|
ping_launch = "ping 192.0.2.7 -I 192.0.2.1 -c 1"
|
||||||
|
selected_lines = r1.run(ping_launch).splitlines()[-2:-1]
|
||||||
|
rtx_stats = "".join(selected_lines[0].split(",")[0:3])
|
||||||
|
current = topotest.normalize_text(rtx_stats)
|
||||||
|
|
||||||
|
expected_stats = "1 packets transmitted 1 received 0% packet loss"
|
||||||
|
expected = topotest.normalize_text(expected_stats)
|
||||||
|
|
||||||
|
if current == expected:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
test_func2 = functools.partial(_check_ping_launch)
|
||||||
|
_, result2 = topotest.run_and_expect(test_func2, None, count=60, wait=1)
|
||||||
|
assert result2 is None, "Failed to verify the fec_nexthop_resolution: ping"
|
||||||
|
|
||||||
|
|
||||||
|
def test_zebra_fec_nexthop_resolution_table():
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
def _zebra_check_mpls_table():
|
||||||
|
r3 = tgen.gears["r3"]
|
||||||
|
inLabel = 0
|
||||||
|
outLabels = 0
|
||||||
|
|
||||||
|
"""
|
||||||
|
Retrieve inLabel from MPLS FEC table
|
||||||
|
"""
|
||||||
|
mpls_fec = r3.vtysh_cmd("show mpls fec 192.0.2.7/32")
|
||||||
|
lines = mpls_fec.split("\n")
|
||||||
|
for line in lines:
|
||||||
|
if "Label" in line:
|
||||||
|
inLabel = line.split(": ", 1)[1]
|
||||||
|
|
||||||
|
"""
|
||||||
|
Retrieve outLabel from BGP
|
||||||
|
"""
|
||||||
|
output = json.loads(r3.vtysh_cmd("show ip route 192.0.2.7/32 json"))
|
||||||
|
|
||||||
|
outLabels = output["192.0.2.7/32"][0]["nexthops"][1]["labels"]
|
||||||
|
|
||||||
|
if (inLabel == 0) or (outLabels == 0):
|
||||||
|
return True
|
||||||
|
|
||||||
|
"""
|
||||||
|
Compare expected data with real data
|
||||||
|
"""
|
||||||
|
output = json.loads(r3.vtysh_cmd("show mpls table " + str(inLabel) + " json"))
|
||||||
|
|
||||||
|
expected = {
|
||||||
|
"inLabel": int(inLabel),
|
||||||
|
"installed": True,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"type": "BGP",
|
||||||
|
"outLabel": outLabels[0],
|
||||||
|
"outLabelStack": outLabels,
|
||||||
|
"distance": 20,
|
||||||
|
"installed": True,
|
||||||
|
"nexthop": "192.168.3.4",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
return topotest.json_cmp(output, expected)
|
||||||
|
|
||||||
|
test_func3 = functools.partial(_zebra_check_mpls_table)
|
||||||
|
_, result3 = topotest.run_and_expect(test_func3, None, count=60, wait=0.5)
|
||||||
|
assert result3 is None, "Failed to verify the fec_nexthop_resolution: mpls table"
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = ["-s"] + sys.argv[1:]
|
||||||
|
sys.exit(pytest.main(args))
|
|
@ -2856,6 +2856,16 @@ module frr-zebra {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
container mpls {
|
||||||
|
description
|
||||||
|
"MPLS Configuration.";
|
||||||
|
leaf fec-nexthop-resolution {
|
||||||
|
type boolean;
|
||||||
|
description
|
||||||
|
"Authorise nexthop resolution over all labeled routes.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uses ribs;
|
uses ribs;
|
||||||
|
|
||||||
uses vrf-vni-mapping;
|
uses vrf-vni-mapping;
|
||||||
|
|
|
@ -108,8 +108,8 @@ struct route_entry {
|
||||||
uint32_t nexthop_mtu;
|
uint32_t nexthop_mtu;
|
||||||
|
|
||||||
/* Flags of this route.
|
/* Flags of this route.
|
||||||
* This flag's definition is in lib/zebra.h ZEBRA_FLAG_* and is exposed
|
* This flag's definition is in lib/zclient.h ZEBRA_FLAG_* and is
|
||||||
* to clients via Zserv
|
* exposed to clients via Zserv
|
||||||
*/
|
*/
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
|
||||||
|
|
|
@ -2221,6 +2221,37 @@ static void lib_vrf_zebra_ipv6_resolve_via_default_cli_write(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFPY_YANG (mpls_fec_nexthop_resolution, mpls_fec_nexthop_resolution_cmd,
|
||||||
|
"[no$no] mpls fec nexthop-resolution",
|
||||||
|
NO_STR
|
||||||
|
MPLS_STR
|
||||||
|
"MPLS FEC table\n"
|
||||||
|
"Authorise nexthop resolution over all labeled routes.\n")
|
||||||
|
{
|
||||||
|
nb_cli_enqueue_change(vty,
|
||||||
|
"./frr-zebra:zebra/mpls/fec-nexthop-resolution",
|
||||||
|
NB_OP_MODIFY, no ? "false" : "true");
|
||||||
|
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
|
return nb_cli_apply_changes(vty, "/frr-vrf:lib/vrf[name='%s']",
|
||||||
|
VRF_DEFAULT_NAME);
|
||||||
|
|
||||||
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lib_vrf_mpls_fec_nexthop_resolution_cli_write(
|
||||||
|
struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
|
||||||
|
{
|
||||||
|
bool fec_nexthop_resolution = yang_dnode_get_bool(dnode, NULL);
|
||||||
|
|
||||||
|
if (fec_nexthop_resolution || show_defaults) {
|
||||||
|
zebra_vrf_indent_cli_write(vty, dnode);
|
||||||
|
|
||||||
|
vty_out(vty, "%smpls fec nexthop-resolution\n",
|
||||||
|
fec_nexthop_resolution ? "" : "no ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DEFPY_YANG (vrf_netns,
|
DEFPY_YANG (vrf_netns,
|
||||||
vrf_netns_cmd,
|
vrf_netns_cmd,
|
||||||
"[no] netns ![NAME$netns_name]",
|
"[no] netns ![NAME$netns_name]",
|
||||||
|
@ -2851,6 +2882,10 @@ const struct frr_yang_module_info frr_zebra_cli_info = {
|
||||||
.xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/netns/table-range",
|
.xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/netns/table-range",
|
||||||
.cbs.cli_show = lib_vrf_zebra_netns_table_range_cli_write,
|
.cbs.cli_show = lib_vrf_zebra_netns_table_range_cli_write,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/mpls/fec-nexthop-resolution",
|
||||||
|
.cbs.cli_show = lib_vrf_mpls_fec_nexthop_resolution_cli_write,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id",
|
.xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id",
|
||||||
.cbs.cli_show = lib_vrf_zebra_l3vni_id_cli_write,
|
.cbs.cli_show = lib_vrf_zebra_l3vni_id_cli_write,
|
||||||
|
@ -2957,6 +2992,9 @@ void zebra_cli_init(void)
|
||||||
install_element(VRF_NODE, &ip_nht_default_route_cmd);
|
install_element(VRF_NODE, &ip_nht_default_route_cmd);
|
||||||
install_element(VRF_NODE, &ipv6_nht_default_route_cmd);
|
install_element(VRF_NODE, &ipv6_nht_default_route_cmd);
|
||||||
|
|
||||||
|
install_element(CONFIG_NODE, &mpls_fec_nexthop_resolution_cmd);
|
||||||
|
install_element(VRF_NODE, &mpls_fec_nexthop_resolution_cmd);
|
||||||
|
|
||||||
install_element(CONFIG_NODE, &vni_mapping_cmd);
|
install_element(CONFIG_NODE, &vni_mapping_cmd);
|
||||||
install_element(VRF_NODE, &vni_mapping_cmd);
|
install_element(VRF_NODE, &vni_mapping_cmd);
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object");
|
DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object");
|
||||||
DEFINE_MTYPE_STATIC(ZEBRA, FEC, "MPLS FEC object");
|
DEFINE_MTYPE_STATIC(ZEBRA, FEC, "MPLS FEC object");
|
||||||
DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object");
|
DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object");
|
||||||
|
DEFINE_MTYPE_STATIC(ZEBRA, NH_LABEL, "Nexthop label");
|
||||||
|
|
||||||
bool mpls_enabled;
|
bool mpls_enabled;
|
||||||
bool mpls_pw_reach_strict; /* Strict reachability checking */
|
bool mpls_pw_reach_strict; /* Strict reachability checking */
|
||||||
|
@ -50,7 +51,7 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
|
||||||
struct route_node *rn, struct route_entry *re);
|
struct route_node *rn, struct route_entry *re);
|
||||||
static int lsp_uninstall(struct zebra_vrf *zvrf, mpls_label_t label);
|
static int lsp_uninstall(struct zebra_vrf *zvrf, mpls_label_t label);
|
||||||
static int fec_change_update_lsp(struct zebra_vrf *zvrf, struct zebra_fec *fec,
|
static int fec_change_update_lsp(struct zebra_vrf *zvrf, struct zebra_fec *fec,
|
||||||
mpls_label_t old_label);
|
mpls_label_t old_label, bool uninstall);
|
||||||
static int fec_send(struct zebra_fec *fec, struct zserv *client);
|
static int fec_send(struct zebra_fec *fec, struct zserv *client);
|
||||||
static void fec_update_clients(struct zebra_fec *fec);
|
static void fec_update_clients(struct zebra_fec *fec);
|
||||||
static void fec_print(struct zebra_fec *fec, struct vty *vty);
|
static void fec_print(struct zebra_fec *fec, struct vty *vty);
|
||||||
|
@ -161,12 +162,14 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
|
||||||
enum lsp_types_t lsp_type;
|
enum lsp_types_t lsp_type;
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
int added, changed;
|
int added, changed;
|
||||||
|
bool zvrf_nexthop_resolution;
|
||||||
|
|
||||||
/* Lookup table. */
|
/* Lookup table. */
|
||||||
lsp_table = zvrf->lsp_table;
|
lsp_table = zvrf->lsp_table;
|
||||||
if (!lsp_table)
|
if (!lsp_table)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
zvrf_nexthop_resolution = zvrf->zebra_mpls_fec_nexthop_resolution;
|
||||||
lsp_type = lsp_type_from_re_type(re->type);
|
lsp_type = lsp_type_from_re_type(re->type);
|
||||||
added = changed = 0;
|
added = changed = 0;
|
||||||
|
|
||||||
|
@ -180,13 +183,20 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
|
||||||
* the label advertised by the recursive nexthop (plus we don't have the
|
* the label advertised by the recursive nexthop (plus we don't have the
|
||||||
* logic yet to push multiple labels).
|
* logic yet to push multiple labels).
|
||||||
*/
|
*/
|
||||||
for (nexthop = re->nhe->nhg.nexthop;
|
nexthop = re->nhe->nhg.nexthop;
|
||||||
nexthop; nexthop = nexthop->next) {
|
while (nexthop) {
|
||||||
/* Skip inactive and recursive entries. */
|
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) {
|
||||||
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|
nexthop =
|
||||||
|
nexthop_next_resolution(nexthop,
|
||||||
|
zvrf_nexthop_resolution);
|
||||||
continue;
|
continue;
|
||||||
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
|
}
|
||||||
|
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) {
|
||||||
|
nexthop =
|
||||||
|
nexthop_next_resolution(nexthop,
|
||||||
|
zvrf_nexthop_resolution);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
nhlfe = nhlfe_find(&lsp->nhlfe_list, lsp_type,
|
nhlfe = nhlfe_find(&lsp->nhlfe_list, lsp_type,
|
||||||
nexthop->type, &nexthop->gate,
|
nexthop->type, &nexthop->gate,
|
||||||
|
@ -194,9 +204,13 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
|
||||||
if (nhlfe) {
|
if (nhlfe) {
|
||||||
/* Clear deleted flag (in case it was set) */
|
/* Clear deleted flag (in case it was set) */
|
||||||
UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED);
|
UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED);
|
||||||
if (nexthop_labels_match(nhlfe->nexthop, nexthop))
|
if (nexthop_labels_match(nhlfe->nexthop, nexthop)) {
|
||||||
/* No change */
|
/* No change */
|
||||||
|
nexthop =
|
||||||
|
nexthop_next_resolution(nexthop,
|
||||||
|
zvrf_nexthop_resolution);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_MPLS) {
|
if (IS_ZEBRA_DEBUG_MPLS) {
|
||||||
|
@ -221,11 +235,18 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_MPLS) {
|
if (IS_ZEBRA_DEBUG_MPLS) {
|
||||||
|
char label_str[MPLS_LABEL_STRLEN];
|
||||||
|
|
||||||
nhlfe2str(nhlfe, buf, BUFSIZ);
|
nhlfe2str(nhlfe, buf, BUFSIZ);
|
||||||
zlog_debug(
|
zlog_debug("Add LSP in-label %u type %d nexthop %s out-label %s",
|
||||||
"Add LSP in-label %u type %d nexthop %s out-label %u",
|
lsp->ile.in_label, lsp_type, buf,
|
||||||
lsp->ile.in_label, lsp_type, buf,
|
mpls_label2str(nexthop->nh_label
|
||||||
nexthop->nh_label->label[0]);
|
->num_labels,
|
||||||
|
nexthop->nh_label->label,
|
||||||
|
label_str,
|
||||||
|
sizeof(label_str),
|
||||||
|
nexthop->nh_label_type,
|
||||||
|
0));
|
||||||
}
|
}
|
||||||
|
|
||||||
lsp->addr_family = NHLFE_FAMILY(nhlfe);
|
lsp->addr_family = NHLFE_FAMILY(nhlfe);
|
||||||
|
@ -234,6 +255,8 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
|
||||||
SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED);
|
SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED);
|
||||||
added++;
|
added++;
|
||||||
}
|
}
|
||||||
|
nexthop = nexthop_next_resolution(nexthop,
|
||||||
|
zvrf_nexthop_resolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Queue LSP for processing if necessary. If no NHLFE got added (special
|
/* Queue LSP for processing if necessary. If no NHLFE got added (special
|
||||||
|
@ -245,6 +268,8 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
lsp_check_free(lsp_table, &lsp);
|
lsp_check_free(lsp_table, &lsp);
|
||||||
|
/* failed to install a new LSP */
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -353,7 +378,7 @@ static void fec_evaluate(struct zebra_vrf *zvrf)
|
||||||
fec_update_clients(fec);
|
fec_update_clients(fec);
|
||||||
|
|
||||||
/* Update label forwarding entries appropriately */
|
/* Update label forwarding entries appropriately */
|
||||||
fec_change_update_lsp(zvrf, fec, old_label);
|
fec_change_update_lsp(zvrf, fec, old_label, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,7 +409,7 @@ static uint32_t fec_derive_label_from_index(struct zebra_vrf *zvrf,
|
||||||
* entries, as appropriate.
|
* entries, as appropriate.
|
||||||
*/
|
*/
|
||||||
static int fec_change_update_lsp(struct zebra_vrf *zvrf, struct zebra_fec *fec,
|
static int fec_change_update_lsp(struct zebra_vrf *zvrf, struct zebra_fec *fec,
|
||||||
mpls_label_t old_label)
|
mpls_label_t old_label, bool uninstall)
|
||||||
{
|
{
|
||||||
struct route_table *table;
|
struct route_table *table;
|
||||||
struct route_node *rn;
|
struct route_node *rn;
|
||||||
|
@ -416,11 +441,17 @@ static int fec_change_update_lsp(struct zebra_vrf *zvrf, struct zebra_fec *fec,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!re || !zebra_rib_labeled_unicast(re))
|
if (!re || !zebra_rib_labeled_unicast(re)) {
|
||||||
|
if (uninstall)
|
||||||
|
lsp_uninstall(zvrf, fec->label);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (lsp_install(zvrf, fec->label, rn, re))
|
if (lsp_install(zvrf, fec->label, rn, re)) {
|
||||||
|
if (uninstall)
|
||||||
|
lsp_uninstall(zvrf, fec->label);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -447,6 +478,30 @@ static int fec_send(struct zebra_fec *fec, struct zserv *client)
|
||||||
return zserv_send_message(client, s);
|
return zserv_send_message(client, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Upon reconfiguring nexthop-resolution updates, update the
|
||||||
|
* lsp entries accordingly.
|
||||||
|
*/
|
||||||
|
void zebra_mpls_fec_nexthop_resolution_update(struct zebra_vrf *zvrf)
|
||||||
|
{
|
||||||
|
int af;
|
||||||
|
struct route_node *rn;
|
||||||
|
struct zebra_fec *fec;
|
||||||
|
|
||||||
|
for (af = AFI_IP; af < AFI_MAX; af++) {
|
||||||
|
if (zvrf->fec_table[af] == NULL)
|
||||||
|
continue;
|
||||||
|
for (rn = route_top(zvrf->fec_table[af]); rn;
|
||||||
|
rn = route_next(rn)) {
|
||||||
|
if (!rn->info)
|
||||||
|
continue;
|
||||||
|
fec = rn->info;
|
||||||
|
fec_change_update_lsp(zvrf, fec, MPLS_INVALID_LABEL,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update all registered clients about this FEC. Caller should've updated
|
* Update all registered clients about this FEC. Caller should've updated
|
||||||
* FEC and ensure no duplicate updates.
|
* FEC and ensure no duplicate updates.
|
||||||
|
@ -1398,7 +1453,31 @@ static int nhlfe_del(struct zebra_nhlfe *nhlfe)
|
||||||
static void nhlfe_out_label_update(struct zebra_nhlfe *nhlfe,
|
static void nhlfe_out_label_update(struct zebra_nhlfe *nhlfe,
|
||||||
struct mpls_label_stack *nh_label)
|
struct mpls_label_stack *nh_label)
|
||||||
{
|
{
|
||||||
nhlfe->nexthop->nh_label->label[0] = nh_label->label[0];
|
struct mpls_label_stack *nh_label_tmp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Enforce limit on label stack size */
|
||||||
|
if (nh_label->num_labels > MPLS_MAX_LABELS)
|
||||||
|
nh_label->num_labels = MPLS_MAX_LABELS;
|
||||||
|
|
||||||
|
/* Resize the array to accommodate the new label stack */
|
||||||
|
if (nh_label->num_labels > nhlfe->nexthop->nh_label->num_labels) {
|
||||||
|
nh_label_tmp = XREALLOC(MTYPE_NH_LABEL, nhlfe->nexthop->nh_label,
|
||||||
|
sizeof(struct mpls_label_stack) +
|
||||||
|
nh_label->num_labels *
|
||||||
|
sizeof(mpls_label_t));
|
||||||
|
if (nh_label_tmp) {
|
||||||
|
nhlfe->nexthop->nh_label = nh_label_tmp;
|
||||||
|
nhlfe->nexthop->nh_label->num_labels =
|
||||||
|
nh_label->num_labels;
|
||||||
|
} else
|
||||||
|
nh_label->num_labels =
|
||||||
|
nhlfe->nexthop->nh_label->num_labels;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the label stack into the array */
|
||||||
|
for (i = 0; i < nh_label->num_labels; i++)
|
||||||
|
nhlfe->nexthop->nh_label->label[i] = nh_label->label[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mpls_lsp_uninstall_all(struct hash *lsp_table, struct zebra_lsp *lsp,
|
static int mpls_lsp_uninstall_all(struct hash *lsp_table, struct zebra_lsp *lsp,
|
||||||
|
@ -2117,7 +2196,7 @@ void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx)
|
||||||
/*
|
/*
|
||||||
* Install dynamic LSP entry.
|
* Install dynamic LSP entry.
|
||||||
*/
|
*/
|
||||||
int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn,
|
void zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn,
|
||||||
struct route_entry *re)
|
struct route_entry *re)
|
||||||
{
|
{
|
||||||
struct route_table *table;
|
struct route_table *table;
|
||||||
|
@ -2125,23 +2204,20 @@ int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn,
|
||||||
|
|
||||||
table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))];
|
table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))];
|
||||||
if (!table)
|
if (!table)
|
||||||
return -1;
|
return;
|
||||||
|
|
||||||
/* See if there is a configured label binding for this FEC. */
|
/* See if there is a configured label binding for this FEC. */
|
||||||
fec = fec_find(table, &rn->p);
|
fec = fec_find(table, &rn->p);
|
||||||
if (!fec || fec->label == MPLS_INVALID_LABEL)
|
if (!fec || fec->label == MPLS_INVALID_LABEL)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
/* We cannot install a label forwarding entry if local label is the
|
/* We cannot install a label forwarding entry if local label is the
|
||||||
* implicit-null label.
|
* implicit-null label.
|
||||||
*/
|
*/
|
||||||
if (fec->label == MPLS_LABEL_IMPLICIT_NULL)
|
if (fec->label == MPLS_LABEL_IMPLICIT_NULL)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
if (lsp_install(zvrf, fec->label, rn, re))
|
lsp_install(zvrf, fec->label, rn, re);
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2345,7 +2421,7 @@ int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_client || label_change)
|
if (new_client || label_change)
|
||||||
return fec_change_update_lsp(zvrf, fec, old_label);
|
return fec_change_update_lsp(zvrf, fec, old_label, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2386,7 +2462,7 @@ int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p,
|
||||||
list_isempty(fec->client_list)) {
|
list_isempty(fec->client_list)) {
|
||||||
mpls_label_t old_label = fec->label;
|
mpls_label_t old_label = fec->label;
|
||||||
fec->label = MPLS_INVALID_LABEL; /* reset */
|
fec->label = MPLS_INVALID_LABEL; /* reset */
|
||||||
fec_change_update_lsp(zvrf, fec, old_label);
|
fec_change_update_lsp(zvrf, fec, old_label, false);
|
||||||
fec_del(fec);
|
fec_del(fec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2556,7 +2632,7 @@ int zebra_mpls_static_fec_add(struct zebra_vrf *zvrf, struct prefix *p,
|
||||||
fec_update_clients(fec);
|
fec_update_clients(fec);
|
||||||
|
|
||||||
/* Update label forwarding entries appropriately */
|
/* Update label forwarding entries appropriately */
|
||||||
ret = fec_change_update_lsp(zvrf, fec, old_label);
|
ret = fec_change_update_lsp(zvrf, fec, old_label, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2609,7 +2685,7 @@ int zebra_mpls_static_fec_del(struct zebra_vrf *zvrf, struct prefix *p)
|
||||||
fec_update_clients(fec);
|
fec_update_clients(fec);
|
||||||
|
|
||||||
/* Update label forwarding entries appropriately */
|
/* Update label forwarding entries appropriately */
|
||||||
return fec_change_update_lsp(zvrf, fec, old_label);
|
return fec_change_update_lsp(zvrf, fec, old_label, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -146,7 +146,7 @@ int zebra_mpls_write_label_block_config(struct vty *vty, struct zebra_vrf *vrf);
|
||||||
/*
|
/*
|
||||||
* Install dynamic LSP entry.
|
* Install dynamic LSP entry.
|
||||||
*/
|
*/
|
||||||
int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn,
|
void zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn,
|
||||||
struct route_entry *re);
|
struct route_entry *re);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -256,6 +256,12 @@ void mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
|
||||||
void zebra_mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
|
void zebra_mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
|
||||||
const struct zapi_labels *zl);
|
const struct zapi_labels *zl);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Upon reconfiguring nexthop-resolution updates, update the
|
||||||
|
* lsp entries accordingly.
|
||||||
|
*/
|
||||||
|
void zebra_mpls_fec_nexthop_resolution_update(struct zebra_vrf *zvrf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Uninstall all NHLFEs bound to a single FEC.
|
* Uninstall all NHLFEs bound to a single FEC.
|
||||||
*
|
*
|
||||||
|
|
|
@ -883,6 +883,13 @@ const struct frr_yang_module_info frr_zebra_info = {
|
||||||
.modify = lib_vrf_zebra_netns_table_range_end_modify,
|
.modify = lib_vrf_zebra_netns_table_range_end_modify,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/mpls/fec-nexthop-resolution",
|
||||||
|
.cbs = {
|
||||||
|
.modify = lib_vrf_zebra_mpls_fec_nexthop_resolution_modify,
|
||||||
|
.destroy = lib_vrf_zebra_mpls_fec_nexthop_resolution_destroy,
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib",
|
.xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib",
|
||||||
.cbs = {
|
.cbs = {
|
||||||
|
|
|
@ -309,6 +309,10 @@ int lib_vrf_zebra_netns_table_range_create(struct nb_cb_create_args *args);
|
||||||
int lib_vrf_zebra_netns_table_range_destroy(struct nb_cb_destroy_args *args);
|
int lib_vrf_zebra_netns_table_range_destroy(struct nb_cb_destroy_args *args);
|
||||||
int lib_vrf_zebra_netns_table_range_start_modify(struct nb_cb_modify_args *args);
|
int lib_vrf_zebra_netns_table_range_start_modify(struct nb_cb_modify_args *args);
|
||||||
int lib_vrf_zebra_netns_table_range_end_modify(struct nb_cb_modify_args *args);
|
int lib_vrf_zebra_netns_table_range_end_modify(struct nb_cb_modify_args *args);
|
||||||
|
int lib_vrf_zebra_mpls_fec_nexthop_resolution_modify(
|
||||||
|
struct nb_cb_modify_args *args);
|
||||||
|
int lib_vrf_zebra_mpls_fec_nexthop_resolution_destroy(
|
||||||
|
struct nb_cb_destroy_args *args);
|
||||||
const void *lib_vrf_zebra_ribs_rib_get_next(struct nb_cb_get_next_args *args);
|
const void *lib_vrf_zebra_ribs_rib_get_next(struct nb_cb_get_next_args *args);
|
||||||
int lib_vrf_zebra_ribs_rib_get_keys(struct nb_cb_get_keys_args *args);
|
int lib_vrf_zebra_ribs_rib_get_keys(struct nb_cb_get_keys_args *args);
|
||||||
const void *
|
const void *
|
||||||
|
|
|
@ -3780,6 +3780,59 @@ int lib_vrf_zebra_netns_table_range_end_modify(struct nb_cb_modify_args *args)
|
||||||
return NB_OK;
|
return NB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/mpls/fec-nexthop-resolution
|
||||||
|
*/
|
||||||
|
int lib_vrf_zebra_mpls_fec_nexthop_resolution_modify(
|
||||||
|
struct nb_cb_modify_args *args)
|
||||||
|
{
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct zebra_vrf *zvrf;
|
||||||
|
bool fec_nexthop_resolution;
|
||||||
|
|
||||||
|
if (args->event != NB_EV_APPLY)
|
||||||
|
return NB_OK;
|
||||||
|
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
zvrf = vrf->info;
|
||||||
|
|
||||||
|
fec_nexthop_resolution = yang_dnode_get_bool(args->dnode, NULL);
|
||||||
|
|
||||||
|
if (zvrf->zebra_mpls_fec_nexthop_resolution == fec_nexthop_resolution)
|
||||||
|
return NB_OK;
|
||||||
|
|
||||||
|
zvrf->zebra_mpls_fec_nexthop_resolution = fec_nexthop_resolution;
|
||||||
|
|
||||||
|
zebra_mpls_fec_nexthop_resolution_update(zvrf);
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lib_vrf_zebra_mpls_fec_nexthop_resolution_destroy(
|
||||||
|
struct nb_cb_destroy_args *args)
|
||||||
|
{
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct zebra_vrf *zvrf;
|
||||||
|
bool fec_nexthop_resolution;
|
||||||
|
|
||||||
|
if (args->event != NB_EV_APPLY)
|
||||||
|
return NB_OK;
|
||||||
|
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
zvrf = vrf->info;
|
||||||
|
|
||||||
|
fec_nexthop_resolution = DFLT_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT;
|
||||||
|
|
||||||
|
if (zvrf->zebra_mpls_fec_nexthop_resolution == fec_nexthop_resolution)
|
||||||
|
return NB_OK;
|
||||||
|
|
||||||
|
zvrf->zebra_mpls_fec_nexthop_resolution = fec_nexthop_resolution;
|
||||||
|
|
||||||
|
zebra_mpls_fec_nexthop_resolution_update(zvrf);
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id
|
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -651,8 +651,10 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
|
||||||
int zebra_rib_labeled_unicast(struct route_entry *re)
|
int zebra_rib_labeled_unicast(struct route_entry *re)
|
||||||
{
|
{
|
||||||
struct nexthop *nexthop = NULL;
|
struct nexthop *nexthop = NULL;
|
||||||
|
struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
|
||||||
|
|
||||||
if (re->type != ZEBRA_ROUTE_BGP)
|
if ((re->type != ZEBRA_ROUTE_BGP) &&
|
||||||
|
!zvrf->zebra_mpls_fec_nexthop_resolution)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
|
for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
|
||||||
|
|
|
@ -173,6 +173,7 @@ struct zebra_vrf {
|
||||||
|
|
||||||
bool zebra_rnh_ip_default_route;
|
bool zebra_rnh_ip_default_route;
|
||||||
bool zebra_rnh_ipv6_default_route;
|
bool zebra_rnh_ipv6_default_route;
|
||||||
|
bool zebra_mpls_fec_nexthop_resolution;
|
||||||
};
|
};
|
||||||
#define PROTO_RM_NAME(zvrf, afi, rtype) zvrf->proto_rm[afi][rtype].name
|
#define PROTO_RM_NAME(zvrf, afi, rtype) zvrf->proto_rm[afi][rtype].name
|
||||||
#define NHT_RM_NAME(zvrf, afi, rtype) zvrf->nht_rm[afi][rtype].name
|
#define NHT_RM_NAME(zvrf, afi, rtype) zvrf->nht_rm[afi][rtype].name
|
||||||
|
|
Loading…
Reference in a new issue