summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_evpn.c67
-rw-r--r--bgpd/bgp_main.c2
-rw-r--r--bgpd/bgp_route.c11
-rw-r--r--bgpd/bgp_vty.c259
-rw-r--r--bgpd/bgp_zebra.c6
-rw-r--r--bgpd/bgpd.c3
-rw-r--r--doc/OSPF-SR.rst23
-rw-r--r--doc/ospfd.texi7
-rw-r--r--lib/command.c3
-rw-r--r--lib/netns_linux.c9
-rw-r--r--lib/zclient.c4
-rw-r--r--ospf6d/ospf6_asbr.c267
-rw-r--r--ospf6d/ospf6_asbr.h3
-rw-r--r--ospf6d/ospf6_route.c26
-rw-r--r--ospf6d/ospf6_top.c27
-rw-r--r--ospfd/ospf_main.c2
-rw-r--r--ospfd/ospf_sr.c264
-rw-r--r--ospfd/ospfd.c1
-rw-r--r--tests/.gitignore4
-rw-r--r--tests/lib/test_ringbuf.py4
-rw-r--r--vtysh/vtysh.c2
-rw-r--r--vtysh/vtysh_config.c7
-rw-r--r--zebra/zebra_rnh.c4
-rw-r--r--zebra/zebra_vxlan.c57
-rw-r--r--zebra/zserv.c10
25 files changed, 657 insertions, 415 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index a8ee14c72e..e5863e4980 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -1760,8 +1760,10 @@ static int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
}
/*
- * There is a tunnel endpoint IP address change for this VNI,
- * need to re-advertise routes with the new nexthop.
+ * There is a tunnel endpoint IP address change for this VNI, delete
+ * prior type-3 route (if needed) and update.
+ * Note: Route re-advertisement happens elsewhere after other processing
+ * other changes.
*/
static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
struct in_addr originator_ip)
@@ -1789,7 +1791,7 @@ static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
/* Update the tunnel IP and re-advertise all routes for this VNI. */
vpn->originator_ip = originator_ip;
- return update_routes_for_vni(bgp, vpn);
+ return 0;
}
/*
@@ -3245,15 +3247,25 @@ void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf,
{
struct bgp_table *table = NULL;
struct bgp_node *rn = NULL;
+ struct bgp_info *ri;
/* Bail out early if we don't have to advertise type-5 routes. */
if (!advertise_type5_routes(bgp_vrf, afi))
return;
table = bgp_vrf->rib[afi][safi];
- for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
- bgp_evpn_withdraw_type5_route(bgp_vrf, &rn->p, afi, safi);
-
+ for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
+ /* Only care about "selected" routes - non-imported. */
+ /* TODO: Support for AddPath for EVPN. */
+ for (ri = rn->info; ri; ri = ri->next) {
+ if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) &&
+ (!ri->extra || !ri->extra->parent)) {
+ bgp_evpn_withdraw_type5_route(bgp_vrf, &rn->p,
+ afi, safi);
+ break;
+ }
+ }
+ }
}
/*
@@ -3274,10 +3286,6 @@ void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct prefix *p,
if (!advertise_type5_routes(bgp_vrf, afi))
return;
- /* only advertise subnet routes as type-5 */
- if (is_host_route(p))
- return;
-
build_type5_prefix_from_ip_prefix(&evp, p);
ret = update_evpn_type5_route(bgp_vrf, &evp, src_attr);
if (ret)
@@ -3305,11 +3313,12 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf,
table = bgp_vrf->rib[afi][safi];
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
/* Need to identify the "selected" route entry to use its
- * attribute.
+ * attribute. Also, we only consider "non-imported" routes.
* TODO: Support for AddPath for EVPN.
*/
for (ri = rn->info; ri; ri = ri->next) {
- if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
+ if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) &&
+ (!ri->extra || !ri->extra->parent)) {
/* apply the route-map */
if (bgp_vrf->adv_cmd_rmap[afi][safi].map) {
@@ -3322,7 +3331,6 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf,
if (ret == RMAP_DENYMATCH)
continue;
}
-
bgp_evpn_advertise_type5_route(bgp_vrf, &rn->p,
ri->attr,
afi, safi);
@@ -4449,8 +4457,8 @@ int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni)
}
/*
- * Handle add (or update) of a local VNI. The only VNI change we care
- * about is change to local-tunnel-ip.
+ * Handle add (or update) of a local VNI. The VNI changes we care
+ * about are for the local-tunnel-ip and the (tenant) VRF.
*/
int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
struct in_addr originator_ip,
@@ -4468,24 +4476,31 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
vpn = bgp_evpn_lookup_vni(bgp, vni);
if (vpn) {
- /* update tenant_vrf_id if required */
+ if (is_vni_live(vpn)
+ && IPV4_ADDR_SAME(&vpn->originator_ip, &originator_ip)
+ && vpn->tenant_vrf_id == tenant_vrf_id)
+ /* Probably some other param has changed that we don't
+ * care about. */
+ return 0;
+
+ /* Update tenant_vrf_id if it has changed. */
if (vpn->tenant_vrf_id != tenant_vrf_id) {
bgpevpn_unlink_from_l3vni(vpn);
vpn->tenant_vrf_id = tenant_vrf_id;
bgpevpn_link_to_l3vni(vpn);
-
- /* update all routes with new export RT for VRFs */
- update_routes_for_vni(bgp, vpn);
}
- if (is_vni_live(vpn)
- && IPV4_ADDR_SAME(&vpn->originator_ip, &originator_ip))
- /* Probably some other param has changed that we don't
- * care about. */
- return 0;
+ /* If tunnel endpoint IP has changed, update (and delete prior
+ * type-3 route, if needed.)
+ */
+ if (!IPV4_ADDR_SAME(&vpn->originator_ip, &originator_ip))
+ handle_tunnel_ip_change(bgp, vpn, originator_ip);
- /* Local tunnel endpoint IP address has changed */
- handle_tunnel_ip_change(bgp, vpn, originator_ip);
+ /* Update all routes with new endpoint IP and/or export RT
+ * for VRFs
+ */
+ if (is_vni_live(vpn))
+ update_routes_for_vni(bgp, vpn);
}
/* Create or update as appropriate. */
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 82c74e4afa..30b7afff92 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -106,7 +106,7 @@ static int retain_mode = 0;
/* privileges */
static zebra_capabilities_t _caps_p[] = {
- ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN,
+ ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN
};
struct zebra_privs_t bgpd_privs = {
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 20bf9635a3..3dfc446b2c 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2228,10 +2228,13 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
/* advertise/withdraw type-5 routes */
if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
- if (new_select)
- bgp_evpn_advertise_type5_route(
- bgp, &rn->p, new_select->attr, afi, safi);
- else if (old_select)
+ if (new_select &&
+ (!new_select->extra || !new_select->extra->parent))
+ bgp_evpn_advertise_type5_route(bgp, &rn->p,
+ new_select->attr,
+ afi, safi);
+ else if (old_select &&
+ (!old_select->extra || !old_select->extra->parent))
bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 2f60871e88..c503a91be2 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -833,7 +833,7 @@ DEFUN_NOSH (router_bgp,
if (listcount(bm->bgp) > 1) {
vty_out(vty,
- "%% Multiple BGP processes are configured\n");
+ "%% Please specify ASN and VRF\n");
return CMD_WARNING_CONFIG_FAILED;
}
}
@@ -909,7 +909,7 @@ DEFUN (no_router_bgp,
if (listcount(bm->bgp) > 1) {
vty_out(vty,
- "%% Multiple BGP processes are configured\n");
+ "%% Please specify ASN and VRF\n");
return CMD_WARNING_CONFIG_FAILED;
}
@@ -10314,227 +10314,43 @@ static void show_bgp_updgrps_adj_info_aux(struct vty *vty, const char *name,
}
}
-DEFUN (show_ip_bgp_updgrps_adj,
- show_ip_bgp_updgrps_adj_cmd,
- "show [ip] bgp update-groups <advertise-queue|advertised-routes|packet-queue>",
- SHOW_STR
- IP_STR
- BGP_STR
- "Detailed info about dynamic update groups\n"
- "Advertisement queue\n"
- "Announced routes\n"
- "Packet queue\n")
-{
- int idx_type = 4;
- show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP, SAFI_UNICAST,
- argv[idx_type]->arg, 0);
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ip_bgp_instance_updgrps_adj,
- show_ip_bgp_instance_updgrps_adj_cmd,
- "show [ip] bgp <view|vrf> VIEWVRFNAME update-groups <advertise-queue|advertised-routes|packet-queue>",
- SHOW_STR
- IP_STR
- BGP_STR
- BGP_INSTANCE_HELP_STR
- "Detailed info about dynamic update groups\n"
- "Advertisement queue\n"
- "Announced routes\n"
- "Packet queue\n")
-{
- int idx_word = 4;
- int idx_type = 6;
- show_bgp_updgrps_adj_info_aux(vty, argv[idx_word]->arg, AFI_IP,
- SAFI_UNICAST, argv[idx_type]->arg, 0);
- return CMD_SUCCESS;
-}
-
-DEFUN (show_bgp_updgrps_afi_adj,
- show_bgp_updgrps_afi_adj_cmd,
- "show [ip] bgp "BGP_AFI_SAFI_CMD_STR" update-groups <advertise-queue|advertised-routes|packet-queue>",
- SHOW_STR
- IP_STR
- BGP_STR
- BGP_AFI_SAFI_HELP_STR
- "Detailed info about dynamic update groups\n"
- "Advertisement queue\n"
- "Announced routes\n"
- "Packet queue\n")
-{
- int idx_afi = 2;
- int idx_safi = 3;
- int idx_type = 5;
- show_bgp_updgrps_adj_info_aux(
- vty, NULL, bgp_vty_afi_from_str(argv[idx_afi]->text),
- bgp_vty_safi_from_str(argv[idx_safi]->text),
- argv[idx_type]->arg, 0);
- return CMD_SUCCESS;
-}
-
-DEFUN (show_bgp_updgrps_adj,
- show_bgp_updgrps_adj_cmd,
- "show [ip] bgp update-groups <advertise-queue|advertised-routes|packet-queue>",
- SHOW_STR
- IP_STR
- BGP_STR
- "Detailed info about dynamic update groups\n"
- "Advertisement queue\n"
- "Announced routes\n"
- "Packet queue\n")
-{
- int idx_type = 3;
- show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP6, SAFI_UNICAST,
- argv[idx_type]->arg, 0);
- return CMD_SUCCESS;
-}
-
-DEFUN (show_bgp_instance_updgrps_adj,
- show_bgp_instance_updgrps_adj_cmd,
- "show [ip] bgp <view|vrf> VIEWVRFNAME update-groups <advertise-queue|advertised-routes|packet-queue>",
- SHOW_STR
- IP_STR
- BGP_STR
- BGP_INSTANCE_HELP_STR
- "Detailed info about dynamic update groups\n"
- "Advertisement queue\n"
- "Announced routes\n"
- "Packet queue\n")
-{
- int idx_word = 3;
- int idx_type = 5;
- show_bgp_updgrps_adj_info_aux(vty, argv[idx_word]->arg, AFI_IP6,
- SAFI_UNICAST, argv[idx_type]->arg, 0);
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ip_bgp_updgrps_adj_s,
- show_ip_bgp_updgrps_adj_s_cmd,
- "show [ip] bgp update-groups SUBGROUP-ID <advertise-queue|advertised-routes|packet-queue>",
- SHOW_STR
- IP_STR
- BGP_STR
- "Detailed info about dynamic update groups\n"
- "Specific subgroup to display info for\n"
- "Advertisement queue\n"
- "Announced routes\n"
- "Packet queue\n")
+DEFPY(show_ip_bgp_instance_updgrps_adj_s,
+ show_ip_bgp_instance_updgrps_adj_s_cmd,
+ "show [ip]$ip bgp [<view|vrf> VIEWVRFNAME$vrf] [<ipv4|ipv6>$afi <unicast|multicast|vpn>$safi] update-groups [SUBGROUP-ID]$sgid <advertise-queue|advertised-routes|packet-queue>$rtq",
+ SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
+ BGP_SAFI_HELP_STR
+ "Detailed info about dynamic update groups\n"
+ "Specific subgroup to display info for\n"
+ "Advertisement queue\n"
+ "Announced routes\n"
+ "Packet queue\n")
{
- int idx_subgroup_id = 4;
- int idx_type = 5;
- uint64_t subgrp_id;
-
- subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10);
-
- show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP, SAFI_UNICAST,
- argv[idx_type]->arg, subgrp_id);
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ip_bgp_instance_updgrps_adj_s,
- show_ip_bgp_instance_updgrps_adj_s_cmd,
- "show [ip] bgp <view|vrf> VIEWVRFNAME update-groups SUBGROUP-ID <advertise-queue|advertised-routes|packet-queue>",
- SHOW_STR
- IP_STR
- BGP_STR
- BGP_INSTANCE_HELP_STR
- "Detailed info about dynamic update groups\n"
- "Specific subgroup to display info for\n"
- "Advertisement queue\n"
- "Announced routes\n"
- "Packet queue\n")
-{
- int idx_vrf = 4;
- int idx_subgroup_id = 6;
- int idx_type = 7;
- uint64_t subgrp_id;
-
- subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10);
-
- show_bgp_updgrps_adj_info_aux(vty, argv[idx_vrf]->arg, AFI_IP,
- SAFI_UNICAST, argv[idx_type]->arg,
- subgrp_id);
- return CMD_SUCCESS;
-}
-
-DEFUN (show_bgp_updgrps_afi_adj_s,
- show_bgp_updgrps_afi_adj_s_cmd,
- "show [ip] bgp "BGP_AFI_SAFI_CMD_STR" update-groups SUBGROUP-ID <advertise-queue|advertised-routes|packet-queue>",
- SHOW_STR
- IP_STR
- BGP_STR
- BGP_AFI_SAFI_HELP_STR
- "Detailed info about dynamic update groups\n"
- "Specific subgroup to display info for\n"
- "Advertisement queue\n"
- "Announced routes\n"
- "Packet queue\n")
-{
- int idx_afi = 2;
- int idx_safi = 3;
- int idx_subgroup_id = 5;
- int idx_type = 6;
- uint64_t subgrp_id;
-
- subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10);
-
- show_bgp_updgrps_adj_info_aux(
- vty, NULL, bgp_vty_afi_from_str(argv[idx_afi]->text),
- bgp_vty_safi_from_str(argv[idx_safi]->text),
- argv[idx_type]->arg, subgrp_id);
- return CMD_SUCCESS;
-}
-
-DEFUN (show_bgp_updgrps_adj_s,
- show_bgp_updgrps_adj_s_cmd,
- "show [ip] bgp update-groups SUBGROUP-ID <advertise-queue|advertised-routes|packet-queue>",
- SHOW_STR
- IP_STR
- BGP_STR
- "Detailed info about dynamic update groups\n"
- "Specific subgroup to display info for\n"
- "Advertisement queue\n"
- "Announced routes\n"
- "Packet queue\n")
-{
- int idx_subgroup_id = 3;
- int idx_type = 4;
- uint64_t subgrp_id;
-
- subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10);
-
- show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP6, SAFI_UNICAST,
- argv[idx_type]->arg, subgrp_id);
- return CMD_SUCCESS;
-}
-
-DEFUN (show_bgp_instance_updgrps_adj_s,
- show_bgp_instance_updgrps_adj_s_cmd,
- "show [ip] bgp <view|vrf> VIEWVRFNAME update-groups SUBGROUP-ID <advertise-queue|advertised-routes|packet-queue>",
- SHOW_STR
- IP_STR
- BGP_STR
- BGP_INSTANCE_HELP_STR
- "Detailed info about dynamic update groups\n"
- "Specific subgroup to display info for\n"
- "Advertisement queue\n"
- "Announced routes\n"
- "Packet queue\n")
-{
- int idx_vrf = 3;
- int idx_subgroup_id = 5;
- int idx_type = 6;
- uint64_t subgrp_id;
+ uint64_t subgrp_id = 0;
+ afi_t afiz;
+ safi_t safiz;
+ if (sgid)
+ subgrp_id = strtoull(sgid, NULL, 10);
+
+ if (!ip && !afi)
+ afiz = AFI_IP6;
+ if (!ip && afi)
+ afiz = bgp_vty_afi_from_str(afi);
+ if (ip && !afi)
+ afiz = AFI_IP;
+ if (ip && afi) {
+ afiz = bgp_vty_afi_from_str(afi);
+ if (afiz != AFI_IP)
+ vty_out(vty,
+ "%% Cannot specify both 'ip' and 'ipv6'\n");
+ return CMD_WARNING;
+ }
- subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10);
+ safiz = safi ? bgp_vty_safi_from_str(safi) : SAFI_UNICAST;
- show_bgp_updgrps_adj_info_aux(vty, argv[idx_vrf]->arg, AFI_IP6,
- SAFI_UNICAST, argv[idx_type]->arg,
- subgrp_id);
+ show_bgp_updgrps_adj_info_aux(vty, vrf, afiz, safiz, rtq, subgrp_id);
return CMD_SUCCESS;
}
-
static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group)
{
struct listnode *node, *nnode;
@@ -12449,19 +12265,10 @@ void bgp_vty_init(void)
/* "show [ip] bgp summary" commands. */
install_element(VIEW_NODE, &show_bgp_instance_all_ipv6_updgrps_cmd);
- install_element(VIEW_NODE, &show_bgp_instance_updgrps_adj_cmd);
- install_element(VIEW_NODE, &show_bgp_instance_updgrps_adj_s_cmd);
install_element(VIEW_NODE, &show_bgp_instance_updgrps_stats_cmd);
- install_element(VIEW_NODE, &show_bgp_updgrps_adj_cmd);
- install_element(VIEW_NODE, &show_bgp_updgrps_adj_s_cmd);
- install_element(VIEW_NODE, &show_bgp_updgrps_afi_adj_cmd);
- install_element(VIEW_NODE, &show_bgp_updgrps_afi_adj_s_cmd);
install_element(VIEW_NODE, &show_bgp_updgrps_stats_cmd);
- install_element(VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_cmd);
install_element(VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_s_cmd);
install_element(VIEW_NODE, &show_ip_bgp_summary_cmd);
- install_element(VIEW_NODE, &show_ip_bgp_updgrps_adj_cmd);
- install_element(VIEW_NODE, &show_ip_bgp_updgrps_adj_s_cmd);
install_element(VIEW_NODE, &show_ip_bgp_updgrps_cmd);
/* "show [ip] bgp neighbors" commands. */
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index daa7ccbf42..029b3d4d36 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1054,6 +1054,9 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
else
continue;
+ api_nh = &api.nexthops[valid_nh_count];
+ api_nh->vrf_id = bgp->vrf_id;
+
if (nh_family == AF_INET) {
struct in_addr *nexthop;
@@ -1078,9 +1081,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
nexthop = &mpinfo_cp->attr->nexthop;
- api_nh = &api.nexthops[valid_nh_count];
api_nh->gate.ipv4 = *nexthop;
- api_nh->vrf_id = bgp->vrf_id;
/* EVPN type-2 routes are
programmed as onlink on l3-vni SVI
*/
@@ -1135,7 +1136,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
if (ifindex == 0)
continue;
- api_nh = &api.nexthops[valid_nh_count];
api_nh->gate.ipv6 = *nexthop;
api_nh->ifindex = ifindex;
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index c06339aad9..e8ea2b717f 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -108,7 +108,8 @@ static int bgp_check_main_socket(bool create, struct bgp *bgp)
struct listnode *bgpnode, *nbgpnode;
struct bgp *bgp_temp;
- if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF &&
+ vrf_is_mapped_on_netns(bgp->vrf_id))
return 0;
if (create == true) {
if (bgp_server_main_created)
diff --git a/doc/OSPF-SR.rst b/doc/OSPF-SR.rst
index 0ee1a12f28..299a7e1c87 100644
--- a/doc/OSPF-SR.rst
+++ b/doc/OSPF-SR.rst
@@ -5,6 +5,26 @@ This is an EXPERIMENTAL support of draft
`draft-ietf-ospf-segment-routing-extensions-24`.
DON'T use it for production network.
+Supported Features
+------------------
+
+* Automatic computation of Primary and Backup Adjacency SID with
+ Cisco experimental remote IP address
+* SRGB configuration
+* Prefix configuration for Node SID with optional NO-PHP flag (Linux
+ kernel support both mode)
+* Node MSD configuration (with Linux Kernel >= 4.10 a maximum of 32 labels
+ could be stack)
+* Automatic provisioning of MPLS table
+* Static route configuration with label stack up to 32 labels
+
+Interoperability
+----------------
+
+* tested on various topology including point-to-point and LAN interfaces
+ in a mix of Free Range Routing instance and Cisco IOS-XR 6.0.x
+* check OSPF LSA conformity with latest wireshark release 2.5.0-rc
+
Implementation details
----------------------
@@ -248,9 +268,6 @@ Known limitations
* MPLS table are not flush at startup. Thus, restarting zebra process is
mandatory to remove old MPLS entries in the data plane after a crash of
ospfd daemon
-* Due to a bug in OSPF Opaque, LSA are not flood when enable Segment Routing
- through CLI once OSPFd started. You must configure Segment Routing within
- configuration file before launching OSPFd
* With NO Penultimate Hop Popping, it is not possible to express a Segment
Path with an Adjacency SID due to the impossibility for the Linux Kernel to
perform double POP instruction.
diff --git a/doc/ospfd.texi b/doc/ospfd.texi
index 33341d2be6..9694be1efe 100644
--- a/doc/ospfd.texi
+++ b/doc/ospfd.texi
@@ -759,10 +759,11 @@ currently supported. The 'no-php-flag' means NO Penultimate Hop Popping that
allows SR node to request to its neighbor to not pop the label.
@end deffn
-@deffn {Command} {show ip ospf database segment-routing} {}
-@deffnx {Command} {show ip ospf database segment-routing adv-router @var{adv-router}} {}
-@deffnx {Command} {show ip ospf database segment-routing self-originate} {}
+@deffn {Command} {show ip ospf database segment-routing [json]} {}
+@deffnx {Command} {show ip ospf database segment-routing adv-router @var{adv-router} [json]} {}
+@deffnx {Command} {show ip ospf database segment-routing self-originate [json]} {}
Show Segment Routing Data Base, all SR nodes, specific advertized router or self router.
+Optional Json output could be obtain by adding 'json' at the end of the command.
@end deffn
@node Debugging OSPF
diff --git a/lib/command.c b/lib/command.c
index 10996d5dd4..3fa086bf62 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -500,6 +500,9 @@ static int config_write_host(struct vty *vty)
if (cmd_hostname_get())
vty_out(vty, "hostname %s\n", cmd_hostname_get());
+ if (cmd_domainname_get())
+ vty_out(vty, "domainname %s\n", cmd_domainname_get());
+
if (host.encrypt) {
if (host.password_encrypt)
vty_out(vty, "password 8 %s\n", host.password_encrypt);
diff --git a/lib/netns_linux.c b/lib/netns_linux.c
index 0e955bade9..a92431d1ae 100644
--- a/lib/netns_linux.c
+++ b/lib/netns_linux.c
@@ -43,6 +43,9 @@
DEFINE_MTYPE_STATIC(LIB, NS, "NetNS Context")
DEFINE_MTYPE_STATIC(LIB, NS_NAME, "NetNS Name")
+/* default NS ID value used when VRF backend is not NETNS */
+#define NS_DEFAULT_INTERNAL 0
+
static inline int ns_compare(const struct ns *ns, const struct ns *ns2);
static struct ns *ns_lookup_name_internal(const char *name);
@@ -414,8 +417,10 @@ void ns_init(void)
#ifdef HAVE_NETNS
if (have_netns_enabled < 0)
ns_default_ns_fd = open(NS_DEFAULT_NAME, O_RDONLY);
- else
+ else {
ns_default_ns_fd = -1;
+ default_ns = NULL;
+ }
#else
ns_default_ns_fd = -1;
default_ns = NULL;
@@ -534,6 +539,6 @@ ns_id_t ns_get_default_id(void)
{
if (default_ns)
return default_ns->ns_id;
- return NS_UNKNOWN;
+ return NS_DEFAULT_INTERNAL;
}
diff --git a/lib/zclient.c b/lib/zclient.c
index ad91eb504b..8535c3b5f5 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1085,7 +1085,7 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
STREAM_GETC(s, api->message);
STREAM_GETC(s, api->safi);
if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
- stream_get(&(api->rmac), s, sizeof(struct ethaddr));
+ STREAM_GET(&(api->rmac), s, sizeof(struct ethaddr));
/* Prefix. */
STREAM_GETC(s, api->prefix.family);
@@ -1266,6 +1266,8 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
break;
}
+ STREAM_GETC(s, nhr->type);
+ STREAM_GETW(s, nhr->instance);
STREAM_GETC(s, nhr->distance);
STREAM_GETL(s, nhr->metric);
STREAM_GETC(s, nhr->nexthop_num);
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 11f9e7c7b6..b52f1cef6c 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -204,26 +204,142 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
{
struct ospf6_route *old_route;
struct ospf6_path *ecmp_path, *o_path = NULL;
- struct listnode *anode;
+ struct listnode *anode, *anext;
struct listnode *nnode, *rnode, *rnext;
struct ospf6_nexthop *nh, *rnh;
char buf[PREFIX2STR_BUFFER];
bool route_found = false;
+ /* check for old entry match with new route origin,
+ * delete old entry.
+ */
for (old_route = old; old_route; old_route = old_route->next) {
- if (ospf6_route_is_same(old_route, route) &&
- (old_route->path.type == route->path.type) &&
- (old_route->path.cost == route->path.cost) &&
- (old_route->path.u.cost_e2 == route->path.u.cost_e2)) {
+ bool route_updated = false;
+
+ if (!ospf6_route_is_same(old_route, route) ||
+ (old_route->path.type != route->path.type))
+ continue;
+
+ /* Current and New route has same origin,
+ * delete old entry.
+ */
+ for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext,
+ o_path)) {
+ /* Check old route path and route has same
+ * origin.
+ */
+ if (o_path->area_id != route->path.area_id ||
+ (memcmp(&(o_path)->origin, &(route)->path.origin,
+ sizeof(struct ospf6_ls_origin)) != 0))
+ continue;
+
+ /* Cost is not same then delete current path */
+ if ((o_path->cost == route->path.cost) &&
+ (o_path->u.cost_e2 == route->path.u.cost_e2))
+ continue;
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
prefix2str(&old_route->prefix, buf,
sizeof(buf));
- zlog_debug("%s: old route %s path cost %u [%u]",
+ zlog_debug("%s: route %s cost old %u new %u is not same, replace route",
+ __PRETTY_FUNCTION__, buf,
+ o_path->cost, route->path.cost);
+ }
+
+ /* Remove selected current rout path's nh from
+ * effective nh list.
+ */
+ for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
+ for (ALL_LIST_ELEMENTS(old_route->nh_list,
+ rnode, rnext, rnh)) {
+ if (!ospf6_nexthop_is_same(rnh, nh))
+ continue;
+ listnode_delete(old_route->nh_list,
+ rnh);
+ ospf6_nexthop_delete(rnh);
+ route_updated = true;
+ }
+ }
+
+ listnode_delete(old_route->paths, o_path);
+ ospf6_path_free(o_path);
+
+ /* Current route's path (adv_router info) is similar
+ * to route being added.
+ * Replace current route's path with paths list head.
+ * Update FIB with effective NHs.
+ */
+ if (listcount(old_route->paths)) {
+ if (old_route->path.origin.id ==
+ route->path.origin.id &&
+ old_route->path.origin.adv_router ==
+ route->path.origin.adv_router) {
+ struct ospf6_path *h_path;
+
+ h_path = (struct ospf6_path *)
+ listgetdata(listhead(old_route->paths));
+ old_route->path.origin.type =
+ h_path->origin.type;
+ old_route->path.origin.id =
+ h_path->origin.id;
+ old_route->path.origin.adv_router =
+ h_path->origin.adv_router;
+ }
+
+ if (route_updated) {
+ for (ALL_LIST_ELEMENTS(old_route->paths,
+ anode, anext, o_path)) {
+ ospf6_merge_nexthops(
+ old_route->nh_list,
+ o_path->nh_list);
+ }
+ /* Update RIB/FIB with effective
+ * nh_list
+ */
+ if (ospf6->route_table->hook_add)
+ (*ospf6->route_table->hook_add)
+ (old_route);
+ break;
+ }
+ } else {
+ if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
+ prefix2str(&old_route->prefix, buf,
+ sizeof(buf));
+ zlog_debug("%s: route %s old cost %u new cost %u, delete old entry.",
+ __PRETTY_FUNCTION__, buf,
+ old_route->path.cost,
+ route->path.cost);
+ }
+ ospf6_route_remove(old_route,
+ ospf6->route_table);
+ break;
+ }
+ }
+ if (route_updated)
+ break;
+ }
+
+ /* Add new route */
+ for (old_route = old; old_route; old_route = old_route->next) {
+
+ /* Current and New Route prefix or route type
+ * is not same skip this current node.
+ */
+ if (!ospf6_route_is_same(old_route, route) ||
+ (old_route->path.type != route->path.type))
+ continue;
+
+ /* Old Route and New Route have Equal Cost, Merge NHs */
+ if ((old_route->path.cost == route->path.cost) &&
+ (old_route->path.u.cost_e2 == route->path.u.cost_e2)) {
+
+ if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
+ prefix2str(&old_route->prefix, buf,
+ sizeof(buf));
+ zlog_debug("%s: old route %s path cost %u e2 %u",
__PRETTY_FUNCTION__, buf,
old_route->path.cost,
- ospf6_route_is_same(old_route,
- route));
+ old_route->path.u.cost_e2);
}
route_found = true;
/* check if this path exists already in
@@ -232,9 +348,10 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
*/
for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
o_path)) {
- if ((o_path->origin.id == route->path.origin.id)
- && (o_path->origin.adv_router ==
- route->path.origin.adv_router))
+ if (o_path->area_id == route->path.area_id &&
+ (memcmp(&(o_path)->origin,
+ &(route)->path.origin,
+ sizeof(struct ospf6_ls_origin)) == 0))
break;
}
/* If path is not found in old_route paths's list,
@@ -262,12 +379,13 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
prefix2str(&route->prefix, buf,
sizeof(buf));
- zlog_debug("%s: route %s another path added with nh %u, Paths %u",
+ zlog_debug("%s: route %s another path added with nh %u, effective paths %u nh %u",
__PRETTY_FUNCTION__, buf,
listcount(ecmp_path->nh_list),
old_route->paths ?
listcount(old_route->paths)
- : 0);
+ : 0,
+ listcount(old_route->nh_list));
}
} else {
for (ALL_LIST_ELEMENTS_RO(o_path->nh_list,
@@ -313,6 +431,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
* route.
*/
ospf6_route_delete(route);
+
break;
}
}
@@ -426,11 +545,12 @@ void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
}
-void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
+void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa,
+ struct ospf6_route *asbr_entry)
{
struct ospf6_as_external_lsa *external;
struct prefix prefix;
- struct ospf6_route *route, *nroute;
+ struct ospf6_route *route, *nroute, *route_to_del;
char buf[PREFIX2STR_BUFFER];
external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
@@ -445,6 +565,35 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
return;
}
+ route_to_del = ospf6_route_create();
+ route_to_del->type = OSPF6_DEST_TYPE_NETWORK;
+ route_to_del->prefix.family = AF_INET6;
+ route_to_del->prefix.prefixlen = external->prefix.prefix_length;
+ ospf6_prefix_in6_addr(&route_to_del->prefix.u.prefix6,
+ &external->prefix);
+
+ route_to_del->path.origin.type = lsa->header->type;
+ route_to_del->path.origin.id = lsa->header->id;
+ route_to_del->path.origin.adv_router = lsa->header->adv_router;
+
+ if (asbr_entry) {
+ route_to_del->path.area_id = asbr_entry->path.area_id;
+ if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_E)) {
+ route_to_del->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
+ route_to_del->path.metric_type = 2;
+ route_to_del->path.cost = asbr_entry->path.cost;
+ route_to_del->path.u.cost_e2 =
+ OSPF6_ASBR_METRIC(external);
+ } else {
+ route_to_del->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
+ route_to_del->path.metric_type = 1;
+ route_to_del->path.cost =
+ asbr_entry->path.cost +
+ OSPF6_ASBR_METRIC(external);
+ route_to_del->path.u.cost_e2 = 0;
+ }
+ }
+
memset(&prefix, 0, sizeof(struct prefix));
prefix.family = AF_INET6;
prefix.prefixlen = external->prefix.prefix_length;
@@ -459,14 +608,25 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
return;
}
- for (ospf6_route_lock(route);
- route && ospf6_route_is_prefix(&prefix, route); route = nroute) {
+ if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
+ prefix2str(&prefix, buf, sizeof(buf));
+ zlog_debug("%s: Current route %s cost %u e2 %u, route to del cost %u e2 %u",
+ __PRETTY_FUNCTION__, buf, route->path.cost,
+ route->path.u.cost_e2,
+ route_to_del->path.cost,
+ route_to_del->path.u.cost_e2);
+ }
+
+ for (ospf6_route_lock(route); route &&
+ ospf6_route_is_prefix(&prefix, route); route = nroute) {
nroute = ospf6_route_next(route);
+
if (route->type != OSPF6_DEST_TYPE_NETWORK)
continue;
- /* Route has multiple ECMP paths remove,
- * matching path and update effective route's nh list.
+ /* Route has multiple ECMP paths, remove matching
+ * path. Update current route's effective nh list
+ * after removal of one of the path.
*/
if (listcount(route->paths) > 1) {
struct listnode *anode, *anext;
@@ -481,18 +641,36 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
*/
for (ALL_LIST_ELEMENTS(route->paths, anode, anext,
o_path)) {
- if (o_path->origin.type != lsa->header->type)
- continue;
- if (o_path->origin.id != lsa->header->id)
+ if ((o_path->origin.type != lsa->header->type)
+ || (o_path->origin.adv_router !=
+ lsa->header->adv_router) ||
+ (o_path->origin.id != lsa->header->id))
continue;
- if (o_path->origin.adv_router !=
- lsa->header->adv_router)
+
+ /* Compare LSA cost with current
+ * route info.
+ */
+ if (!asbr_entry && (o_path->cost !=
+ route_to_del->path.cost ||
+ o_path->u.cost_e2 !=
+ route_to_del->path.u.cost_e2)) {
+ if (IS_OSPF6_DEBUG_EXAMIN(
+ AS_EXTERNAL)) {
+ prefix2str(&prefix, buf,
+ sizeof(buf));
+ zlog_debug(
+ "%s: route %s to delete is not same, cost %u del cost %u. skip",
+ __PRETTY_FUNCTION__, buf,
+ route->path.cost,
+ route_to_del->path.cost);
+ }
continue;
+ }
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
prefix2str(&prefix, buf, sizeof(buf));
zlog_debug(
- "%s: route %s path found with nh %u",
+ "%s: route %s path found with nh %u to remove.",
__PRETTY_FUNCTION__, buf,
listcount(o_path->nh_list));
}
@@ -542,13 +720,13 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
listcount(route->nh_list));
}
- /* Update RIB/FIB w/ effective nh_list */
+ /* Update RIB/FIB with effective nh_list */
if (ospf6->route_table->hook_add)
(*ospf6->route_table->hook_add)(route);
- /* route's path is similar to lsa header,
- * replace route's path with route's
- * paths list head.
+ /* route's primary path is similar to LSA,
+ * replace route's primary path with
+ * route's paths list head.
*/
if (route->path.origin.id == lsa->header->id &&
route->path.origin.adv_router ==
@@ -568,12 +746,29 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
continue;
} else {
- if (route->path.origin.type != lsa->header->type)
- continue;
- if (route->path.origin.id != lsa->header->id)
+ /* Compare LSA origin and cost with current route info.
+ * if any check fails skip del this route node.
+ */
+ if (asbr_entry && (!ospf6_route_is_same_origin(route,
+ route_to_del) ||
+ (route->path.type != route_to_del->path.type) ||
+ (route->path.cost != route_to_del->path.cost) ||
+ (route->path.u.cost_e2 !=
+ route_to_del->path.u.cost_e2))) {
+ if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
+ prefix2str(&prefix, buf, sizeof(buf));
+ zlog_debug("%s: route %s to delete is not same, cost %u del cost %u. skip",
+ __PRETTY_FUNCTION__, buf,
+ route->path.cost,
+ route_to_del->path.cost);
+ }
continue;
- if (route->path.origin.adv_router !=
- lsa->header->adv_router)
+ }
+
+ if ((route->path.origin.type != lsa->header->type) ||
+ (route->path.origin.adv_router !=
+ lsa->header->adv_router) ||
+ (route->path.origin.id != lsa->header->id))
continue;
}
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
@@ -589,6 +784,8 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
}
if (route != NULL)
ospf6_route_unlock(route);
+
+ ospf6_route_delete(route_to_del);
}
void ospf6_asbr_lsentry_add(struct ospf6_route *asbr_entry)
@@ -622,7 +819,7 @@ void ospf6_asbr_lsentry_remove(struct ospf6_route *asbr_entry)
type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
router = ospf6_linkstate_prefix_adv_router(&asbr_entry->prefix);
for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, router, lsa))
- ospf6_asbr_lsa_remove(lsa);
+ ospf6_asbr_lsa_remove(lsa, asbr_entry);
}
diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h
index cc4f0272aa..bd160a6456 100644
--- a/ospf6d/ospf6_asbr.h
+++ b/ospf6d/ospf6_asbr.h
@@ -71,7 +71,8 @@ struct ospf6_as_external_lsa {
}
extern void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa);
-extern void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa);
+extern void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa,
+ struct ospf6_route *asbr_entry);
extern void ospf6_asbr_lsentry_add(struct ospf6_route *asbr_entry);
extern void ospf6_asbr_lsentry_remove(struct ospf6_route *asbr_entry);
diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c
index 19eb9a3fe6..ef0a093d13 100644
--- a/ospf6d/ospf6_route.c
+++ b/ospf6d/ospf6_route.c
@@ -469,6 +469,8 @@ int ospf6_route_cmp(struct ospf6_route *ra, struct ospf6_route *rb)
if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2) {
if (ra->path.u.cost_e2 != rb->path.u.cost_e2)
return (ra->path.u.cost_e2 - rb->path.u.cost_e2);
+ else
+ return (ra->path.cost - rb->path.cost);
} else {
if (ra->path.cost != rb->path.cost)
return (ra->path.cost - rb->path.cost);
@@ -627,10 +629,10 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
if (ospf6_route_is_identical(old, route)) {
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
zlog_debug(
- "%s %p: route add %p: needless update of %p",
+ "%s %p: route add %p: needless update of %p old cost %u",
ospf6_route_table_name(table),
(void *)table, (void *)route,
- (void *)old);
+ (void *)old, old->path.cost);
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
zlog_debug("%s: route add: needless update",
ospf6_route_table_name(table));
@@ -645,9 +647,10 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
}
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
- zlog_debug("%s %p: route add %p: update of %p",
+ zlog_debug("%s %p: route add %p cost %u: update of %p old cost %u",
ospf6_route_table_name(table), (void *)table,
- (void *)route, (void *)old);
+ (void *)route, route->path.cost, (void *)old,
+ old->path.cost);
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
zlog_debug("%s: route add: update",
ospf6_route_table_name(table));
@@ -686,13 +689,14 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
if (prev || next) {
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
zlog_debug(
- "%s %p: route add %p: another path: prev %p, next %p node refcount %u",
+ "%s %p: route add %p cost %u: another path: prev %p, next %p node ref %u",
ospf6_route_table_name(table), (void *)table,
- (void *)route, (void *)prev, (void *)next,
- node->lock);
+ (void *)route, route->path.cost, (void *)prev,
+ (void *)next, node->lock);
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
- zlog_debug("%s: route add: another path found",
- ospf6_route_table_name(table));
+ zlog_debug("%s: route add cost %u: another path found",
+ ospf6_route_table_name(table),
+ route->path.cost);
if (prev == NULL)
prev = next->prev;
@@ -814,9 +818,9 @@ void ospf6_route_remove(struct ospf6_route *route,
prefix2str(&route->prefix, buf, sizeof(buf));
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
- zlog_debug("%s %p: route remove %p: %s refcount %u",
+ zlog_debug("%s %p: route remove %p: %s cost %u refcount %u",
ospf6_route_table_name(table), (void *)table,
- (void *)route, buf, route->lock);
+ (void *)route, buf, route->path.cost, route->lock);
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
zlog_debug("%s: route remove: %s",
ospf6_route_table_name(table), buf);
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index 25d968fb68..afe2d7397b 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -72,7 +72,7 @@ static void ospf6_top_lsdb_hook_remove(struct ospf6_lsa *lsa)
{
switch (ntohs(lsa->header->type)) {
case OSPF6_LSTYPE_AS_EXTERNAL:
- ospf6_asbr_lsa_remove(lsa);
+ ospf6_asbr_lsa_remove(lsa, NULL);
break;
default:
@@ -96,11 +96,16 @@ static void ospf6_top_route_hook_remove(struct ospf6_route *route)
static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
{
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
- char buf[PREFIX2STR_BUFFER];
-
- prefix2str(&route->prefix, buf, sizeof(buf));
- zlog_debug("%s: brouter %s add with nh count %u",
- __PRETTY_FUNCTION__, buf, listcount(route->nh_list));
+ uint32_t brouter_id;
+ char brouter_name[16];
+
+ brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
+ inet_ntop(AF_INET, &brouter_id, brouter_name,
+ sizeof(brouter_name));
+ zlog_debug("%s: brouter %s add with adv router %x nh count %u",
+ __PRETTY_FUNCTION__, brouter_name,
+ route->path.origin.adv_router,
+ listcount(route->nh_list));
}
ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
ospf6_asbr_lsentry_add(route);
@@ -110,11 +115,15 @@ static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
{
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
- char buf[PREFIX2STR_BUFFER];
+ uint32_t brouter_id;
+ char brouter_name[16];
- prefix2str(&route->prefix, buf, sizeof(buf));
+ brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
+ inet_ntop(AF_INET, &brouter_id, brouter_name,
+ sizeof(brouter_name));
zlog_debug("%s: brouter %s del with nh count %u",
- __PRETTY_FUNCTION__, buf, listcount(route->nh_list));
+ __PRETTY_FUNCTION__, brouter_name,
+ listcount(route->nh_list));
}
route->flag |= OSPF6_ROUTE_REMOVE;
ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c
index 7bd644f43d..8dbf39ef5d 100644
--- a/ospfd/ospf_main.c
+++ b/ospfd/ospf_main.c
@@ -55,7 +55,7 @@
/* ospfd privileges */
zebra_capabilities_t _caps_p[] = {
- ZCAP_NET_RAW, ZCAP_BIND, ZCAP_NET_ADMIN,
+ ZCAP_NET_RAW, ZCAP_BIND, ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN
};
struct zebra_privs_t ospfd_privs = {
diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c
index 1560977ae8..fef77f574e 100644
--- a/ospfd/ospf_sr.c
+++ b/ospfd/ospf_sr.c
@@ -47,6 +47,7 @@
#include "thread.h"
#include "vty.h"
#include "zclient.h"
+#include <lib/json.h>
#include "ospfd/ospfd.h"
#include "ospfd/ospf_interface.h"
@@ -306,7 +307,8 @@ int ospf_sr_init(void)
{
int rc = -1;
- zlog_info("SR (%s): Initialize SR Data Base", __func__);
+ if (IS_DEBUG_OSPF_SR)
+ zlog_info("SR (%s): Initialize SR Data Base", __func__);
memset(&OspfSR, 0, sizeof(struct ospf_sr_db));
OspfSR.enabled = false;
@@ -675,6 +677,7 @@ static int ospf_zebra_send_mpls_ftn(int cmd, struct sr_nhlfe nhlfe)
SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
api_nh->labels[0] = nhlfe.label_out;
api_nh->label_num = 1;
+ api_nh->vrf_id = VRF_DEFAULT;
api.nexthop_num = 1;
}
@@ -1616,11 +1619,11 @@ static int ospf_sr_update_schedule(struct thread *t)
monotime(&stop_time);
- zlog_info(
- "SR (%s): SPF Processing Time(usecs): %lld\n",
- __func__,
- (stop_time.tv_sec - start_time.tv_sec) * 1000000LL
- + (stop_time.tv_usec - start_time.tv_usec));
+ if (IS_DEBUG_OSPF_SR)
+ zlog_debug("SR (%s): SPF Processing Time(usecs): %lld\n",
+ __func__,
+ (stop_time.tv_sec - start_time.tv_sec) * 1000000LL
+ + (stop_time.tv_usec - start_time.tv_usec));
OspfSR.update = false;
return 1;
@@ -2128,91 +2131,197 @@ DEFUN (no_sr_prefix_sid,
-static void show_vty_sr_node(struct vty *vty, struct sr_node *srn)
+static void show_sr_node(struct vty *vty, struct json_object *json,
+ struct sr_node *srn)
{
struct listnode *node;
struct sr_link *srl;
struct sr_prefix *srp;
struct interface *itf;
- char pref[16];
+ char pref[19];
char sid[22];
char label[8];
+ json_object *json_node = NULL, *json_algo, *json_obj;
+ json_object *json_prefix = NULL, *json_link = NULL;
/* Sanity Check */
if (srn == NULL)
return;
- vty_out(vty, "SR-Node: %s", inet_ntoa(srn->adv_router));
- vty_out(vty, "\tSRGB (Size/Label): %u/%u", srn->srgb.range_size,
- srn->srgb.lower_bound);
- vty_out(vty, "\tAlgorithm(s): %s",
- srn->algo[0] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF");
- for (int i = 1; i < ALGORITHM_COUNT; i++) {
- if (srn->algo[i] == SR_ALGORITHM_UNSET)
- continue;
- vty_out(vty, "/%s",
- srn->algo[i] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF");
- }
- if (srn->msd != 0)
- vty_out(vty, "\tMSD: %u", srn->msd);
-
- vty_out(vty,
- "\n\n Prefix or Link Label In Label Out "
- "Node or Adj. SID Interface Nexthop\n");
- vty_out(vty,
- "------------------ -------- --------- "
- "--------------------- --------- ---------------\n");
+ if (json) {
+ json_node = json_object_new_object();
+ json_object_string_add(json_node, "routerID",
+ inet_ntoa(srn->adv_router));
+ json_object_int_add(json_node, "srgbSize",
+ srn->srgb.range_size);
+ json_object_int_add(json_node, "srgbLabel",
+ srn->srgb.lower_bound);
+ json_algo = json_object_new_array();
+ json_object_object_add(json_node, "algorithms", json_algo);
+ for (int i = 0; i < ALGORITHM_COUNT; i++) {
+ if (srn->algo[i] == SR_ALGORITHM_UNSET)
+ continue;
+ json_obj = json_object_new_object();
+ char tmp[2];
+
+ snprintf(tmp, 2, "%u", i);
+ json_object_string_add(json_obj, tmp,
+ srn->algo[i] == SR_ALGORITHM_SPF ?
+ "SPF" : "S-SPF");
+ json_object_array_add(json_algo, json_obj);
+ }
+ if (srn->msd != 0)
+ json_object_int_add(json_node, "nodeMsd", srn->msd);
+ } else {
+ vty_out(vty, "SR-Node: %s", inet_ntoa(srn->adv_router));
+ vty_out(vty, "\tSRGB (Size/Label): %u/%u",
+ srn->srgb.range_size, srn->srgb.lower_bound);
+ vty_out(vty, "\tAlgorithm(s): %s",
+ srn->algo[0] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF");
+ for (int i = 1; i < ALGORITHM_COUNT; i++) {
+ if (srn->algo[i] == SR_ALGORITHM_UNSET)
+ continue;
+ vty_out(vty, "/%s",
+ srn->algo[i] == SR_ALGORITHM_SPF ?
+ "SPF" : "S-SPF");
+ }
+ if (srn->msd != 0)
+ vty_out(vty, "\tMSD: %u", srn->msd);
+ }
+
+ if (!json) {
+ vty_out(vty,
+ "\n\n Prefix or Link Label In Label Out "
+ "Node or Adj. SID Interface Nexthop\n");
+ vty_out(vty,
+ "------------------ -------- --------- "
+ "--------------------- --------- ---------------\n");
+ }
for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
- strncpy(pref, inet_ntoa(srp->nhlfe.prefv4.prefix), 16);
+ snprintf(pref, 19, "%s/%u",
+ inet_ntoa(srp->nhlfe.prefv4.prefix),
+ srp->nhlfe.prefv4.prefixlen);
snprintf(sid, 22, "SR Pfx (idx %u)", srp->sid);
if (srp->nhlfe.label_out == MPLS_LABEL_IMPLICIT_NULL)
sprintf(label, "pop");
else
sprintf(label, "%u", srp->nhlfe.label_out);
itf = if_lookup_by_index(srp->nhlfe.ifindex, VRF_DEFAULT);
- vty_out(vty, "%15s/%u %8u %9s %21s %9s %15s\n", pref,
- srp->nhlfe.prefv4.prefixlen, srp->nhlfe.label_in, label,
- sid, itf ? itf->name : "-",
- inet_ntoa(srp->nhlfe.nexthop));
+ if (json) {
+ if (!json_prefix) {
+ json_prefix = json_object_new_array();
+ json_object_object_add(json_node,
+ "extendedPrefix", json_prefix);
+ }
+ json_obj = json_object_new_object();
+ json_object_string_add(json_obj, "prefix", pref);
+ json_object_int_add(json_obj, "sid", srp->sid);
+ json_object_int_add(json_obj, "inputLabel",
+ srp->nhlfe.label_in);
+ json_object_string_add(json_obj, "outputLabel",
+ label);
+ json_object_string_add(json_obj, "interface",
+ itf ? itf->name : "-");
+ json_object_string_add(json_obj, "nexthop",
+ inet_ntoa(srp->nhlfe.nexthop));
+ json_object_array_add(json_prefix, json_obj);
+ } else {
+ vty_out(vty, "%18s %8u %9s %21s %9s %15s\n",
+ pref, srp->nhlfe.label_in, label,
+ sid, itf ? itf->name : "-",
+ inet_ntoa(srp->nhlfe.nexthop));
+ }
}
for (ALL_LIST_ELEMENTS_RO(srn->ext_link, node, srl)) {
- strncpy(pref, inet_ntoa(srl->nhlfe[0].prefv4.prefix), 16);
+ snprintf(pref, 19, "%s/%u",
+ inet_ntoa(srl->nhlfe[0].prefv4.prefix),
+ srl->nhlfe[0].prefv4.prefixlen);
snprintf(sid, 22, "SR Adj. (lbl %u)", srl->sid[0]);
if (srl->nhlfe[0].label_out == MPLS_LABEL_IMPLICIT_NULL)
sprintf(label, "pop");
else
sprintf(label, "%u", srl->nhlfe[0].label_out);
itf = if_lookup_by_index(srl->nhlfe[0].ifindex, VRF_DEFAULT);
- vty_out(vty, "%15s/%u %8u %9s %21s %9s %15s\n", pref,
- srl->nhlfe[0].prefv4.prefixlen, srl->nhlfe[0].label_in,
- label, sid, itf ? itf->name : "-",
- inet_ntoa(srl->nhlfe[0].nexthop));
- snprintf(sid, 22, "SR Adj. (lbl %u)", srl->sid[1]);
- if (srl->nhlfe[1].label_out == MPLS_LABEL_IMPLICIT_NULL)
- sprintf(label, "pop");
- else
- sprintf(label, "%u", srl->nhlfe[0].label_out);
- vty_out(vty, "%15s/%u %8u %9s %21s %9s %15s\n", pref,
- srl->nhlfe[1].prefv4.prefixlen, srl->nhlfe[1].label_in,
- label, sid, itf ? itf->name : "-",
- inet_ntoa(srl->nhlfe[1].nexthop));
+ if (json) {
+ if (!json_link) {
+ json_link = json_object_new_array();
+ json_object_object_add(json_node,
+ "extendedLink", json_link);
+ }
+ /* Primary Link */
+ json_obj = json_object_new_object();
+ json_object_string_add(json_obj, "prefix", pref);
+ json_object_int_add(json_obj, "sid", srl->sid[0]);
+ json_object_int_add(json_obj, "inputLabel",
+ srl->nhlfe[0].label_in);
+ json_object_string_add(json_obj, "outputLabel",
+ label);
+ json_object_string_add(json_obj, "interface",
+ itf ? itf->name : "-");
+ json_object_string_add(json_obj, "nexthop",
+ inet_ntoa(srl->nhlfe[0].nexthop));
+ json_object_array_add(json_link, json_obj);
+ /* Backup Link */
+ json_obj = json_object_new_object();
+ snprintf(sid, 22, "SR Adj. (lbl %u)", srl->sid[1]);
+ if (srl->nhlfe[1].label_out == MPLS_LABEL_IMPLICIT_NULL)
+ sprintf(label, "pop");
+ else
+ sprintf(label, "%u", srl->nhlfe[0].label_out);
+ json_object_string_add(json_obj, "prefix", pref);
+ json_object_int_add(json_obj, "sid", srl->sid[1]);
+ json_object_int_add(json_obj, "inputLabel",
+ srl->nhlfe[1].label_in);
+ json_object_string_add(json_obj, "outputLabel",
+ label);
+ json_object_string_add(json_obj, "interface",
+ itf ? itf->name : "-");
+ json_object_string_add(json_obj, "nexthop",
+ inet_ntoa(srl->nhlfe[1].nexthop));
+ json_object_array_add(json_link, json_obj);
+ } else {
+ vty_out(vty, "%18s %8u %9s %21s %9s %15s\n",
+ pref, srl->nhlfe[0].label_in,
+ label, sid, itf ? itf->name : "-",
+ inet_ntoa(srl->nhlfe[0].nexthop));
+ snprintf(sid, 22, "SR Adj. (lbl %u)", srl->sid[1]);
+ if (srl->nhlfe[1].label_out == MPLS_LABEL_IMPLICIT_NULL)
+ sprintf(label, "pop");
+ else
+ sprintf(label, "%u", srl->nhlfe[1].label_out);
+ vty_out(vty, "%18s %8u %9s %21s %9s %15s\n",
+ pref, srl->nhlfe[1].label_in,
+ label, sid, itf ? itf->name : "-",
+ inet_ntoa(srl->nhlfe[1].nexthop));
+ }
}
- vty_out(vty, "\n");
+ if (json)
+ json_object_array_add(json, json_node);
+ else
+ vty_out(vty, "\n");
}
-static void show_srdb_entry(struct hash_backet *backet, void *args)
+static void show_vty_srdb(struct hash_backet *backet, void *args)
{
struct vty *vty = (struct vty *)args;
struct sr_node *srn = (struct sr_node *)backet->data;
- show_vty_sr_node(vty, srn);
+ show_sr_node(vty, NULL, srn);
+}
+
+static void show_json_srdb(struct hash_backet *backet, void *args)
+{
+ struct json_object *json = (struct json_object *)args;
+ struct sr_node *srn = (struct sr_node *)backet->data;
+
+ show_sr_node(NULL, json, srn);
}
DEFUN (show_ip_opsf_srdb,
show_ip_ospf_srdb_cmd,
- "show ip ospf database segment-routing [adv-router A.B.C.D|self-originate]",
+ "show ip ospf database segment-routing [adv-router A.B.C.D|self-originate] [json]",
SHOW_STR
IP_STR
OSPF_STR
@@ -2220,23 +2329,41 @@ DEFUN (show_ip_opsf_srdb,
"Show Segment Routing Data Base\n"
"Advertising SR node\n"
"Advertising SR node ID (as an IP address)\n"
- "Self-originated SR node\n")
+ "Self-originated SR node\n"
+ JSON_STR)
{
int idx = 0;
struct in_addr rid;
struct sr_node *srn;
+ u_char uj = use_json(argc, argv);
+ json_object *json = NULL, *json_node_array = NULL;
if (!OspfSR.enabled) {
vty_out(vty, "Segment Routing is disabled on this router\n");
return CMD_WARNING;
}
- vty_out(vty, "\n OSPF Segment Routing database for ID %s\n\n",
- inet_ntoa(OspfSR.self->adv_router));
+ if (uj) {
+ json = json_object_new_object();
+ json_node_array = json_object_new_array();
+ json_object_string_add(json, "srdbID",
+ inet_ntoa(OspfSR.self->adv_router));
+ json_object_object_add(json, "srNodes", json_node_array);
+ } else {
+ vty_out(vty,
+ "\n\t\tOSPF Segment Routing database for ID %s\n\n",
+ inet_ntoa(OspfSR.self->adv_router));
+ }
if (argv_find(argv, argc, "self-originate", &idx)) {
srn = OspfSR.self;
- show_vty_sr_node(vty, srn);
+ show_sr_node(vty, json_node_array, srn);
+ if (uj) {
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(json,
+ JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
return CMD_SUCCESS;
}
@@ -2250,15 +2377,32 @@ DEFUN (show_ip_opsf_srdb,
/* Get the SR Node from the SRDB */
srn = (struct sr_node *)hash_lookup(OspfSR.neighbors,
(void *)&rid);
- show_vty_sr_node(vty, srn);
+ show_sr_node(vty, json_node_array, srn);
+ if (uj) {
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(json,
+ JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
return CMD_SUCCESS;
}
/* No parameters have been provided, Iterate through all the SRDB */
- hash_iterate(
- OspfSR.neighbors,
- (void (*)(struct hash_backet *, void *))show_srdb_entry,
- (void *)vty);
+ if (uj) {
+ hash_iterate(
+ OspfSR.neighbors,
+ (void (*)(struct hash_backet *, void *))show_json_srdb,
+ (void *)json_node_array);
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(json,
+ JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ } else {
+ hash_iterate(
+ OspfSR.neighbors,
+ (void (*)(struct hash_backet *, void *))show_vty_srdb,
+ (void *)vty);
+ }
return CMD_SUCCESS;
}
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 79af4a55fb..b3c4e4a365 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -707,6 +707,7 @@ static void ospf_finish_final(struct ospf *ospf)
OSPF_TIMER_OFF(ospf->t_read);
OSPF_TIMER_OFF(ospf->t_write);
OSPF_TIMER_OFF(ospf->t_opaque_lsa_self);
+ OSPF_TIMER_OFF(ospf->t_sr_update);
close(ospf->fd);
stream_free(ospf->ibuf);
diff --git a/tests/.gitignore b/tests/.gitignore
index ab1d55b548..c2fe9c8890 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -24,10 +24,12 @@ __pycache__
/bgpd/test_ecommunity
/bgpd/test_mp_attr
/bgpd/test_mpath
+/bgpd/test_packet
/isisd/test_fuzz_isis_tlv
/isisd/test_fuzz_isis_tlv_tests.h
/isisd/test_isis_vertex_queue
/lib/cli/test_cli
+/lib/cli/test_cli_clippy.c
/lib/cli/test_commands
/lib/cli/test_commands_defun.c
/lib/test_buffer
@@ -38,6 +40,7 @@ __pycache__
/lib/test_memory
/lib/test_nexthop_iter
/lib/test_privs
+/lib/test_ringbuf
/lib/test_srcdest_table
/lib/test_segv
/lib/test_sig
@@ -48,3 +51,4 @@ __pycache__
/lib/test_ttable
/lib/test_zmq
/ospf6d/test_lsdb
+/ospf6d/test_lsdb_clippy.c
diff --git a/tests/lib/test_ringbuf.py b/tests/lib/test_ringbuf.py
index 860d872f86..5d994ddd7b 100644
--- a/tests/lib/test_ringbuf.py
+++ b/tests/lib/test_ringbuf.py
@@ -1,4 +1,6 @@
import frrtest
-class TestRingbuf(frrtest.TestExitNonzero):
+class TestRingbuf(frrtest.TestMultiOut):
program = './test_ringbuf'
+
+TestRingbuf.exit_cleanly()
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 8719226281..bf9d70bae9 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -539,7 +539,7 @@ int vtysh_mark_file(const char *filename)
}
vty = vty_new();
- vty->fd = 0; /* stdout */
+ vty->wfd = STDERR_FILENO;
vty->type = VTY_TERM;
vty->node = CONFIG_NODE;
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index aa1dd407eb..c055d29d4b 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -398,7 +398,7 @@ static int vtysh_read_file(FILE *confp)
int ret;
vty = vty_new();
- vty->fd = 0; /* stdout */
+ vty->wfd = STDERR_FILENO;
vty->type = VTY_TERM;
vty->node = CONFIG_NODE;
@@ -448,6 +448,11 @@ void vtysh_config_write()
sprintf(line, "hostname %s", cmd_hostname_get());
vtysh_config_parse_line(NULL, line);
}
+
+ if (cmd_domainname_get()) {
+ sprintf(line, "domainname %s", cmd_domainname_get());
+ vtysh_config_parse_line(NULL, line);
+ }
if (vtysh_write_integrated == WRITE_INTEGRATED_NO)
vtysh_config_parse_line(NULL,
"no service integrated-vtysh-config");
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 9fc5afff0f..d960dbd937 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -1019,6 +1019,8 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
break;
}
if (re) {
+ stream_putc(s, re->type);
+ stream_putw(s, re->instance);
stream_putc(s, re->distance);
stream_putl(s, re->metric);
num = 0;
@@ -1054,6 +1056,8 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
}
stream_putc_at(s, nump, num);
} else {
+ stream_putc(s, 0); // type
+ stream_putw(s, 0); // instance
stream_putc(s, 0); // distance
stream_putl(s, 0); // metric
stream_putc(s, 0); // nexthops
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 20b9e94288..e07dc6059f 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -1135,7 +1135,8 @@ static void zvni_print_hash(struct hash_backet *backet, void *ctxt[])
"%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
zvni->vni, "L2",
zvni->vxlan_if ? zvni->vxlan_if->name : "unknown",
- num_macs, num_neigh, num_vteps,
+ num_macs, num_neigh,
+ num_vteps,
vrf_id_to_name(zvni->vrf_id));
else {
char vni_str[VNI_STR_LEN];
@@ -1858,20 +1859,18 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
return -1;
/* only need to delete the entry from bgp if we sent it before */
- if (advertise_gw_macip_enabled(zvni)) {
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
- ifp->vrf_id, ifp->name,
- ifp->ifindex, zvni->vni,
- prefix_mac2str(&(n->emac),
- NULL,
- ETHER_ADDR_STRLEN),
- ipaddr2str(ip, buf2, sizeof(buf2)));
-
- /* Remove neighbor from BGP. */
- zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
- ZEBRA_MACIP_TYPE_GW);
- }
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
+ ifp->vrf_id, ifp->name,
+ ifp->ifindex, zvni->vni,
+ prefix_mac2str(&(n->emac),
+ NULL,
+ ETHER_ADDR_STRLEN),
+ ipaddr2str(ip, buf2, sizeof(buf2)));
+
+ /* Remove neighbor from BGP. */
+ zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
+ ZEBRA_MACIP_TYPE_GW);
/* Delete this neighbor entry. */
zvni_neigh_del(zvni, n);
@@ -6256,15 +6255,33 @@ int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags)
zebra_vxlan_process_l3vni_oper_down(zl3vni);
zl3vni->svi_if = NULL;
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
+ zl3vni->local_vtep_ip = vxl->vtep_ip;
if (is_l3vni_oper_up(zl3vni))
zebra_vxlan_process_l3vni_oper_up(
zl3vni);
}
}
+ /*
+ * local-ip change - process oper down, associate with new
+ * local-ip and then process oper up again
+ */
+ if (chgflags & ZEBRA_VXLIF_LOCAL_IP_CHANGE) {
+ if (if_is_operative(ifp)) {
+ zebra_vxlan_process_l3vni_oper_down(zl3vni);
+ zl3vni->local_vtep_ip = vxl->vtep_ip;
+ if (is_l3vni_oper_up(zl3vni))
+ zebra_vxlan_process_l3vni_oper_up(
+ zl3vni);
+ }
+ }
+
+ /* Update local tunnel IP. */
+ zl3vni->local_vtep_ip = vxl->vtep_ip;
+
/* if we have a valid new master, process l3-vni oper up */
if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
- if (is_l3vni_oper_up(zl3vni))
+ if (if_is_operative(ifp) && is_l3vni_oper_up(zl3vni))
zebra_vxlan_process_l3vni_oper_up(zl3vni);
}
} else {
@@ -6704,6 +6721,10 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
struct interface *vlan_if = NULL;
struct interface *vrr_if = NULL;
+ zvni = zvni_lookup(vni);
+ if (!zvni)
+ return 0;
+
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"EVPN gateway macip Adv %s on VNI %d , currently %s",
@@ -6712,10 +6733,6 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
? "enabled"
: "disabled");
- zvni = zvni_lookup(vni);
- if (!zvni)
- return 0;
-
if (zvni->advertise_gw_macip == advertise)
return 0;
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 98cb54f7b8..bca8a509d8 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -1166,12 +1166,12 @@ static int zread_route_add(struct zserv *client, u_short length,
switch (api_nh->type) {
case NEXTHOP_TYPE_IFINDEX:
nexthop = route_entry_nexthop_ifindex_add(
- re, api_nh->ifindex, re->vrf_id);
+ re, api_nh->ifindex, api_nh->vrf_id);
break;
case NEXTHOP_TYPE_IPV4:
nexthop = route_entry_nexthop_ipv4_add(
re, &api_nh->gate.ipv4, NULL,
- re->vrf_id);
+ api_nh->vrf_id);
break;
case NEXTHOP_TYPE_IPV4_IFINDEX: {
@@ -1188,7 +1188,7 @@ static int zread_route_add(struct zserv *client, u_short length,
nexthop = route_entry_nexthop_ipv4_ifindex_add(
re, &api_nh->gate.ipv4, NULL, ifindex,
- re->vrf_id);
+ api_nh->vrf_id);
/* if this an EVPN route entry,
program the nh as neigh
@@ -1211,12 +1211,12 @@ static int zread_route_add(struct zserv *client, u_short length,
}
case NEXTHOP_TYPE_IPV6:
nexthop = route_entry_nexthop_ipv6_add(
- re, &api_nh->gate.ipv6, re->vrf_id);
+ re, &api_nh->gate.ipv6, api_nh->vrf_id);
break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
nexthop = route_entry_nexthop_ipv6_ifindex_add(
re, &api_nh->gate.ipv6, api_nh->ifindex,
- re->vrf_id);
+ api_nh->vrf_id);
break;
case NEXTHOP_TYPE_BLACKHOLE:
nexthop = route_entry_nexthop_blackhole_add(