summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_evpn.c69
-rw-r--r--bgpd/bgp_evpn_vty.c20
-rw-r--r--bgpd/bgp_route.c23
-rw-r--r--bgpd/bgp_routemap.c4
-rw-r--r--bgpd/bgp_vty.c85
-rw-r--r--doc/user/ospfd.rst9
-rw-r--r--lib/command.h1
-rw-r--r--ospfd/ospf_memory.c1
-rw-r--r--ospfd/ospf_memory.h1
-rw-r--r--ospfd/ospf_ri.c576
-rw-r--r--ospfd/ospf_ri.h66
-rw-r--r--ospfd/ospf_te.c8
-rw-r--r--vtysh/vtysh.c2
-rw-r--r--zebra/zebra_vty.c3
-rw-r--r--zebra/zebra_vxlan.c36
15 files changed, 638 insertions, 266 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index c91a2ab6bd..cff050a9ef 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -1693,6 +1693,58 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
}
/*
+ * If the local route was not selected evict it and tell zebra to re-add
+ * the best remote dest.
+ *
+ * Typically a local path added by zebra is expected to be selected as
+ * best. In which case when a remote path wins as best (later)
+ * evpn_route_select_install itself evicts the older-local-best path.
+ *
+ * However if bgp's add and zebra's add cross paths (race condition) it
+ * is possible that the local path is no longer the "older" best path.
+ * It is a path that was never designated as best and hence requires
+ * additional handling to prevent bgp from injecting and holding on to a
+ * non-best local path.
+ */
+static void evpn_cleanup_local_non_best_route(struct bgp *bgp,
+ struct bgpevpn *vpn,
+ struct bgp_node *rn,
+ struct bgp_path_info *local_pi)
+{
+ struct bgp_path_info *tmp_pi;
+ struct bgp_path_info *curr_select = NULL;
+ uint8_t flags = 0;
+ char buf[PREFIX_STRLEN];
+
+ /* local path was not picked as the winner; kick it out */
+ if (bgp_debug_zebra(NULL)) {
+ zlog_debug("evicting local evpn prefix %s as remote won",
+ prefix2str(&rn->p, buf, sizeof(buf)));
+ }
+ evpn_delete_old_local_route(bgp, vpn, rn, local_pi);
+ bgp_path_info_reap(rn, local_pi);
+
+ /* tell zebra to re-add the best remote path */
+ for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) {
+ if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_SELECTED)) {
+ curr_select = tmp_pi;
+ break;
+ }
+ }
+ if (curr_select &&
+ curr_select->type == ZEBRA_ROUTE_BGP
+ && curr_select->sub_type == BGP_ROUTE_IMPORTED) {
+ if (curr_select->attr->sticky)
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
+ if (curr_select->attr->default_gw)
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
+ evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p,
+ curr_select->attr->nexthop, flags,
+ mac_mobility_seqnum(curr_select->attr));
+ }
+}
+
+/*
* Create or update EVPN route (of type based on prefix) for specified VNI
* and schedule for processing.
*/
@@ -1754,10 +1806,23 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
assert(pi);
attr_new = pi->attr;
+ /* lock ri to prevent freeing in evpn_route_select_install */
+ bgp_path_info_lock(pi);
/* Perform route selection; this is just to set the flags correctly
* as local route in the VNI always wins.
*/
evpn_route_select_install(bgp, vpn, rn);
+ /*
+ * If the new local route was not selected evict it and tell zebra
+ * to re-add the best remote dest. BGP doesn't retain non-best local
+ * routes.
+ */
+ if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
+ route_change = 0;
+ evpn_cleanup_local_non_best_route(bgp, vpn, rn, pi);
+ }
+ bgp_path_info_unlock(pi);
+
bgp_unlock_node(rn);
/* If this is a new route or some attribute has changed, export the
@@ -1928,8 +1993,10 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
/* Delete route entry in the VNI route table. This can just be removed.
*/
delete_evpn_route_entry(bgp, afi, safi, rn, &pi);
- if (pi)
+ if (pi) {
bgp_path_info_reap(rn, pi);
+ evpn_route_select_install(bgp, vpn, rn);
+ }
bgp_unlock_node(rn);
return 0;
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index 29f9f64cca..aa5eabeade 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -3195,7 +3195,7 @@ DEFUN (no_bgp_evpn_advertise_type5,
*/
DEFUN(show_bgp_l2vpn_evpn_vni,
show_bgp_l2vpn_evpn_vni_cmd,
- "show bgp l2vpn evpn vni [(1-16777215)] [json]",
+ "show bgp l2vpn evpn vni [" CMD_VNI_RANGE "] [json]",
SHOW_STR
BGP_STR
L2VPN_HELP_STR
@@ -3623,7 +3623,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_esi,
* Display per-VNI EVPN routing table.
*/
DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
- "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
+ "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " [<type <macip|multicast> | vtep A.B.C.D>] [json]",
SHOW_STR
BGP_STR
L2VPN_HELP_STR
@@ -3696,7 +3696,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
*/
DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
show_bgp_l2vpn_evpn_route_vni_macip_cmd,
- "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
+ "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD] [json]",
SHOW_STR
BGP_STR
L2VPN_HELP_STR
@@ -3766,7 +3766,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
*/
DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
- "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
+ "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D [json]",
SHOW_STR
BGP_STR
L2VPN_HELP_STR
@@ -4019,7 +4019,7 @@ DEFUN(test_withdraw_evpn_type4_route,
}
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
- "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
+ "show bgp evpn vni [" CMD_VNI_RANGE "]", SHOW_STR BGP_STR EVPN_HELP_STR
"Show VNI\n"
"VNI number\n")
@@ -4060,7 +4060,7 @@ ALIAS_HIDDEN(
ALIAS_HIDDEN(
show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
- "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
+ "show bgp evpn route vni " CMD_VNI_RANGE " [<type <macip|multicast> | vtep A.B.C.D>]",
SHOW_STR BGP_STR EVPN_HELP_STR
"EVPN route information\n"
"VXLAN Network Identifier\n"
@@ -4073,7 +4073,7 @@ ALIAS_HIDDEN(
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
show_bgp_evpn_route_vni_macip_cmd,
- "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
+ "show bgp evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD]",
SHOW_STR BGP_STR EVPN_HELP_STR
"EVPN route information\n"
"VXLAN Network Identifier\n"
@@ -4085,7 +4085,7 @@ ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
show_bgp_evpn_route_vni_multicast_cmd,
- "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
+ "show bgp evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D",
SHOW_STR BGP_STR EVPN_HELP_STR
"EVPN route information\n"
"VXLAN Network Identifier\n"
@@ -4108,7 +4108,7 @@ ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
DEFUN_NOSH (bgp_evpn_vni,
bgp_evpn_vni_cmd,
- "vni (1-16777215)",
+ "vni " CMD_VNI_RANGE,
"VXLAN Network Identifier\n"
"VNI number\n")
{
@@ -4134,7 +4134,7 @@ DEFUN_NOSH (bgp_evpn_vni,
DEFUN (no_bgp_evpn_vni,
no_bgp_evpn_vni_cmd,
- "no vni (1-16777215)",
+ "no vni " CMD_VNI_RANGE,
NO_STR
"VXLAN Network Identifier\n"
"VNI number\n")
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 4542d0ec27..8ae74a008c 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -453,6 +453,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
char exist_buf[PATH_ADDPATH_STR_BUFFER];
uint32_t new_mm_seq;
uint32_t exist_mm_seq;
+ int nh_cmp;
*paths_eq = 0;
@@ -545,6 +546,28 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
exist_mm_seq);
return 0;
}
+
+ /*
+ * if sequence numbers are the same path with the lowest IP
+ * wins
+ */
+ nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
+ if (nh_cmp < 0) {
+ if (debug)
+ zlog_debug(
+ "%s: %s wins over %s due to same MM seq %u and lower IP %s",
+ pfx_buf, new_buf, exist_buf, new_mm_seq,
+ inet_ntoa(new->attr->nexthop));
+ return 1;
+ }
+ if (nh_cmp > 0) {
+ if (debug)
+ zlog_debug(
+ "%s: %s loses to %s due to same MM seq %u and higher IP %s",
+ pfx_buf, new_buf, exist_buf, new_mm_seq,
+ inet_ntoa(new->attr->nexthop));
+ return 0;
+ }
}
/* 1. Weight check. */
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 60a4e994c9..f7c4175383 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -3438,7 +3438,7 @@ DEFUN (no_match_evpn_route_type,
DEFUN (match_evpn_vni,
match_evpn_vni_cmd,
- "match evpn vni (1-16777215)",
+ "match evpn vni " CMD_VNI_RANGE,
MATCH_STR
EVPN_HELP_STR
"Match VNI\n"
@@ -3450,7 +3450,7 @@ DEFUN (match_evpn_vni,
DEFUN (no_match_evpn_vni,
no_match_evpn_vni_cmd,
- "no match evpn vni (1-16777215)",
+ "no match evpn vni " CMD_VNI_RANGE,
NO_STR
MATCH_STR
EVPN_HELP_STR
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 948cc8518c..c57cd38151 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -822,6 +822,87 @@ DEFUN_HIDDEN (no_bgp_multiple_instance,
return CMD_SUCCESS;
}
+DEFUN_HIDDEN (bgp_local_mac,
+ bgp_local_mac_cmd,
+ "bgp local-mac vni " CMD_VNI_RANGE " mac WORD seq (0-4294967295)",
+ BGP_STR
+ "Local MAC config\n"
+ "VxLAN Network Identifier\n"
+ "VNI number\n"
+ "local mac\n"
+ "mac address\n"
+ "mac-mobility sequence\n"
+ "seq number\n")
+{
+ int rv;
+ vni_t vni;
+ struct ethaddr mac;
+ struct ipaddr ip;
+ uint32_t seq;
+ struct bgp *bgp;
+
+ vni = strtoul(argv[3]->arg, NULL, 10);
+ if (!prefix_str2mac(argv[5]->arg, &mac)) {
+ vty_out(vty, "%% Malformed MAC address\n");
+ return CMD_WARNING;
+ }
+ memset(&ip, 0, sizeof(ip));
+ seq = strtoul(argv[7]->arg, NULL, 10);
+
+ bgp = bgp_get_default();
+ if (!bgp) {
+ vty_out(vty, "Default BGP instance is not there\n");
+ return CMD_WARNING;
+ }
+
+ rv = bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, 0 /* flags */, seq);
+ if (rv < 0) {
+ vty_out(vty, "Internal error\n");
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_HIDDEN (no_bgp_local_mac,
+ no_bgp_local_mac_cmd,
+ "no bgp local-mac vni " CMD_VNI_RANGE " mac WORD",
+ NO_STR
+ BGP_STR
+ "Local MAC config\n"
+ "VxLAN Network Identifier\n"
+ "VNI number\n"
+ "local mac\n"
+ "mac address\n")
+{
+ int rv;
+ vni_t vni;
+ struct ethaddr mac;
+ struct ipaddr ip;
+ struct bgp *bgp;
+
+ vni = strtoul(argv[4]->arg, NULL, 10);
+ if (!prefix_str2mac(argv[6]->arg, &mac)) {
+ vty_out(vty, "%% Malformed MAC address\n");
+ return CMD_WARNING;
+ }
+ memset(&ip, 0, sizeof(ip));
+
+ bgp = bgp_get_default();
+ if (!bgp) {
+ vty_out(vty, "Default BGP instance is not there\n");
+ return CMD_WARNING;
+ }
+
+ rv = bgp_evpn_local_macip_del(bgp, vni, &mac, &ip);
+ if (rv < 0) {
+ vty_out(vty, "Internal error\n");
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
#if (CONFDATE > 20190601)
CPP_NOTICE("bgpd: time to remove deprecated cli bgp config-type cisco")
CPP_NOTICE("This includes BGP_OPT_CISCO_CONFIG")
@@ -12593,6 +12674,10 @@ void bgp_vty_init(void)
install_element(CONFIG_NODE, &bgp_config_type_cmd);
install_element(CONFIG_NODE, &no_bgp_config_type_cmd);
+ /* "bgp local-mac" hidden commands. */
+ install_element(CONFIG_NODE, &bgp_local_mac_cmd);
+ install_element(CONFIG_NODE, &no_bgp_local_mac_cmd);
+
/* bgp route-map delay-timer commands. */
install_element(CONFIG_NODE, &bgp_set_route_map_delay_timer_cmd);
install_element(CONFIG_NODE, &no_bgp_set_route_map_delay_timer_cmd);
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index e843136396..b6a7cd5de0 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -979,14 +979,17 @@ Traffic Engineering
Router Information
==================
-.. index:: router-info [as | area <A.B.C.D>]
-.. clicmd:: router-info [as | area <A.B.C.D>]
+.. index:: router-info [as | area]
+.. clicmd:: router-info [as | area]
.. index:: no router-info
.. clicmd:: no router-info
Enable Router Information (:rfc:`4970`) LSA advertisement with AS scope
- (default) or Area scope flooding when area is specified.
+ (default) or Area scope flooding when area is specified. Old syntax
+ `router-info area <A.B.C.D>` is always supported but mark as deprecated
+ as the area ID is no more necessary. Indeed, router information support
+ multi-area and detect automatically the areas.
.. index:: pce address <A.B.C.D>
.. clicmd:: pce address <A.B.C.D>
diff --git a/lib/command.h b/lib/command.h
index 873ecdda98..11514fd5e8 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -378,6 +378,7 @@ struct cmd_node {
#define WATCHFRR_STR "watchfrr information\n"
#define ZEBRA_STR "Zebra information\n"
+#define CMD_VNI_RANGE "(1-16777215)"
#define CONF_BACKUP_EXT ".sav"
/* Command warnings. */
diff --git a/ospfd/ospf_memory.c b/ospfd/ospf_memory.c
index 1332104b0a..c4dc0136ed 100644
--- a/ospfd/ospf_memory.c
+++ b/ospfd/ospf_memory.c
@@ -52,6 +52,7 @@ DEFINE_MTYPE(OSPFD, OSPF_IF_INFO, "OSPF if info")
DEFINE_MTYPE(OSPFD, OSPF_IF_PARAMS, "OSPF if params")
DEFINE_MTYPE(OSPFD, OSPF_MESSAGE, "OSPF message")
DEFINE_MTYPE(OSPFD, OSPF_MPLS_TE, "OSPF MPLS parameters")
+DEFINE_MTYPE(OSPFD, OSPF_ROUTER_INFO, "OSPF Router Info parameters")
DEFINE_MTYPE(OSPFD, OSPF_PCE_PARAMS, "OSPF PCE parameters")
DEFINE_MTYPE(OSPFD, OSPF_EXT_PARAMS, "OSPF Extended parameters")
DEFINE_MTYPE(OSPFD, OSPF_SR_PARAMS, "OSPF Segment Routing parameters")
diff --git a/ospfd/ospf_memory.h b/ospfd/ospf_memory.h
index 50c6f33ecf..861de64c25 100644
--- a/ospfd/ospf_memory.h
+++ b/ospfd/ospf_memory.h
@@ -51,6 +51,7 @@ DECLARE_MTYPE(OSPF_IF_INFO)
DECLARE_MTYPE(OSPF_IF_PARAMS)
DECLARE_MTYPE(OSPF_MESSAGE)
DECLARE_MTYPE(OSPF_MPLS_TE)
+DECLARE_MTYPE(OSPF_ROUTER_INFO)
DECLARE_MTYPE(OSPF_PCE_PARAMS)
DECLARE_MTYPE(OSPF_SR_PARAMS)
DECLARE_MTYPE(OSPF_EXT_PARAMS)
diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c
index bef16761f2..72f6dbe08e 100644
--- a/ospfd/ospf_ri.c
+++ b/ospfd/ospf_ri.c
@@ -59,60 +59,6 @@
#include "ospfd/ospf_ri.h"
#include "ospfd/ospf_errors.h"
-/* Store Router Information PCE TLV and SubTLV in network byte order. */
-struct ospf_pce_info {
- bool enabled;
- struct ri_tlv_pce pce_header;
- struct ri_pce_subtlv_address pce_address;
- struct ri_pce_subtlv_path_scope pce_scope;
- struct list *pce_domain;
- struct list *pce_neighbor;
- struct ri_pce_subtlv_cap_flag pce_cap_flag;
-};
-
-/*
- * Store Router Information Segment Routing TLV and SubTLV
- * in network byte order
- */
-struct ospf_ri_sr_info {
- bool enabled;
- /* Algorithms supported by the node */
- struct ri_sr_tlv_sr_algorithm algo;
- /*
- * Segment Routing Global Block i.e. label range
- * Only one range supported in this code
- */
- struct ri_sr_tlv_sid_label_range range;
- /* Maximum SID Depth supported by the node */
- struct ri_sr_tlv_node_msd msd;
-};
-
-/* Following structure are internal use only. */
-struct ospf_router_info {
- bool enabled;
-
- uint8_t registered;
- uint8_t scope;
-
-/* Flags to manage this router information. */
-#define RIFLG_LSA_ENGAGED 0x1
-#define RIFLG_LSA_FORCED_REFRESH 0x2
- uint32_t flags;
-
- /* area pointer if flooding is Type 10 Null if flooding is AS scope */
- struct ospf_area *area;
- struct in_addr area_id;
-
- /* Store Router Information Capabilities LSA */
- struct ri_tlv_router_cap router_cap;
-
- /* Store PCE capability LSA */
- struct ospf_pce_info pce_info;
-
- /* Store SR capability LSA */
- struct ospf_ri_sr_info sr_info;
-};
-
/*
* Global variable to manage Opaque-LSA/Router Information on this node.
* Note that all parameter values are stored in network byte order.
@@ -126,28 +72,29 @@ static struct ospf_router_info OspfRI;
static void ospf_router_info_ism_change(struct ospf_interface *oi,
int old_status);
-static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr,
- int old_status);
static void ospf_router_info_config_write_router(struct vty *vty);
static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa);
static int ospf_router_info_lsa_originate(void *arg);
static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa);
-static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode);
+static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
+ enum lsa_opcode opcode);
static void ospf_router_info_register_vty(void);
static int ospf_router_info_lsa_update(struct ospf_lsa *lsa);
+static void del_area_info(void *val);
static void del_pce_info(void *val);
int ospf_router_info_init(void)
{
- zlog_info("RI -> Initialize Router Information");
+ zlog_info("RI (%s): Initialize Router Information", __func__);
memset(&OspfRI, 0, sizeof(struct ospf_router_info));
OspfRI.enabled = false;
OspfRI.registered = 0;
OspfRI.scope = OSPF_OPAQUE_AS_LSA;
- OspfRI.area_id.s_addr = 0;
- OspfRI.flags = 0;
+ OspfRI.as_flags = RIFLG_LSA_INACTIVE;
+ OspfRI.area_info = list_new();
+ OspfRI.area_info->del = del_area_info;
/* Initialize pce domain and neighbor list */
OspfRI.pce_info.enabled = false;
@@ -171,13 +118,15 @@ static int ospf_router_info_register(uint8_t scope)
if (OspfRI.registered)
return rc;
- zlog_info("RI -> Register Router Information with scope %s(%d)",
+ zlog_info("RI (%s): Register Router Information with scope %s(%d)",
+ __func__,
scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope);
rc = ospf_register_opaque_functab(
scope, OPAQUE_TYPE_ROUTER_INFORMATION_LSA,
NULL, /* new interface */
NULL, /* del interface */
- ospf_router_info_ism_change, ospf_router_info_nsm_change,
+ ospf_router_info_ism_change,
+ NULL, /* NSM change */
ospf_router_info_config_write_router,
NULL, /* Config. write interface */
NULL, /* Config. write debug */
@@ -188,7 +137,7 @@ static int ospf_router_info_register(uint8_t scope)
if (rc != 0) {
flog_warn(
EC_OSPF_OPAQUE_REGISTRATION,
- "ospf_router_info_init: Failed to register functions");
+ "RI (%s): Failed to register functions", __func__);
return rc;
}
@@ -235,10 +184,14 @@ void ospf_router_info_finish(void)
OspfRI.enabled = false;
}
+static void del_area_info(void *val)
+{
+ XFREE(MTYPE_OSPF_ROUTER_INFO, val);
+}
+
static void del_pce_info(void *val)
{
XFREE(MTYPE_OSPF_PCE_PARAMS, val);
- return;
}
/* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
@@ -248,14 +201,26 @@ struct scope_info ospf_router_info_get_flooding_scope(void)
if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
flooding_scope.scope = OSPF_OPAQUE_AS_LSA;
- flooding_scope.area_id.s_addr = 0;
+ flooding_scope.areas = NULL;
return flooding_scope;
}
flooding_scope.scope = OSPF_OPAQUE_AREA_LSA;
- flooding_scope.area_id.s_addr = OspfRI.area_id.s_addr;
+ flooding_scope.areas = OspfRI.area_info;
return flooding_scope;
}
+static struct ospf_ri_area_info *lookup_by_area(struct ospf_area *area)
+{
+ struct listnode *node, *nnode;
+ struct ospf_ri_area_info *ai;
+
+ for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai))
+ if (ai->area == area)
+ return ai;
+
+ return NULL;
+}
+
/*------------------------------------------------------------------------*
* Followings are control functions for ROUTER INFORMATION parameters
*management.
@@ -525,6 +490,9 @@ static void initialize_params(struct ospf_router_info *ori)
{
uint32_t cap = 0;
struct ospf *top;
+ struct listnode *node, *nnode;
+ struct ospf_area *area;
+ struct ospf_ri_area_info *new;
/*
* Initialize default Router Information Capabilities.
@@ -536,14 +504,22 @@ static void initialize_params(struct ospf_router_info *ori)
/* If Area address is not null and exist, retrieve corresponding
* structure */
top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- zlog_info("RI-> Initialize Router Info for %s scope within area %s",
- OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS",
- inet_ntoa(OspfRI.area_id));
+ zlog_info("RI (%s): Initialize Router Info for %s scope", __func__,
+ OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
- /* Try to get the Area context at this step. Do it latter if not
- * available */
- if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL))
- OspfRI.area = ospf_area_lookup_by_area_id(top, OspfRI.area_id);
+ /* Try to get available Area's context from ospf at this step.
+ * Do it latter if not available */
+ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
+ for (ALL_LIST_ELEMENTS(top->areas, node, nnode, area)) {
+ zlog_debug("RI (%s): Add area %s to Router Information",
+ __func__, inet_ntoa(area->area_id));
+ new = XCALLOC(MTYPE_OSPF_ROUTER_INFO,
+ sizeof(struct ospf_ri_area_info));
+ new->area = area;
+ new->flags = RIFLG_LSA_INACTIVE;
+ listnode_add(OspfRI.area_info, new);
+ }
+ }
/*
* Initialize default PCE Information values
@@ -597,16 +573,31 @@ static int is_mandated_params_set(struct ospf_router_info ori)
*/
void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd)
{
+ struct listnode *node, *nnode;
+ struct ospf_ri_area_info *ai;
+
+ /* First, check if Router Information is registered or not */
+ if (!OspfRI.registered)
+ ospf_router_info_register(OSPF_OPAQUE_AREA_LSA);
+
+ /* Verify that scope is AREA */
+ if (OspfRI.scope != OSPF_OPAQUE_AREA_LSA) {
+ zlog_err(
+ "RI (%s): Router Info is %s flooding: Change scope to Area flooding for Segment Routing",
+ __func__,
+ OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
+ return;
+ }
- /* First activate and initialize Router Information is necessary */
+ /* Then, activate and initialize Router Information if necessary */
if (!OspfRI.enabled) {
OspfRI.enabled = true;
initialize_params(&OspfRI);
}
if (IS_DEBUG_OSPF_SR)
- zlog_debug("RI-> %s Routing Information for Segment Routing",
- enable ? "Enable" : "Disable");
+ zlog_debug("RI (%s): %s Routing Information for Segment Routing",
+ __func__, enable ? "Enable" : "Disable");
/* Unset or Set SR parameters */
if (!enable) {
@@ -626,10 +617,14 @@ void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd)
}
/* Refresh if already engaged or originate RI LSA */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
- else
- ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA);
+ for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
+ if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
+ ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA);
+ else
+ ospf_router_info_lsa_schedule(ai,
+ REORIGINATE_THIS_LSA);
+
+ }
}
/*------------------------------------------------------------------------*
@@ -638,14 +633,22 @@ void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd)
static void ospf_router_info_ism_change(struct ospf_interface *oi,
int old_state)
{
- /* So far, nothing to do here. */
- return;
-}
-static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr,
- int old_state)
-{
- /* So far, nothing to do here. */
+ struct ospf_ri_area_info *ai;
+
+ /* Collect area information */
+ ai = lookup_by_area(oi->area);
+
+ /* Check if area is not yet registered */
+ if (ai != NULL)
+ return;
+
+ /* Add this new area to the list */
+ ai = XCALLOC(MTYPE_OSPF_ROUTER_INFO, sizeof(struct ospf_ri_area_info));
+ ai->area = oi->area;
+ ai->flags = RIFLG_LSA_INACTIVE;
+ listnode_add(OspfRI.area_info, ai);
+
return;
}
@@ -723,7 +726,7 @@ static void ospf_router_info_lsa_body_set(struct stream *s)
}
/* Create new opaque-LSA. */
-static struct ospf_lsa *ospf_router_info_lsa_new()
+static struct ospf_lsa *ospf_router_info_lsa_new(struct ospf_area *area)
{
struct ospf *top;
struct stream *s;
@@ -768,8 +771,7 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
/* Now, create an OSPF LSA instance. */
new = ospf_lsa_new_and_data(length);
- new->area = OspfRI.area; /* Area must be null if the Opaque type is AS
- scope, fulfill otherwise */
+ new->area = area;
if (new->area && new->area->ospf)
new->vrf_id = new->area->ospf->vrf_id;
@@ -783,36 +785,31 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
return new;
}
-static int ospf_router_info_lsa_originate1(void *arg)
+static int ospf_router_info_lsa_originate_as(void *arg)
{
struct ospf_lsa *new;
struct ospf *top;
- struct ospf_area *area;
int rc = -1;
vrf_id_t vrf_id = VRF_DEFAULT;
- /* First check if the area is known if flooding scope is Area */
+ /* Sanity Check */
if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
- area = (struct ospf_area *)arg;
- if (area->area_id.s_addr != OspfRI.area_id.s_addr) {
- zlog_debug(
- "RI -> This is not the Router Information Area. Stop processing");
- return rc;
- }
- OspfRI.area = area;
- if (area->ospf)
- vrf_id = area->ospf->vrf_id;
+ flog_warn(
+ EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): wrong flooding scope AREA instead of AS ?",
+ __func__);
+ return rc;
}
/* Create new Opaque-LSA/ROUTER INFORMATION instance. */
- new = ospf_router_info_lsa_new();
- new->vrf_id = vrf_id;
+ new = ospf_router_info_lsa_new(NULL);
+ new->vrf_id = VRF_DEFAULT;
+ top = (struct ospf *)arg;
- /* Get ospf info */
- top = ospf_lookup_by_vrf_id(vrf_id);
+ /* Check ospf info */
if (top == NULL) {
- zlog_debug("%s: ospf instance not found for vrf id %u",
- __PRETTY_FUNCTION__, vrf_id);
+ zlog_debug("RI (%s): ospf instance not found for vrf id %u",
+ __func__, vrf_id);
ospf_lsa_unlock(&new);
return rc;
}
@@ -821,22 +818,86 @@ static int ospf_router_info_lsa_originate1(void *arg)
if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
flog_warn(
EC_OSPF_LSA_INSTALL_FAILURE,
- "ospf_router_info_lsa_originate1: ospf_lsa_install() ?");
+ "RI (%s): ospf_lsa_install() ?", __func__);
+ ospf_lsa_unlock(&new);
+ return rc;
+ }
+
+ /* Update new LSA origination count. */
+ top->lsa_originate_count++;
+
+ /* Flood new LSA through AREA or AS. */
+ SET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
+ ospf_flood_through_as(top, NULL /*nbr */, new);
+
+ if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
+ zlog_debug(
+ "LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
+ new->data->type, inet_ntoa(new->data->id));
+ ospf_lsa_header_dump(new->data);
+ }
+
+ rc = 0;
+ return rc;
+}
+
+static int ospf_router_info_lsa_originate_area(void *arg)
+{
+ struct ospf_lsa *new;
+ struct ospf *top;
+ struct ospf_ri_area_info *ai = NULL;
+ int rc = -1;
+ vrf_id_t vrf_id = VRF_DEFAULT;
+
+ /* Sanity Check */
+ if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
+ flog_warn(
+ EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): wrong flooding scope AS instead of AREA ?",
+ __func__);
+ return rc;
+ }
+
+ /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
+ ai = lookup_by_area((struct ospf_area *)arg);
+ if (ai == NULL) {
+ zlog_debug(
+ "RI (%s): There is no context for this Router Information. Stop processing",
+ __func__);
+ return rc;
+ }
+ if (ai->area->ospf) {
+ vrf_id = ai->area->ospf->vrf_id;
+ top = ai->area->ospf;
+ } else {
+ top = ospf_lookup_by_vrf_id(vrf_id);
+ }
+ new = ospf_router_info_lsa_new(ai->area);
+ new->vrf_id = vrf_id;
+
+ /* Check ospf info */
+ if (top == NULL) {
+ zlog_debug("RI (%s): ospf instance not found for vrf id %u",
+ __func__, vrf_id);
ospf_lsa_unlock(&new);
return rc;
}
- /* Now this Router Info parameter entry has associated LSA. */
- SET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED);
+ /* Install this LSA into LSDB. */
+ if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
+ flog_warn(
+ EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): ospf_lsa_install() ?", __func__);
+ ospf_lsa_unlock(&new);
+ return rc;
+ }
/* Update new LSA origination count. */
top->lsa_originate_count++;
- /* Flood new LSA through AS. */
- if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
- ospf_flood_through_as(top, NULL /*nbr */, new);
- else
- ospf_flood_through_area(OspfRI.area, NULL /*nbr */, new);
+ /* Flood new LSA through AREA or AS. */
+ SET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
+ ospf_flood_through_area(ai->area, NULL /*nbr */, new);
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
zlog_debug(
@@ -852,38 +913,62 @@ static int ospf_router_info_lsa_originate1(void *arg)
static int ospf_router_info_lsa_originate(void *arg)
{
+ struct ospf_ri_area_info *ai;
int rc = -1;
if (!OspfRI.enabled) {
- zlog_info(
- "ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now.");
+ zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
+ __func__);
rc = 0; /* This is not an error case. */
return rc;
}
/* Check if Router Information LSA is already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) {
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_FORCED_REFRESH)) {
- UNSET_FLAG(OspfRI.flags, RIFLG_LSA_FORCED_REFRESH);
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
+ if ((CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
+ && (CHECK_FLAG(OspfRI.as_flags,
+ RIFLG_LSA_FORCED_REFRESH))) {
+ UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_FORCED_REFRESH);
+ ospf_router_info_lsa_schedule(NULL, REFRESH_THIS_LSA);
+ rc = 0;
+ return rc;
}
} else {
- if (!is_mandated_params_set(OspfRI))
+ ai = lookup_by_area((struct ospf_area *)arg);
+ if (ai == NULL) {
flog_warn(
EC_OSPF_LSA,
- "ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters");
-
- /* Ok, let's try to originate an LSA */
- if (ospf_router_info_lsa_originate1(arg) != 0)
+ "RI (%s): Missing area information", __func__);
return rc;
+ }
+ if ((CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
+ && (CHECK_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH))) {
+ UNSET_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH);
+ ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA);
+ rc = 0;
+ return rc;
+ }
}
- rc = 0;
+ /* Router Information is not yet Engaged, check parameters */
+ if (!is_mandated_params_set(OspfRI))
+ flog_warn(
+ EC_OSPF_LSA,
+ "RI (%s): lacks mandated ROUTER INFORMATION parameters",
+ __func__);
+
+ /* Ok, let's try to originate an LSA */
+ if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
+ rc = ospf_router_info_lsa_originate_as(arg);
+ else
+ rc = ospf_router_info_lsa_originate_area(arg);
+
return rc;
}
static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
{
+ struct ospf_ri_area_info *ai = NULL;
struct ospf_lsa *new = NULL;
struct ospf *top;
@@ -893,8 +978,8 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
* status change.
* It seems a slip among routers in the routing domain.
*/
- zlog_info(
- "ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now.");
+ zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
+ __func__);
lsa->data->ls_age =
htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
}
@@ -903,37 +988,66 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
if (GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)) != 0) {
flog_warn(
EC_OSPF_LSA,
- "ospf_router_info_lsa_refresh: Unsupported Router Information ID");
+ "RI (%s): Unsupported Router Information ID",
+ __func__);
return NULL;
}
- /* If the lsa's age reached to MaxAge, start flushing procedure. */
- if (IS_LSA_MAXAGE(lsa)) {
- UNSET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED);
- ospf_opaque_lsa_flush_schedule(lsa);
- return NULL;
- }
-
- /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
- new = ospf_router_info_lsa_new();
- new->data->ls_seqnum = lsa_seqnum_increment(lsa);
- new->vrf_id = lsa->vrf_id;
-
- /* Install this LSA into LSDB. */
- /* Given "lsa" will be freed in the next function. */
- top = ospf_lookup_by_vrf_id(lsa->vrf_id);
- if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
- flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
- "ospf_router_info_lsa_refresh: ospf_lsa_install() ?");
- ospf_lsa_unlock(&new);
- return new;
- }
-
- /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */
- if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
+ /* Process LSA depending of the flooding scope */
+ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
+ /* Get context AREA context */
+ ai = lookup_by_area(lsa->area);
+ if (ai == NULL) {
+ flog_warn(
+ EC_OSPF_LSA,
+ "RI (%s): No associated Area", __func__);
+ return NULL;
+ }
+ /* Flush LSA, if the lsa's age reached to MaxAge. */
+ if (IS_LSA_MAXAGE(lsa)) {
+ UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
+ ospf_opaque_lsa_flush_schedule(lsa);
+ return NULL;
+ }
+ /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
+ new = ospf_router_info_lsa_new(ai->area);
+ new->data->ls_seqnum = lsa_seqnum_increment(lsa);
+ new->vrf_id = lsa->vrf_id;
+ /* Install this LSA into LSDB. */
+ /* Given "lsa" will be freed in the next function. */
+ top = ospf_lookup_by_vrf_id(lsa->vrf_id);
+ if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
+ flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): ospf_lsa_install() ?", __func__);
+ ospf_lsa_unlock(&new);
+ return new;
+ }
+ /* Flood updated LSA through AREA */
+ ospf_flood_through_area(ai->area, NULL /*nbr */, new);
+
+ } else { /* AS Flooding scope */
+ /* Flush LSA, if the lsa's age reached to MaxAge. */
+ if (IS_LSA_MAXAGE(lsa)) {
+ UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
+ ospf_opaque_lsa_flush_schedule(lsa);
+ return NULL;
+ }
+ /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
+ new = ospf_router_info_lsa_new(NULL);
+ new->data->ls_seqnum = lsa_seqnum_increment(lsa);
+ new->vrf_id = lsa->vrf_id;
+ /* Install this LSA into LSDB. */
+ /* Given "lsa" will be freed in the next function. */
+ top = ospf_lookup_by_vrf_id(lsa->vrf_id);
+ if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
+ flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
+ "RI (%s): ospf_lsa_install() ?", __func__);
+ ospf_lsa_unlock(&new);
+ return new;
+ }
+ /* Flood updated LSA through AS */
ospf_flood_through_as(top, NULL /*nbr */, new);
- else
- ospf_flood_through_area(OspfRI.area, NULL /*nbr */, new);
+ }
/* Debug logging. */
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
@@ -946,7 +1060,8 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
return new;
}
-static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
+static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
+ enum lsa_opcode opcode)
{
struct ospf_lsa lsa;
struct lsa_header lsah;
@@ -956,28 +1071,44 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
memset(&lsa, 0, sizeof(lsa));
memset(&lsah, 0, sizeof(lsah));
- zlog_debug("RI-> LSA schedule %s%s%s",
+ zlog_debug("RI (%s): LSA schedule %s%s%s", __func__,
opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
opcode == REFRESH_THIS_LSA ? "Refresh" : "",
opcode == FLUSH_THIS_LSA ? "Flush" : "");
- /* Check LSA flags state coherence */
- if (!CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)
- && (opcode != REORIGINATE_THIS_LSA))
- return;
+ /* Check LSA flags state coherence and collect area information */
+ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
+ if ((ai == NULL) || (ai->area == NULL)) {
+ flog_warn(
+ EC_OSPF_LSA,
+ "RI (%s): Router Info is Area scope flooding but area is not set",
+ __func__);
+ return;
+ }
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)
- && (opcode == REORIGINATE_THIS_LSA))
- opcode = REFRESH_THIS_LSA;
+ if (!CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
+ && (opcode != REORIGINATE_THIS_LSA))
+ return;
- top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set");
- OspfRI.area = ospf_area_lookup_by_area_id(top, OspfRI.area_id);
+ if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
+ && (opcode == REORIGINATE_THIS_LSA))
+ opcode = REFRESH_THIS_LSA;
+
+ lsa.area = ai->area;
+ top = ai->area->ospf;
+ } else {
+ if (!CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
+ && (opcode != REORIGINATE_THIS_LSA))
+ return;
+
+ if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
+ && (opcode == REORIGINATE_THIS_LSA))
+ opcode = REFRESH_THIS_LSA;
+
+ top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
+ lsa.area = NULL;
}
- lsa.area = OspfRI.area;
+
lsa.data = &lsah;
lsah.type = OspfRI.scope;
@@ -989,7 +1120,7 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
case REORIGINATE_THIS_LSA:
if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
ospf_opaque_lsa_reoriginate_schedule(
- (void *)OspfRI.area, OSPF_OPAQUE_AREA_LSA,
+ (void *)ai->area, OSPF_OPAQUE_AREA_LSA,
OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
else
ospf_opaque_lsa_reoriginate_schedule(
@@ -1000,7 +1131,10 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
ospf_opaque_lsa_refresh_schedule(&lsa);
break;
case FLUSH_THIS_LSA:
- UNSET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED);
+ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
+ UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
+ else
+ UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
ospf_opaque_lsa_flush_schedule(&lsa);
break;
}
@@ -1014,7 +1148,7 @@ static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
/* Sanity Check */
if (lsa == NULL) {
- flog_warn(EC_OSPF_LSA, "OSPF-RI (%s): Abort! LSA is NULL",
+ flog_warn(EC_OSPF_LSA, "RI (%s): Abort! LSA is NULL",
__func__);
return -1;
}
@@ -1356,8 +1490,7 @@ static void ospf_router_info_config_write_router(struct vty *vty)
if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
vty_out(vty, " router-info as\n");
else
- vty_out(vty, " router-info area %s\n",
- inet_ntoa(OspfRI.area_id));
+ vty_out(vty, " router-info area\n");
if (OspfRI.pce_info.enabled) {
@@ -1405,43 +1538,53 @@ static void ospf_router_info_config_write_router(struct vty *vty)
/*------------------------------------------------------------------------*
* Followings are vty command functions.
*------------------------------------------------------------------------*/
+/* Simple wrapper schedule RI LSA action in function of the scope */
+static void ospf_router_info_schedule(enum lsa_opcode opcode)
+{
+ struct listnode *node, *nnode;
+ struct ospf_ri_area_info *ai;
+
+ if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
+ if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
+ ospf_router_info_lsa_schedule(NULL, opcode);
+ else if (opcode == REORIGINATE_THIS_LSA)
+ ospf_router_info_lsa_schedule(NULL, opcode);
+ } else {
+ for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
+ if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
+ ospf_router_info_lsa_schedule(ai, opcode);
+ }
+ }
+}
DEFUN (router_info,
router_info_area_cmd,
- "router-info <as|area A.B.C.D>",
+ "router-info <as|area [A.B.C.D]>",
OSPF_RI_STR
"Enable the Router Information functionality with AS flooding scope\n"
"Enable the Router Information functionality with Area flooding scope\n"
- "OSPF area ID in IP format\n")
+ "OSPF area ID in IP format (deprecated)\n")
{
- int idx_ipv4 = 2;
- char *area = (argc == 3) ? argv[idx_ipv4]->arg : NULL;
-
+ int idx_mode = 1;
uint8_t scope;
if (OspfRI.enabled)
return CMD_SUCCESS;
/* Check and get Area value if present */
- if (area) {
- if (!inet_aton(area, &OspfRI.area_id)) {
- vty_out(vty, "%% specified Area ID %s is invalid\n",
- area);
- return CMD_WARNING_CONFIG_FAILED;
- }
- scope = OSPF_OPAQUE_AREA_LSA;
- } else {
- OspfRI.area_id.s_addr = 0;
+ if (strncmp(argv[idx_mode]->arg, "as", 2) == 0)
scope = OSPF_OPAQUE_AS_LSA;
- }
+ else
+ scope = OSPF_OPAQUE_AREA_LSA;
/* First start to register Router Information callbacks */
- if ((ospf_router_info_register(scope)) != 0) {
+ if (!OspfRI.registered && (ospf_router_info_register(scope)) != 0) {
vty_out(vty,
"%% Unable to register Router Information callbacks.");
flog_err(
EC_OSPF_INIT_FAIL,
- "Unable to register Router Information callbacks. Abort!");
+ "RI (%s): Unable to register Router Information callbacks. Abort!",
+ __func__);
return CMD_WARNING_CONFIG_FAILED;
}
@@ -1463,14 +1606,8 @@ DEFUN (router_info,
initialize_params(&OspfRI);
- /* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) {
- zlog_debug("RI-> Refresh LSA following configuration");
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
- } else {
- zlog_debug("RI-> Initial origination following configuration");
- ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA);
- }
+ /* Originate or Refresh RI LSA if already engaged */
+ ospf_router_info_schedule(REORIGINATE_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1488,8 +1625,7 @@ DEFUN (no_router_info,
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("RI-> Router Information: ON -> OFF");
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(FLUSH_THIS_LSA);
+ ospf_router_info_schedule(FLUSH_THIS_LSA);
OspfRI.enabled = false;
@@ -1533,8 +1669,7 @@ DEFUN (pce_address,
set_pce_address(value, pi);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
}
return CMD_SUCCESS;
@@ -1552,8 +1687,7 @@ DEFUN (no_pce_address,
unset_param(&OspfRI.pce_info.pce_address);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1583,8 +1717,7 @@ DEFUN (pce_path_scope,
set_pce_path_scope(scope, pi);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
}
return CMD_SUCCESS;
@@ -1602,8 +1735,7 @@ DEFUN (no_pce_path_scope,
unset_param(&OspfRI.pce_info.pce_address);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1641,8 +1773,7 @@ DEFUN (pce_domain,
set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1671,8 +1802,7 @@ DEFUN (no_pce_domain,
unset_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1711,8 +1841,7 @@ DEFUN (pce_neigbhor,
set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1741,8 +1870,7 @@ DEFUN (no_pce_neighbor,
unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
@@ -1773,8 +1901,7 @@ DEFUN (pce_cap_flag,
set_pce_cap_flag(cap, pce);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
}
return CMD_SUCCESS;
@@ -1791,8 +1918,7 @@ DEFUN (no_pce_cap_flag,
unset_param(&OspfRI.pce_info.pce_cap_flag);
/* Refresh RI LSA if already engaged */
- if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
- ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
+ ospf_router_info_schedule(REFRESH_THIS_LSA);
return CMD_SUCCESS;
}
diff --git a/ospfd/ospf_ri.h b/ospfd/ospf_ri.h
index 26bcc1b62a..84511ac5e7 100644
--- a/ospfd/ospf_ri.h
+++ b/ospfd/ospf_ri.h
@@ -170,7 +170,71 @@ struct ri_pce_subtlv_cap_flag {
/* Structure to share flooding scope info for Segment Routing */
struct scope_info {
uint8_t scope;
- struct in_addr area_id;
+ struct list *areas;
+};
+
+/* Flags to manage the Router Information LSA. */
+#define RIFLG_LSA_INACTIVE 0x0
+#define RIFLG_LSA_ENGAGED 0x1
+#define RIFLG_LSA_FORCED_REFRESH 0x2
+
+/* Store Router Information PCE TLV and SubTLV in network byte order. */
+struct ospf_pce_info {
+ bool enabled;
+ struct ri_tlv_pce pce_header;
+ struct ri_pce_subtlv_address pce_address;
+ struct ri_pce_subtlv_path_scope pce_scope;
+ struct list *pce_domain;
+ struct list *pce_neighbor;
+ struct ri_pce_subtlv_cap_flag pce_cap_flag;
+};
+
+/*
+ * Store Router Information Segment Routing TLV and SubTLV
+ * in network byte order
+ */
+struct ospf_ri_sr_info {
+ bool enabled;
+ /* Algorithms supported by the node */
+ struct ri_sr_tlv_sr_algorithm algo;
+ /*
+ * Segment Routing Global Block i.e. label range
+ * Only one range supported in this code
+ */
+ struct ri_sr_tlv_sid_label_range range;
+ /* Maximum SID Depth supported by the node */
+ struct ri_sr_tlv_node_msd msd;
+};
+
+/* Store area information to flood LSA per area */
+struct ospf_ri_area_info {
+
+ uint32_t flags;
+
+ /* area pointer if flooding is Type 10 Null if flooding is AS scope */
+ struct ospf_area *area;
+};
+
+/* Following structure are internal use only. */
+struct ospf_router_info {
+ bool enabled;
+
+ uint8_t registered;
+ uint8_t scope;
+ /* LSA flags are only used when scope is AS flooding */
+ uint32_t as_flags;
+
+ /* List of area info to flood RI LSA */
+ struct list *area_info;
+
+ /* Store Router Information Capabilities LSA */
+ struct ri_tlv_router_cap router_cap;
+
+ /* Store PCE capability LSA */
+ struct ospf_pce_info pce_info;
+
+ /* Store SR capability LSA */
+ struct ospf_ri_sr_info sr_info;
};
/* Prototypes. */
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index 02698d770a..16347f1c5b 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -2398,16 +2398,16 @@ DEFUN (no_ospf_mpls_te_inter_as,
zlog_debug("MPLS-TE: Inter-AS support OFF");
if ((OspfMplsTE.enabled) && (OspfMplsTE.inter_as != Off)) {
- OspfMplsTE.inter_as = Off;
/* Flush all Inter-AS LSA */
for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
if (IS_INTER_AS(lp->type)
&& CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
- }
- /* Deregister the Callbacks for Inter-AS support */
- ospf_mpls_te_unregister();
+ /* Deregister the Callbacks for Inter-AS support */
+ ospf_mpls_te_unregister();
+ OspfMplsTE.inter_as = Off;
+ }
return CMD_SUCCESS;
}
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 35f719fa54..cd78551cb4 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -1458,7 +1458,7 @@ DEFUNSH_HIDDEN(VTYSH_BGPD, address_family_evpn2, address_family_evpn2_cmd,
}
#endif
-DEFUNSH(VTYSH_BGPD, bgp_evpn_vni, bgp_evpn_vni_cmd, "vni (1-16777215)",
+DEFUNSH(VTYSH_BGPD, bgp_evpn_vni, bgp_evpn_vni_cmd, "vni " CMD_VNI_RANGE,
"VXLAN Network Identifier\n"
"VNI number\n")
{
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 4fff376377..263cb3d22c 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -68,9 +68,6 @@ static void vty_show_ip_route_summary(struct vty *vty,
static void vty_show_ip_route_summary_prefix(struct vty *vty,
struct route_table *table);
-/* VNI range as per RFC 7432 */
-#define CMD_VNI_RANGE "(1-16777215)"
-
DEFUN (ip_multicast_mode,
ip_multicast_mode_cmd,
"ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 0bc1ea50bb..d372d3e832 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -148,8 +148,7 @@ static void zvni_mac_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *macaddr);
static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
uint8_t flags, uint32_t seq);
-static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr,
- uint8_t flags);
+static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr);
static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
struct interface *br_if, vlanid_t vid);
static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac);
@@ -2305,6 +2304,7 @@ static int zvni_remote_neigh_update(zebra_vni_t *zvni,
UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
+ ZEBRA_NEIGH_SET_ACTIVE(n);
n->r_vtep_ip = zmac->fwd_info.r_vtep_ip;
}
@@ -2407,7 +2407,7 @@ static void zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg)
&wctx->r_vtep_ip))) {
if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
zvni_mac_send_del_to_client(wctx->zvni->vni,
- &mac->macaddr, mac->flags);
+ &mac->macaddr);
}
if (wctx->uninstall)
@@ -2494,18 +2494,10 @@ static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
/*
* Inform BGP about local MAC deletion.
*/
-static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr,
- uint8_t mac_flags)
+static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr)
{
- uint8_t flags = 0;
-
- if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
- if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
-
- return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
- 0, ZEBRA_MACIP_DEL);
+ return zvni_macip_send_msg_to_client(vni, macaddr, NULL, 0 /* flags */,
+ 0 /* seq */, ZEBRA_MACIP_DEL);
}
/*
@@ -4304,6 +4296,10 @@ static void process_remote_macip_add(vni_t vni,
}
}
+ /* Remove local MAC from BGP. */
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
+ zvni_mac_send_del_to_client(zvni->vni, macaddr);
+
/* Set "auto" and "remote" forwarding info. */
UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
@@ -4324,6 +4320,7 @@ static void process_remote_macip_add(vni_t vni,
/* Install the entry. */
zvni_mac_install(zvni, mac);
+
}
/* Update seq number. */
@@ -4522,6 +4519,13 @@ static void process_remote_macip_del(vni_t vni,
} else {
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
zvni_process_neigh_on_remote_mac_del(zvni, mac);
+ /*
+ * the remote sequence number in the auto mac entry
+ * needs to be reset to 0 as the mac entry may have
+ * been removed on all VTEPs (including
+ * the originating one)
+ */
+ mac->rem_seq = 0;
/* If all remote neighbors referencing a remote MAC
* go away, we need to uninstall the MAC.
@@ -5730,7 +5734,7 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp,
ifp->ifindex, vni);
/* Remove MAC from BGP. */
- zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags);
+ zvni_mac_send_del_to_client(zvni->vni, macaddr);
/*
* If there are no neigh associated with the mac delete the mac
@@ -5841,7 +5845,7 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
zvni_process_neigh_on_local_mac_del(zvni, mac);
/* Remove MAC from BGP. */
- zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags);
+ zvni_mac_send_del_to_client(zvni->vni, macaddr);
/*
* If there are no neigh associated with the mac delete the mac