*: Introduce Local Host Routes to FRR

Create Local routes in FRR:

S   0.0.0.0/0 [1/0] via 192.168.119.1, enp39s0, weight 1, 00:03:46
K>* 0.0.0.0/0 [0/100] via 192.168.119.1, enp39s0, 00:03:51
O   192.168.119.0/24 [110/100] is directly connected, enp39s0, weight 1, 00:03:46
C>* 192.168.119.0/24 is directly connected, enp39s0, 00:03:51
L>* 192.168.119.224/32 is directly connected, enp39s0, 00:03:51
O   192.168.119.229/32 [110/100] via 0.0.0.0, enp39s0 inactive, weight 1, 00:03:46
C>* 192.168.119.229/32 is directly connected, enp39s0, 00:03:46

Create ability to redistribute local routes.

Modify tests to support this change.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
This commit is contained in:
Donald Sharp 2023-01-04 18:32:43 -05:00
parent 8e3a96e846
commit d4aa24ba7d
42 changed files with 263 additions and 87 deletions

View File

@ -547,6 +547,8 @@ int proto_redistnum(int afi, const char *s)
return ZEBRA_ROUTE_KERNEL;
else if (strmatch(s, "connected"))
return ZEBRA_ROUTE_CONNECT;
else if (strmatch(s, "local"))
return ZEBRA_ROUTE_LOCAL;
else if (strmatch(s, "static"))
return ZEBRA_ROUTE_STATIC;
else if (strmatch(s, "rip"))
@ -581,6 +583,8 @@ int proto_redistnum(int afi, const char *s)
return ZEBRA_ROUTE_KERNEL;
else if (strmatch(s, "connected"))
return ZEBRA_ROUTE_CONNECT;
else if (strmatch(s, "local"))
return ZEBRA_ROUTE_LOCAL;
else if (strmatch(s, "static"))
return ZEBRA_ROUTE_STATIC;
else if (strmatch(s, "ripng"))

View File

@ -49,6 +49,7 @@
ZEBRA_ROUTE_SYSTEM, system, NULL, 'X', 0, 0, 0, "Reserved", none
ZEBRA_ROUTE_KERNEL, kernel, zebra, 'K', 1, 1, 1, "kernel route", zebra
ZEBRA_ROUTE_CONNECT, connected, zebra, 'C', 1, 1, 1, "connected", zebra
ZEBRA_ROUTE_LOCAL, local, zebra, 'L', 1, 1, 1, "local", zebra
ZEBRA_ROUTE_STATIC, static, zebra, 'S', 1, 1, 1, "static", zebra
ZEBRA_ROUTE_RIP, rip, ripd, 'R', 1, 0, 1, "RIP", ripd
ZEBRA_ROUTE_RIPNG, ripng, ripngd, 'R', 0, 1, 1, "RIPng", ripngd
@ -94,6 +95,7 @@ ZEBRA_ROUTE_ALL, wildcard, none, '-', 0, 0, 0, "-", no
ZEBRA_ROUTE_SYSTEM, "Reserved route type, for internal use only"
ZEBRA_ROUTE_KERNEL, "Kernel routes (not installed via the zebra RIB)"
ZEBRA_ROUTE_CONNECT,"Connected routes (directly attached subnet or host)"
ZEBRA_ROUTE_LOCAL, "Local routes (directly attached host route)"
ZEBRA_ROUTE_STATIC, "Statically configured routes"
ZEBRA_ROUTE_RIP, "Routing Information Protocol (RIP)"
ZEBRA_ROUTE_RIPNG, "Routing Information Protocol next-generation (IPv6) (RIPng)"

View File

@ -865,7 +865,7 @@ int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in,
((uint32_t)250000000) /* Bottom 28 bits then rounded down */
#define ZEBRA_NHG_PROTO_SPACING (ZEBRA_NHG_PROTO_UPPER / ZEBRA_ROUTE_MAX)
#define ZEBRA_NHG_PROTO_LOWER \
(ZEBRA_NHG_PROTO_SPACING * (ZEBRA_ROUTE_CONNECT + 1))
(ZEBRA_NHG_PROTO_SPACING * (ZEBRA_ROUTE_LOCAL + 1))
extern uint32_t zclient_get_nhg_start(uint32_t proto);

View File

@ -8,6 +8,16 @@ C>* 192.168.6.0/26 is directly connected, r1-eth6, XX:XX:XX
C>* 192.168.7.0/26 is directly connected, r1-eth7, XX:XX:XX
C>* 192.168.8.0/26 is directly connected, r1-eth8, XX:XX:XX
C>* 192.168.9.0/26 is directly connected, r1-eth9, XX:XX:XX
L>* 192.168.0.1/32 is directly connected, r1-eth0, XX:XX:XX
L>* 192.168.1.1/32 is directly connected, r1-eth1, XX:XX:XX
L>* 192.168.2.1/32 is directly connected, r1-eth2, XX:XX:XX
L>* 192.168.3.1/32 is directly connected, r1-eth3, XX:XX:XX
L>* 192.168.4.1/32 is directly connected, r1-eth4, XX:XX:XX
L>* 192.168.5.1/32 is directly connected, r1-eth5, XX:XX:XX
L>* 192.168.6.1/32 is directly connected, r1-eth6, XX:XX:XX
L>* 192.168.7.1/32 is directly connected, r1-eth7, XX:XX:XX
L>* 192.168.8.1/32 is directly connected, r1-eth8, XX:XX:XX
L>* 192.168.9.1/32 is directly connected, r1-eth9, XX:XX:XX
O 192.168.0.0/24 [110/10] is directly connected, r1-eth0, weight 1, XX:XX:XX
O 192.168.3.0/26 [110/10] is directly connected, r1-eth3, weight 1, XX:XX:XX
S>* 1.1.1.1/32 [1/0] is directly connected, r1-eth1, weight 1, XX:XX:XX

View File

@ -19,6 +19,16 @@ C * fe80::/64 is directly connected, r1-eth6, XX:XX:XX
C * fe80::/64 is directly connected, r1-eth7, XX:XX:XX
C * fe80::/64 is directly connected, r1-eth8, XX:XX:XX
C * fe80::/64 is directly connected, r1-eth9, XX:XX:XX
L>* fc00:0:0:1::1/128 is directly connected, r1-eth1, XX:XX:XX
L>* fc00:0:0:2::1/128 is directly connected, r1-eth2, XX:XX:XX
L>* fc00:0:0:3::1/128 is directly connected, r1-eth3, XX:XX:XX
L>* fc00:0:0:4::1/128 is directly connected, r1-eth4, XX:XX:XX
L>* fc00:0:0:5::1/128 is directly connected, r1-eth5, XX:XX:XX
L>* fc00:0:0:6::1/128 is directly connected, r1-eth6, XX:XX:XX
L>* fc00:0:0:7::1/128 is directly connected, r1-eth7, XX:XX:XX
L>* fc00:0:0:8::1/128 is directly connected, r1-eth8, XX:XX:XX
L>* fc00:0:0:9::1/128 is directly connected, r1-eth9, XX:XX:XX
L>* fc00::1/128 is directly connected, r1-eth0, XX:XX:XX
O fc00:0:0:4::/64 [110/10] is directly connected, r1-eth4, weight 1, XX:XX:XX
S>* 4:5::6:10/128 [1/0] via fc00::2, r1-eth0, weight 1, XX:XX:XX
S>* 4:5::6:11/128 [1/0] via fc00::2, r1-eth0, weight 1, XX:XX:XX

View File

@ -8,6 +8,6 @@
"type":"sharp"
}
],
"routesTotal":4,
"routesTotalFib":4
"routesTotal":5,
"routesTotalFib":5
}

View File

@ -5,12 +5,18 @@ log file /tmp/r1-frr.log
!
interface r1-eth0
ip address 10.0.1.1/24
ip ospf hello-interval 1
ip ospf dead-interval 4
!
interface r1-eth1
ip address 10.0.20.1/24
ip ospf hello-interval 1
ip ospf dead-interval 4
!
interface r1-eth2 vrf neno
ip address 10.0.30.1/24
ip ospf hello-interval 1
ip ospf dead-interval 4
!
ip forwarding
!

View File

@ -1,9 +1,11 @@
O 10.0.1.0/24 [110/10] is directly connected, r1-eth0, weight 1, XX:XX:XX
C>* 10.0.1.0/24 is directly connected, r1-eth0, XX:XX:XX
L>* 10.0.1.1/32 is directly connected, r1-eth0, XX:XX:XX
O>* 10.0.2.0/24 [110/20] via 10.0.20.2, r1-eth1, weight 1, XX:XX:XX
B>* 10.0.3.0/24 [20/20] via 10.0.30.3, r1-eth2 (vrf neno), weight 1, XX:XX:XX
O>* 10.0.4.0/24 [110/20] via 10.0.20.2, r1-eth1, weight 1, XX:XX:XX
O 10.0.20.0/24 [110/10] is directly connected, r1-eth1, weight 1, XX:XX:XX
C>* 10.0.20.0/24 is directly connected, r1-eth1, XX:XX:XX
L>* 10.0.20.1/32 is directly connected, r1-eth1, XX:XX:XX
B>* 10.0.30.0/24 [20/0] is directly connected, r1-eth2 (vrf neno), weight 1, XX:XX:XX
O>* 10.0.40.0/24 [110/20] via 10.0.20.2, r1-eth1, weight 1, XX:XX:XX

View File

@ -3,4 +3,5 @@ O>* 10.0.3.0/24 [110/20] via 10.0.30.3, r1-eth2, weight 1, XX:XX:XX
B>* 10.0.4.0/24 [20/20] via 10.0.20.2, r1-eth1 (vrf default), weight 1, XX:XX:XX
O 10.0.30.0/24 [110/10] is directly connected, r1-eth2, weight 1, XX:XX:XX
C>* 10.0.30.0/24 is directly connected, r1-eth2, XX:XX:XX
L>* 10.0.30.1/32 is directly connected, r1-eth2, XX:XX:XX
B>* 10.0.40.0/24 [20/20] via 10.0.20.2, r1-eth1 (vrf default), weight 1, XX:XX:XX

View File

@ -5,14 +5,20 @@ log file /tmp/r2-frr.log
!
interface r2-eth0
ip address 10.0.2.2/24
ip ospf hello-interval 1
ip ospf dead-interval 4
!
interface r2-eth1
ip address 10.0.20.2/24
ip ospf hello-interval 1
ip ospf dead-interval 4
!
ip route 0.0.0.0/0 10.0.20.1
!
interface r2-eth2 vrf ray
ip address 10.0.40.2/24
ip ospf hello-interval 1
ip ospf dead-interval 4
!
ip forwarding
!

View File

@ -2,9 +2,11 @@ S>* 0.0.0.0/0 [1/0] via 10.0.20.1, r2-eth1, weight 1, XX:XX:XX
O>* 10.0.1.0/24 [110/20] via 10.0.20.1, r2-eth1, weight 1, XX:XX:XX
O 10.0.2.0/24 [110/10] is directly connected, r2-eth0, weight 1, XX:XX:XX
C>* 10.0.2.0/24 is directly connected, r2-eth0, XX:XX:XX
L>* 10.0.2.2/32 is directly connected, r2-eth0, XX:XX:XX
O>* 10.0.3.0/24 [110/20] via 10.0.20.1, r2-eth1, weight 1, XX:XX:XX
B>* 10.0.4.0/24 [20/20] via 10.0.40.4, r2-eth2 (vrf ray), weight 1, XX:XX:XX
O 10.0.20.0/24 [110/10] is directly connected, r2-eth1, weight 1, XX:XX:XX
C>* 10.0.20.0/24 is directly connected, r2-eth1, XX:XX:XX
L>* 10.0.20.2/32 is directly connected, r2-eth1, XX:XX:XX
O>* 10.0.30.0/24 [110/20] via 10.0.20.1, r2-eth1, weight 1, XX:XX:XX
B>* 10.0.40.0/24 [20/0] is directly connected, r2-eth2 (vrf ray), weight 1, XX:XX:XX

View File

@ -7,3 +7,4 @@ B 10.0.20.0/24 [20/0] is directly connected, r2-eth1 (vrf default) inactive, w
B>* 10.0.30.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default), weight 1, XX:XX:XX
O 10.0.40.0/24 [110/10] is directly connected, r2-eth2, weight 1, XX:XX:XX
C>* 10.0.40.0/24 is directly connected, r2-eth2, XX:XX:XX
L>* 10.0.40.2/32 is directly connected, r2-eth2, XX:XX:XX

View File

@ -5,9 +5,13 @@ log file /tmp/r3-frr.log
!
interface r3-eth0
ip address 10.0.3.3/24
ip ospf hello-interval 1
ip ospf dead-interval 4
!
interface r3-eth1
ip address 10.0.30.3/24
ip ospf hello-interval 1
ip ospf dead-interval 4
!
ip forwarding
!

View File

@ -1,8 +1,10 @@
O 10.0.3.0/24 [110/10] is directly connected, r3-eth0, weight 1, XX:XX:XX
C>* 10.0.3.0/24 is directly connected, r3-eth0, XX:XX:XX
L>* 10.0.3.3/32 is directly connected, r3-eth0, XX:XX:XX
O>* 10.0.4.0/24 [110/20] via 10.0.30.1, r3-eth1, weight 1, XX:XX:XX
O 10.0.30.0/24 [110/10] is directly connected, r3-eth1, weight 1, XX:XX:XX
C>* 10.0.30.0/24 is directly connected, r3-eth1, XX:XX:XX
L>* 10.0.30.3/32 is directly connected, r3-eth1, XX:XX:XX
O>* 10.0.40.0/24 [110/20] via 10.0.30.1, r3-eth1, weight 1, XX:XX:XX

View File

@ -5,9 +5,13 @@ log file /tmp/r4-frr.log
!
interface r4-eth0
ip address 10.0.4.4/24
ip ospf hello-interval 1
ip ospf dead-interval 4
!
interface r4-eth1
ip address 10.0.40.4/24
ip ospf hello-interval 1
ip ospf dead-interval 4
!
ip forwarding
!

View File

@ -1,7 +1,9 @@
O>* 10.0.3.0/24 [110/20] via 10.0.40.2, r4-eth1, weight 1, XX:XX:XX
O 10.0.4.0/24 [110/10] is directly connected, r4-eth0, weight 1, XX:XX:XX
C>* 10.0.4.0/24 is directly connected, r4-eth0, XX:XX:XX
L>* 10.0.4.4/32 is directly connected, r4-eth0, XX:XX:XX
O>* 10.0.30.0/24 [110/20] via 10.0.40.2, r4-eth1, weight 1, XX:XX:XX
O 10.0.40.0/24 [110/10] is directly connected, r4-eth1, weight 1, XX:XX:XX
C>* 10.0.40.0/24 is directly connected, r4-eth1, XX:XX:XX
L>* 10.0.40.4/32 is directly connected, r4-eth1, XX:XX:XX

View File

@ -3,6 +3,14 @@ hostname r1
password zebra
log file /tmp/r1-ospfd.log
!
interface r1-eth0 vrf r1-ospf-cust1
ip ospf hello-interval 1
ip ospf dead-interval 4
!
interface r1-eth1 vrf r1-ospf-cust1
ip ospf hello-interval 1
ip ospf dead-interval 4
!
router ospf vrf r1-ospf-cust1
ospf router-id 10.0.255.1
redistribute kernel

View File

@ -1,8 +1,10 @@
VRF r1-ospf-cust1:
O 10.0.1.0/24 [110/10] is directly connected, r1-eth0, weight 1, XX:XX:XX
C>* 10.0.1.0/24 is directly connected, r1-eth0, XX:XX:XX
L>* 10.0.1.1/32 is directly connected, r1-eth0, XX:XX:XX
O>* 10.0.2.0/24 [110/20] via 10.0.3.3, r1-eth1, weight 1, XX:XX:XX
O 10.0.3.0/24 [110/10] is directly connected, r1-eth1, weight 1, XX:XX:XX
C>* 10.0.3.0/24 is directly connected, r1-eth1, XX:XX:XX
L>* 10.0.3.2/32 is directly connected, r1-eth1, XX:XX:XX
O>* 10.0.10.0/24 [110/20] via 10.0.3.1, r1-eth1, weight 1, XX:XX:XX

View File

@ -1,7 +1,9 @@
VRF r1-ospf-cust1:
O 10.0.1.0/24 [110/10] is directly connected, r1-eth0, weight 1, XX:XX:XX
C>* 10.0.1.0/24 is directly connected, r1-eth0, XX:XX:XX
L>* 10.0.1.1/32 is directly connected, r1-eth0, XX:XX:XX
O>* 10.0.2.0/24 [110/20] via 10.0.3.3, r1-eth1, weight 1, XX:XX:XX
O 10.0.3.0/24 [110/10] is directly connected, r1-eth1, weight 1, XX:XX:XX
C>* 10.0.3.0/24 is directly connected, r1-eth1, XX:XX:XX
L>* 10.0.3.2/32 is directly connected, r1-eth1, XX:XX:XX

View File

@ -3,6 +3,13 @@ hostname r2
password zebra
log file /tmp/r2-ospfd.log
!
interface r2-eth0 vrf r2-ospf-cust1
ip ospf hello-interval 1
ip ospf dead-interval 4
!
interface r2-eth1 vrf r2-ospf-cust1
ip ospf hello-interval 1
ip ospf dead-interval 4
!
router ospf vrf r2-ospf-cust1
ospf router-id 10.0.255.2

View File

@ -2,7 +2,9 @@ VRF r2-ospf-cust1:
O>* 10.0.1.0/24 [110/20] via 10.0.3.2, r2-eth1, weight 1, XX:XX:XX
O 10.0.2.0/24 [110/10] is directly connected, r2-eth0, weight 1, XX:XX:XX
C>* 10.0.2.0/24 is directly connected, r2-eth0, XX:XX:XX
L>* 10.0.2.1/32 is directly connected, r2-eth0, XX:XX:XX
O 10.0.3.0/24 [110/10] is directly connected, r2-eth1, weight 1, XX:XX:XX
C>* 10.0.3.0/24 is directly connected, r2-eth1, XX:XX:XX
L>* 10.0.3.3/32 is directly connected, r2-eth1, XX:XX:XX
O>* 10.0.10.0/24 [110/20] via 10.0.3.1, r2-eth1, weight 1, XX:XX:XX

View File

@ -2,6 +2,8 @@ VRF r2-ospf-cust1:
O>* 10.0.1.0/24 [110/20] via 10.0.3.2, r2-eth1, weight 1, XX:XX:XX
O 10.0.2.0/24 [110/10] is directly connected, r2-eth0, weight 1, XX:XX:XX
C>* 10.0.2.0/24 is directly connected, r2-eth0, XX:XX:XX
L>* 10.0.2.1/32 is directly connected, r2-eth0, XX:XX:XX
O 10.0.3.0/24 [110/10] is directly connected, r2-eth1, weight 1, XX:XX:XX
C>* 10.0.3.0/24 is directly connected, r2-eth1, XX:XX:XX
L>* 10.0.3.3/32 is directly connected, r2-eth1, XX:XX:XX

View File

@ -4,6 +4,14 @@ password zebra
log file /tmp/r3-ospfd.log
!
!
interface r3-eth0 vrf r3-ospf-cust1
ip ospf hello-interval 1
ip ospf dead-interval 4
!
interface r3-eth1 vrf r3-ospf-cust1
ip ospf hello-interval 1
ip ospf dead-interval 4
!
router ospf vrf r3-ospf-cust1
ospf router-id 10.0.255.3
redistribute kernel

View File

@ -3,6 +3,8 @@ O>* 10.0.1.0/24 [110/20] via 10.0.3.2, r3-eth0, weight 1, XX:XX:XX
O>* 10.0.2.0/24 [110/20] via 10.0.3.3, r3-eth0, weight 1, XX:XX:XX
O 10.0.3.0/24 [110/10] is directly connected, r3-eth0, weight 1, XX:XX:XX
C>* 10.0.3.0/24 is directly connected, r3-eth0, XX:XX:XX
L>* 10.0.3.1/32 is directly connected, r3-eth0, XX:XX:XX
O 10.0.10.0/24 [110/10] is directly connected, r3-eth1, weight 1, XX:XX:XX
C>* 10.0.10.0/24 is directly connected, r3-eth1, XX:XX:XX
L>* 10.0.10.1/32 is directly connected, r3-eth1, XX:XX:XX

View File

@ -1,4 +1,5 @@
VRF r3-ospf-cust1:
O 10.0.10.0/24 [110/10] is directly connected, r3-eth1, weight 1, XX:XX:XX
C>* 10.0.10.0/24 is directly connected, r3-eth1, XX:XX:XX
L>* 10.0.10.1/32 is directly connected, r3-eth1, XX:XX:XX

View File

@ -11,6 +11,6 @@
"type":"sharp"
}
],
"routesTotal":1000032,
"routesTotalFib":1000032
"routesTotal":1000064,
"routesTotalFib":1000064
}

View File

@ -6,6 +6,6 @@
"type":"connected"
}
],
"routesTotal":32,
"routesTotalFib":32
"routesTotal":64,
"routesTotalFib":64
}

View File

@ -54,44 +54,47 @@ module frr-route-types {
enum connected {
value 2;
}
enum static {
enum local {
value 3;
}
enum rip {
enum static {
value 4;
}
enum rip {
value 5;
}
enum ospf {
value 6;
value 7;
}
enum isis {
value 8;
}
enum bgp {
value 9;
}
enum eigrp {
value 11;
enum bgp {
value 10;
}
enum nhrp {
enum eigrp {
value 12;
}
enum nhrp {
value 13;
}
enum table {
value 15;
value 16;
}
enum vnc {
value 17;
}
enum vnc-direct {
value 18;
}
enum babel {
value 22;
enum vnc-direct {
value 19;
}
enum sharp {
enum babel {
value 23;
}
enum sharp {
value 24;
}
enum openfabric {
value 26;
value 27;
}
}
}
@ -104,41 +107,44 @@ module frr-route-types {
enum connected {
value 2;
}
enum static {
enum local {
value 3;
}
enum static {
value 4;
}
enum ripng {
value 5;
value 6;
}
enum ospf6 {
value 7;
}
enum isis {
value 8;
}
enum bgp {
enum isis {
value 9;
}
enum bgp {
value 10;
}
enum nhrp {
value 12;
value 13;
}
enum table {
value 15;
value 16;
}
enum vnc {
value 17;
}
enum vnc-direct {
value 18;
}
enum babel {
value 22;
enum vnc-direct {
value 19;
}
enum sharp {
enum babel {
value 23;
}
enum sharp {
value 24;
}
enum openfabric {
value 26;
value 27;
}
}
}

View File

@ -182,7 +182,7 @@ static void connected_update(struct interface *ifp, struct connected *ifc)
void connected_up(struct interface *ifp, struct connected *ifc)
{
afi_t afi;
struct prefix p;
struct prefix p, plocal;
struct nexthop nh = {
.type = NEXTHOP_TYPE_IFINDEX,
.ifindex = ifp->ifindex,
@ -194,6 +194,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
uint32_t count = 0;
struct listnode *cnode;
struct connected *c;
bool install_local = true;
zvrf = ifp->vrf->info;
if (!zvrf) {
@ -210,6 +211,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
UNSET_FLAG(ifc->conf, ZEBRA_IFC_DOWN);
prefix_copy(&p, CONNECTED_PREFIX(ifc));
prefix_copy(&plocal, ifc->address);
/* Apply mask to the network. */
apply_mask(&p);
@ -224,6 +226,8 @@ void connected_up(struct interface *ifp, struct connected *ifc)
*/
if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
return;
plocal.prefixlen = IPV4_MAX_BITLEN;
break;
case AFI_IP6:
#ifndef GNU_LINUX
@ -231,6 +235,11 @@ void connected_up(struct interface *ifp, struct connected *ifc)
if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
return;
#endif
if (IN6_IS_ADDR_LINKLOCAL(&plocal.u.prefix6))
install_local = false;
plocal.prefixlen = IPV6_MAX_BITLEN;
break;
case AFI_UNSPEC:
case AFI_L2VPN:
@ -284,6 +293,15 @@ void connected_up(struct interface *ifp, struct connected *ifc)
flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0,
false);
if (install_local) {
rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_LOCAL,
0, flags, &plocal, NULL, &nh, 0, zvrf->table_id, 0, 0,
0, 0, false);
rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id,
ZEBRA_ROUTE_LOCAL, 0, flags, &plocal, NULL, &nh, 0,
zvrf->table_id, 0, 0, 0, 0, false);
}
/* Schedule LSP forwarding entries for processing, if appropriate. */
if (zvrf->vrf->vrf_id == VRF_DEFAULT) {
if (IS_ZEBRA_DEBUG_MPLS)
@ -368,7 +386,7 @@ void connected_add_ipv4(struct interface *ifp, int flags,
void connected_down(struct interface *ifp, struct connected *ifc)
{
afi_t afi;
struct prefix p;
struct prefix p, plocal;
struct nexthop nh = {
.type = NEXTHOP_TYPE_IFINDEX,
.ifindex = ifp->ifindex,
@ -378,6 +396,7 @@ void connected_down(struct interface *ifp, struct connected *ifc)
uint32_t count = 0;
struct listnode *cnode;
struct connected *c;
bool remove_local = true;
zvrf = ifp->vrf->info;
if (!zvrf) {
@ -403,6 +422,7 @@ void connected_down(struct interface *ifp, struct connected *ifc)
}
prefix_copy(&p, CONNECTED_PREFIX(ifc));
prefix_copy(&plocal, ifc->address);
/* Apply mask to the network. */
apply_mask(&p);
@ -417,10 +437,18 @@ void connected_down(struct interface *ifp, struct connected *ifc)
*/
if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
return;
plocal.prefixlen = IPV4_MAX_BITLEN;
break;
case AFI_IP6:
if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
return;
plocal.prefixlen = IPV6_MAX_BITLEN;
if (IN6_IS_ADDR_LINKLOCAL(&plocal.u.prefix6))
remove_local = false;
break;
case AFI_UNSPEC:
case AFI_L2VPN:
@ -463,6 +491,16 @@ void connected_down(struct interface *ifp, struct connected *ifc)
rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT,
0, 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false);
if (remove_local) {
rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id,
ZEBRA_ROUTE_LOCAL, 0, 0, &plocal, NULL, &nh, 0,
zvrf->table_id, 0, 0, false);
rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id,
ZEBRA_ROUTE_LOCAL, 0, 0, &plocal, NULL, &nh, 0,
zvrf->table_id, 0, 0, false);
}
/* Schedule LSP forwarding entries for processing, if appropriate. */
if (zvrf->vrf->vrf_id == VRF_DEFAULT) {
if (IS_ZEBRA_DEBUG_MPLS)

View File

@ -710,9 +710,10 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED))
continue;
if (same->type == re->type && same->instance == re->instance
&& same->table == re->table
&& same->type != ZEBRA_ROUTE_CONNECT)
if (same->type == re->type && same->instance == re->instance &&
same->table == re->table &&
(same->type != ZEBRA_ROUTE_CONNECT &&
same->type != ZEBRA_ROUTE_LOCAL))
break;
}

View File

@ -169,7 +169,7 @@ struct route_entry {
/* Define route types that are equivalent to "connected". */
#define RIB_CONNECTED_ROUTE(R) \
((R)->type == ZEBRA_ROUTE_CONNECT || (R)->type == ZEBRA_ROUTE_NHRP)
((R)->type == ZEBRA_ROUTE_CONNECT || (R)->type == ZEBRA_ROUTE_LOCAL || (R)->type == ZEBRA_ROUTE_NHRP)
/* meta-queue structure:
* sub-queue 0: nexthop group objects

View File

@ -25,7 +25,8 @@ extern "C" {
#define RKERNEL_ROUTE(type) ((type) == ZEBRA_ROUTE_KERNEL)
#define RSYSTEM_ROUTE(type) \
((RKERNEL_ROUTE(type)) || (type) == ZEBRA_ROUTE_CONNECT)
((RKERNEL_ROUTE(type)) || (type) == ZEBRA_ROUTE_CONNECT || \
(type) == ZEBRA_ROUTE_LOCAL)
#ifndef HAVE_NETLINK
/*

View File

@ -278,6 +278,7 @@ int zebra2proto(int proto)
proto = RTPROT_ZEBRA;
break;
case ZEBRA_ROUTE_CONNECT:
case ZEBRA_ROUTE_LOCAL:
case ZEBRA_ROUTE_KERNEL:
proto = RTPROT_KERNEL;
break;

View File

@ -2391,7 +2391,7 @@ static void zread_hello(ZAPI_HANDLER_ARGS)
client->synchronous = true;
/* accept only dynamic routing protocols */
if ((proto < ZEBRA_ROUTE_MAX) && (proto > ZEBRA_ROUTE_CONNECT)) {
if ((proto < ZEBRA_ROUTE_MAX) && (proto > ZEBRA_ROUTE_LOCAL)) {
zlog_notice(
"client %d says hello and bids fair to announce only %s routes vrf=%u",
client->sock, zebra_route_string(proto),

View File

@ -327,7 +327,7 @@ void zread_client_capabilities(ZAPI_HANDLER_ARGS)
return;
/* GR only for dynamic clients */
if (client->proto <= ZEBRA_ROUTE_CONNECT) {
if (client->proto <= ZEBRA_ROUTE_LOCAL) {
LOG_GR("%s: GR capabilities for client %s not supported",
__func__, zebra_route_string(client->proto));
return;

View File

@ -616,8 +616,9 @@ static int nhlfe_nexthop_active_ipv4(struct zebra_nhlfe *nhlfe,
for (match_nh = match->nhe->nhg.nexthop; match_nh;
match_nh = match_nh->next) {
if (match->type == ZEBRA_ROUTE_CONNECT
|| nexthop->ifindex == match_nh->ifindex) {
if ((match->type == ZEBRA_ROUTE_CONNECT ||
match->type == ZEBRA_ROUTE_LOCAL) ||
nexthop->ifindex == match_nh->ifindex) {
nexthop->ifindex = match_nh->ifindex;
return 1;
}
@ -659,9 +660,10 @@ static int nhlfe_nexthop_active_ipv6(struct zebra_nhlfe *nhlfe,
/* Locate a valid connected route. */
RNODE_FOREACH_RE (rn, match) {
if ((match->type == ZEBRA_ROUTE_CONNECT)
&& !CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)
&& CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED))
if (((match->type == ZEBRA_ROUTE_CONNECT ||
match->type == ZEBRA_ROUTE_LOCAL)) &&
!CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED) &&
CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED))
break;
}

View File

@ -2129,7 +2129,8 @@ zebra_nhg_connected_ifindex(struct route_node *rn, struct route_entry *match,
* of those ifindexes match as well.
*/
RNODE_FOREACH_RE (rn, re) {
if (re->type != ZEBRA_ROUTE_CONNECT)
if (re->type != ZEBRA_ROUTE_CONNECT &&
re->type != ZEBRA_ROUTE_LOCAL)
continue;
if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))

View File

@ -103,6 +103,9 @@ static const struct {
[ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT,
ZEBRA_CONNECT_DISTANCE_DEFAULT,
META_QUEUE_CONNECTED},
[ZEBRA_ROUTE_LOCAL] = {ZEBRA_ROUTE_LOCAL,
ZEBRA_CONNECT_DISTANCE_DEFAULT,
META_QUEUE_CONNECTED},
[ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC,
ZEBRA_STATIC_DISTANCE_DEFAULT,
META_QUEUE_STATIC},
@ -522,7 +525,8 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
if (rn)
route_lock_node(rn);
} else {
if (match->type != ZEBRA_ROUTE_CONNECT) {
if (match->type != ZEBRA_ROUTE_CONNECT &&
match->type != ZEBRA_ROUTE_LOCAL) {
if (!CHECK_FLAG(match->status,
ROUTE_ENTRY_INSTALLED))
return NULL;
@ -624,7 +628,8 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
if (!match)
return NULL;
if (match->type == ZEBRA_ROUTE_CONNECT)
if (match->type == ZEBRA_ROUTE_CONNECT ||
match->type == ZEBRA_ROUTE_LOCAL)
return match;
if (CHECK_FLAG(match->status, ROUTE_ENTRY_INSTALLED))
@ -1123,27 +1128,15 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
}
/* Check if 'alternate' RIB entry is better than 'current'. */
static struct route_entry *rib_choose_best(struct route_entry *current,
struct route_entry *alternate)
static struct route_entry *rib_choose_best_type(uint8_t route_type,
struct route_entry *current,
struct route_entry *alternate)
{
if (current == NULL)
return alternate;
/* filter route selection in following order:
* - connected beats other types
* - if both connected, loopback or vrf wins
* - lower distance beats higher
* - lower metric beats higher for equal distance
* - last, hence oldest, route wins tie break.
/*
* We know that alternate and current are now non-NULL
*/
/* Connected routes. Check to see if either are a vrf
* or loopback interface. If not, pick the last connected
* route of the set of lowest metric connected routes.
*/
if (alternate->type == ZEBRA_ROUTE_CONNECT) {
if (current->type != ZEBRA_ROUTE_CONNECT)
if (alternate->type == route_type) {
if (current->type != route_type)
return alternate;
/* both are connected. are either loop or vrf? */
@ -1172,7 +1165,41 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
return current;
}
if (current->type == ZEBRA_ROUTE_CONNECT)
return NULL;
}
/* Check if 'alternate' RIB entry is better than 'current'. */
static struct route_entry *rib_choose_best(struct route_entry *current,
struct route_entry *alternate)
{
struct route_entry *possible;
if (current == NULL)
return alternate;
/* filter route selection in following order:
* - Local beats Connected
* - connected beats other types
* - if both connected, loopback or vrf wins
* - lower distance beats higher
* - lower metric beats higher for equal distance
* - last, hence oldest, route wins tie break.
*/
/* Connected or Local routes. Check to see if either are a vrf
* or loopback interface. If not, pick the last connected
* route of the set of lowest metric connected routes.
*/
possible = rib_choose_best_type(ZEBRA_ROUTE_LOCAL, current, alternate);
if (possible)
return possible;
possible = rib_choose_best_type(ZEBRA_ROUTE_CONNECT, current, alternate);
if (possible)
return possible;
if (current->type == ZEBRA_ROUTE_CONNECT ||
current->type == ZEBRA_ROUTE_LOCAL)
return current;
/* higher distance loses */
@ -1507,7 +1534,8 @@ static bool rib_route_match_ctx(const struct route_entry *re,
} else if (re->type == ZEBRA_ROUTE_KERNEL &&
re->metric != dplane_ctx_get_metric(ctx)) {
result = false;
} else if (re->type == ZEBRA_ROUTE_CONNECT) {
} else if (re->type == ZEBRA_ROUTE_CONNECT ||
re->type == ZEBRA_ROUTE_LOCAL) {
result = nexthop_group_equal_no_recurse(
&re->nhe->nhg, dplane_ctx_get_ng(ctx));
}
@ -1565,7 +1593,7 @@ static bool rib_compare_routes(const struct route_entry *re1,
* v6 link-locals, and we also support multiple addresses in the same
* subnet on a single interface.
*/
if (re1->type != ZEBRA_ROUTE_CONNECT)
if (re1->type != ZEBRA_ROUTE_CONNECT && re1->type != ZEBRA_ROUTE_LOCAL)
return true;
return false;
@ -2968,7 +2996,8 @@ static void process_subq_early_route_delete(struct zebra_early_route *ere)
if (re->type == ZEBRA_ROUTE_KERNEL &&
re->metric != ere->re->metric)
continue;
if (re->type == ZEBRA_ROUTE_CONNECT &&
if ((re->type == ZEBRA_ROUTE_CONNECT ||
re->type == ZEBRA_ROUTE_LOCAL) &&
(rtnh = re->nhe->nhg.nexthop) &&
rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
if (rtnh->ifindex != nh->ifindex)

View File

@ -513,10 +513,14 @@ static bool rnh_check_re_nexthops(const struct route_entry *re,
goto done;
}
/* Some special checks if registration asked for them. */
/*
* Some special checks if registration asked for them.
* LOCAL routes are by their definition not CONNECTED
* and as such should not be considered here
*/
if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) {
if ((re->type == ZEBRA_ROUTE_CONNECT)
|| (re->type == ZEBRA_ROUTE_STATIC))
if ((re->type == ZEBRA_ROUTE_CONNECT) ||
(re->type == ZEBRA_ROUTE_STATIC))
ret = true;
if (re->type == ZEBRA_ROUTE_NHRP) {

View File

@ -223,6 +223,8 @@ static int proto_trans(int type)
return 1; /* other */
case ZEBRA_ROUTE_CONNECT:
return 2; /* local interface */
case ZEBRA_ROUTE_LOCAL:
return 2;
case ZEBRA_ROUTE_STATIC:
return 3; /* static route */
case ZEBRA_ROUTE_RIP:

View File

@ -764,9 +764,10 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
}
/* Distance and metric display. */
if (((re->type == ZEBRA_ROUTE_CONNECT) &&
if (((re->type == ZEBRA_ROUTE_CONNECT ||
re->type == ZEBRA_ROUTE_LOCAL) &&
(re->distance || re->metric)) ||
(re->type != ZEBRA_ROUTE_CONNECT))
(re->type != ZEBRA_ROUTE_CONNECT && re->type != ZEBRA_ROUTE_LOCAL))
len += vty_out(vty, " [%u/%u]", re->distance,
re->metric);
@ -2251,7 +2252,8 @@ static void show_ip_route_dump_vty(struct vty *vty, struct route_table *table)
vrf_id_to_name(re->vrf_id));
vty_out(vty, " flags: %u\n", re->flags);
if (re->type != ZEBRA_ROUTE_CONNECT) {
if (re->type != ZEBRA_ROUTE_CONNECT &&
re->type != ZEBRA_ROUTE_LOCAL) {
vty_out(vty, " distance: %u\n", re->distance);
vty_out(vty, " metric: %u\n", re->metric);
}

View File

@ -237,8 +237,7 @@ DECLARE_HOOK(zserv_client_connect, (struct zserv *client), (client));
DECLARE_KOOH(zserv_client_close, (struct zserv *client), (client));
#define DYNAMIC_CLIENT_GR_DISABLED(_client) \
((_client->proto <= ZEBRA_ROUTE_CONNECT) \
|| !(_client->gr_instance_count))
((_client->proto <= ZEBRA_ROUTE_LOCAL) || !(_client->gr_instance_count))
/*
* Initialize Zebra API server.