summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c10
-rw-r--r--bgpd/bgp_attr.h3
-rw-r--r--bgpd/bgp_attr_evpn.c33
-rw-r--r--bgpd/bgp_attr_evpn.h2
-rw-r--r--bgpd/bgp_ecommunity.h3
-rw-r--r--bgpd/bgp_evpn.c30
-rw-r--r--bgpd/bgp_evpn_private.h12
-rw-r--r--bgpd/bgp_routemap.c117
-rw-r--r--doc/Makefile.am1
-rw-r--r--doc/extra/spelling_wordlist.txt1
-rw-r--r--doc/user/index.rst1
-rw-r--r--doc/user/ldpd.rst309
-rw-r--r--isisd/isis_routemap.c11
-rw-r--r--ldpd/ldp_vty_cmds.c1
-rw-r--r--lib/filter.c9
-rw-r--r--lib/filter.h3
-rw-r--r--lib/plist.c13
-rw-r--r--lib/plist.h5
-rw-r--r--lib/routemap.c5
-rw-r--r--lib/routemap.h8
-rw-r--r--lib/zclient.h2
-rw-r--r--ospf6d/ospf6_asbr.c15
-rw-r--r--ospfd/ospf_routemap.c20
-rw-r--r--pimd/pim_rp.c6
-rw-r--r--pimd/pim_zebra.c31
-rw-r--r--ripd/rip_routemap.c22
-rw-r--r--ripngd/ripng_routemap.c16
-rwxr-xr-xtools/frr-reload.py2
-rw-r--r--zebra/if_netlink.c14
-rw-r--r--zebra/rt.h2
-rw-r--r--zebra/rt_netlink.c67
-rw-r--r--zebra/rt_socket.c10
-rw-r--r--zebra/rule_netlink.c6
-rw-r--r--zebra/zebra_rib.c4
-rw-r--r--zebra/zebra_routemap.c36
-rw-r--r--zebra/zebra_routemap.h5
-rw-r--r--zebra/zebra_vty.c9
-rw-r--r--zebra/zebra_vxlan.c88
-rw-r--r--zebra/zebra_vxlan.h3
-rw-r--r--zebra/zebra_vxlan_private.h3
40 files changed, 735 insertions, 203 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 6596e7cfa2..e5ad5e2338 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -1890,6 +1890,16 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
/* Check if this is a Gateway MAC-IP advertisement */
attr->default_gw = bgp_attr_default_gw(attr);
+ /* Handle scenario where router flag ecommunity is not
+ * set but default gw ext community is present.
+ * Use default gateway, set and propogate R-bit.
+ */
+ if (attr->default_gw)
+ attr->router_flag = 1;
+
+ /* Check EVPN Neighbor advertisement flags, R-bit */
+ bgp_attr_evpn_na_flag(attr, &attr->router_flag);
+
/* Extract the Rmac, if any */
bgp_attr_rmac(attr, &attr->rmac);
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index f17c2a68e4..883b129136 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -185,6 +185,9 @@ struct attr {
/* Flag for default gateway extended community in EVPN */
uint8_t default_gw;
+ /* NA router flag (R-bit) support in EVPN */
+ uint8_t router_flag;
+
/* route tag */
route_tag_t tag;
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
index 14ff01ada5..88e520fdc5 100644
--- a/bgpd/bgp_attr_evpn.c
+++ b/bgpd/bgp_attr_evpn.c
@@ -210,6 +210,39 @@ uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky)
return 0;
}
+/*
+ * return true if attr contains router flag extended community
+ */
+void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag)
+{
+ struct ecommunity *ecom;
+ int i;
+ uint8_t val;
+
+ ecom = attr->ecommunity;
+ if (!ecom || !ecom->size)
+ return;
+
+ /* If there is a evpn na extendd community set router_flag */
+ for (i = 0; i < ecom->size; i++) {
+ uint8_t *pnt;
+ uint8_t type, sub_type;
+
+ pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
+ type = *pnt++;
+ sub_type = *pnt++;
+
+ if (type == ECOMMUNITY_ENCODE_EVPN &&
+ sub_type == ECOMMUNITY_EVPN_SUBTYPE_ND) {
+ val = *pnt++;
+ if (val & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG) {
+ *router_flag = 1;
+ break;
+ }
+ }
+ }
+}
+
/* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
struct prefix *dst)
diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h
index 7454b81b96..b036702151 100644
--- a/bgpd/bgp_attr_evpn.h
+++ b/bgpd/bgp_attr_evpn.h
@@ -65,4 +65,6 @@ extern uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
uint8_t *sticky);
extern uint8_t bgp_attr_default_gw(struct attr *attr);
+extern void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag);
+
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index 2f59308d65..c71f371a97 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -48,8 +48,11 @@
#define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02
#define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03
#define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d
+#define ECOMMUNITY_EVPN_SUBTYPE_ND 0x08
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY 0x01
+#define ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG 0x01
+#define ECOMMUNITY_EVPN_SUBTYPE_ND_OVERRIDE_FLAG 0x02
/* Low-order octet of the Extended Communities type field for OPAQUE types */
#define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index a026df59a0..73f225784c 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -730,10 +730,13 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
struct ecommunity ecom_sticky;
struct ecommunity ecom_default_gw;
struct ecommunity ecom_rmac;
+ struct ecommunity ecom_na;
struct ecommunity_val eval;
struct ecommunity_val eval_sticky;
struct ecommunity_val eval_default_gw;
struct ecommunity_val eval_rmac;
+ struct ecommunity_val eval_na;
+
bgp_encap_types tnl_type;
struct listnode *node, *nnode;
struct ecommunity *ecom;
@@ -798,6 +801,15 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
ecommunity_merge(attr->ecommunity, &ecom_default_gw);
}
+ if (attr->router_flag) {
+ memset(&ecom_na, 0, sizeof(ecom_na));
+ encode_na_flag_extcomm(&eval_na, attr->router_flag);
+ ecom_na.size = 1;
+ ecom_na.val = (uint8_t *)eval_na.val;
+ attr->ecommunity = ecommunity_merge(attr->ecommunity,
+ &ecom_na);
+ }
+
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
}
@@ -1089,6 +1101,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
{
struct bgp_info *old_select, *new_select;
struct bgp_info_pair old_and_new;
+ struct prefix_evpn *evp;
afi_t afi = AFI_L2VPN;
safi_t safi = SAFI_EVPN;
int ret = 0;
@@ -1100,6 +1113,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
old_select = old_and_new.old;
new_select = old_and_new.new;
+ evp = (struct prefix_evpn *)&rn->p;
/* If the best path hasn't changed - see if there is still something to
* update
* to zebra RIB.
@@ -1115,6 +1129,10 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
if (old_select->attr->default_gw)
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
+ if (is_evpn_prefix_ipaddr_v6(evp) &&
+ old_select->attr->router_flag)
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
+
ret = evpn_zebra_install(
bgp, vpn, (struct prefix_evpn *)&rn->p,
old_select->attr->nexthop, flags);
@@ -1148,6 +1166,10 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
if (new_select->attr->default_gw)
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
+ if (is_evpn_prefix_ipaddr_v6(evp) &&
+ new_select->attr->router_flag)
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
+
ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p,
new_select->attr->nexthop, flags);
/* If an old best existed and it was a "local" route, the only
@@ -1695,6 +1717,8 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr.sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? 1 : 0;
attr.default_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW) ? 1 : 0;
+ attr.router_flag = CHECK_FLAG(flags,
+ ZEBRA_MACIP_TYPE_ROUTER_FLAG) ? 1 : 0;
/* PMSI is only needed for type-3 routes */
if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE)
@@ -1993,11 +2017,13 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_sticky, 0, 1, &ri,
0);
- else if (evpn_route_is_def_gw(bgp, rn))
+ else if (evpn_route_is_def_gw(bgp, rn)) {
+ if (is_evpn_prefix_ipaddr_v6(evp))
+ attr_def_gw.router_flag = 1;
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_def_gw, 0, 1, &ri,
0);
- else
+ } else
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr, 0, 1, &ri, 0);
}
diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h
index bf6a24dea6..8d71c3123e 100644
--- a/bgpd/bgp_evpn_private.h
+++ b/bgpd/bgp_evpn_private.h
@@ -311,6 +311,16 @@ static inline void encode_mac_mobility_extcomm(int static_mac, uint32_t seq,
eval->val[7] = seq & 0xff;
}
+static inline void encode_na_flag_extcomm(struct ecommunity_val *eval,
+ uint8_t na_flag)
+{
+ memset(eval, 0, sizeof(*eval));
+ eval->val[0] = ECOMMUNITY_ENCODE_EVPN;
+ eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_ND;
+ if (na_flag)
+ eval->val[2] |= ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG;
+}
+
static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp,
struct prefix *ip)
{
@@ -328,7 +338,7 @@ static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp,
}
}
-static inline int is_evpn_prefix_default(struct prefix *evp)
+static inline int is_evpn_prefix_default(const struct prefix *evp)
{
if (evp->family != AF_EVPN)
return 0;
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index f9f5142cd0..903018b2a2 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -234,7 +234,8 @@ struct bgp_match_peer_compiled {
/* Compares the peer specified in the 'match peer' clause with the peer
received in bgp_info->peer. If it is the same, or if the peer structure
received is a peer_group containing it, returns RMAP_MATCH. */
-static route_map_result_t route_match_peer(void *rule, struct prefix *prefix,
+static route_map_result_t route_match_peer(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -334,7 +335,7 @@ struct route_map_rule_cmd route_match_peer_cmd = {"peer", route_match_peer,
/* Match function should return 1 if match is success else return
zero. */
static route_map_result_t route_match_ip_address(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -374,7 +375,7 @@ struct route_map_rule_cmd route_match_ip_address_cmd = {
/* Match function return 1 if match is success else return zero. */
static route_map_result_t route_match_ip_next_hop(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -421,7 +422,7 @@ struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
/* Match function return 1 if match is success else return zero. */
static route_map_result_t route_match_ip_route_source(void *rule,
- struct prefix *prefix,
+ const struct prefix *pfx,
route_map_object_t type,
void *object)
{
@@ -430,7 +431,7 @@ static route_map_result_t route_match_ip_route_source(void *rule,
struct peer *peer;
struct prefix_ipv4 p;
- if (type == RMAP_BGP && prefix->family == AF_INET) {
+ if (type == RMAP_BGP && pfx->family == AF_INET) {
bgp_info = object;
peer = bgp_info->peer;
@@ -473,7 +474,7 @@ struct route_map_rule_cmd route_match_ip_route_source_cmd = {
/* `match ip address prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ip_address_prefix_list(void *rule, struct prefix *prefix,
+route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
@@ -508,7 +509,7 @@ struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
/* `match ip next-hop prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix,
+route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
@@ -550,7 +551,8 @@ struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
/* `match ip route-source prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ip_route_source_prefix_list(void *rule, struct prefix *prefix,
+route_match_ip_route_source_prefix_list(void *rule,
+ const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
@@ -599,7 +601,7 @@ struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = {
/* Match function should return 1 if match is success else 0 */
static route_map_result_t route_match_evpn_default_route(void *rule,
- struct prefix *p,
+ const struct prefix *p,
route_map_object_t
type, void *object)
{
@@ -618,7 +620,7 @@ struct route_map_rule_cmd route_match_evpn_default_route_cmd = {
/* Match function should return 1 if match is success else return
zero. */
static route_map_result_t route_match_mac_address(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -667,7 +669,8 @@ struct route_map_rule_cmd route_match_mac_address_cmd = {
/* Match function should return 1 if match is success else return
zero. */
-static route_map_result_t route_match_vni(void *rule, struct prefix *prefix,
+static route_map_result_t route_match_vni(void *rule,
+ const struct prefix *prefix,
route_map_object_t type, void *object)
{
vni_t vni = 0;
@@ -722,7 +725,7 @@ struct route_map_rule_cmd route_match_evpn_vni_cmd = {
/* Match function should return 1 if match is success else return
zero. */
static route_map_result_t route_match_evpn_route_type(void *rule,
- struct prefix *prefix,
+ const struct prefix *pfx,
route_map_object_t type,
void *object)
{
@@ -731,7 +734,7 @@ static route_map_result_t route_match_evpn_route_type(void *rule,
if (type == RMAP_BGP) {
route_type = *((uint8_t *)rule);
- if (route_type == prefix->u.prefix_evpn.route_type)
+ if (route_type == pfx->u.prefix_evpn.route_type)
return RMAP_MATCH;
}
@@ -770,7 +773,7 @@ struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
/* Match function return 1 if match is success else return zero. */
static route_map_result_t route_match_local_pref(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -829,7 +832,8 @@ struct route_map_rule_cmd route_match_local_pref_cmd = {
/* `match metric METRIC' */
/* Match function return 1 if match is success else return zero. */
-static route_map_result_t route_match_metric(void *rule, struct prefix *prefix,
+static route_map_result_t route_match_metric(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -852,7 +856,8 @@ struct route_map_rule_cmd route_match_metric_cmd = {
/* `match as-path ASPATH' */
/* Match function for as-path match. I assume given object is */
-static route_map_result_t route_match_aspath(void *rule, struct prefix *prefix,
+static route_map_result_t route_match_aspath(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -901,7 +906,7 @@ struct rmap_community {
/* Match function for community match. */
static route_map_result_t route_match_community(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -969,7 +974,7 @@ struct route_map_rule_cmd route_match_community_cmd = {
/* Match function for lcommunity match. */
static route_map_result_t route_match_lcommunity(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1030,7 +1035,7 @@ struct route_map_rule_cmd route_match_lcommunity_cmd = {
/* Match function for extcommunity match. */
static route_map_result_t route_match_ecommunity(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1072,7 +1077,8 @@ struct route_map_rule_cmd route_match_ecommunity_cmd = {
and `address-family vpnv4'. */
/* `match origin' */
-static route_map_result_t route_match_origin(void *rule, struct prefix *prefix,
+static route_map_result_t route_match_origin(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1120,7 +1126,7 @@ struct route_map_rule_cmd route_match_origin_cmd = {
/* match probability { */
static route_map_result_t route_match_probability(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1175,7 +1181,7 @@ struct route_map_rule_cmd route_match_probability_cmd = {
/* Match function should return 1 if match is success else return
zero. */
static route_map_result_t route_match_interface(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1221,7 +1227,8 @@ struct route_map_rule_cmd route_match_interface_cmd = {
/* `set ip next-hop IP_ADDRESS' */
/* Match function return 1 if match is success else return zero. */
-static route_map_result_t route_match_tag(void *rule, struct prefix *prefix,
+static route_map_result_t route_match_tag(void *rule,
+ const struct prefix *prefix,
route_map_object_t type, void *object)
{
route_tag_t *tag;
@@ -1254,7 +1261,7 @@ struct rmap_ip_nexthop_set {
};
static route_map_result_t route_set_ip_nexthop(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1362,7 +1369,7 @@ struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
/* Set local preference. */
static route_map_result_t route_set_local_pref(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1396,7 +1403,8 @@ struct route_map_rule_cmd route_set_local_pref_cmd = {
/* `set weight WEIGHT' */
/* Set weight. */
-static route_map_result_t route_set_weight(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_weight(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1424,7 +1432,8 @@ struct route_map_rule_cmd route_set_weight_cmd = {
/* `set metric METRIC' */
/* Set metric to attribute. */
-static route_map_result_t route_set_metric(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_metric(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1457,7 +1466,7 @@ struct route_map_rule_cmd route_set_metric_cmd = {
/* For AS path prepend mechanism. */
static route_map_result_t route_set_aspath_prepend(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1520,7 +1529,7 @@ struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
* Make a deep copy of existing AS_PATH, but for the first ASn only.
*/
static route_map_result_t route_set_aspath_exclude(void *rule,
- struct prefix *dummy,
+ const struct prefix *dummy,
route_map_object_t type,
void *object)
{
@@ -1554,7 +1563,8 @@ struct rmap_com_set {
};
/* For community set mechanism. */
-static route_map_result_t route_set_community(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_community(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1670,7 +1680,7 @@ struct rmap_lcom_set {
/* For lcommunity set mechanism. */
static route_map_result_t route_set_lcommunity(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1783,7 +1793,7 @@ struct route_map_rule_cmd route_set_lcommunity_cmd = {
/* For large community set mechanism. */
static route_map_result_t route_set_lcommunity_delete(void *rule,
- struct prefix *prefix,
+ const struct prefix *pfx,
route_map_object_t type,
void *object)
{
@@ -1866,10 +1876,11 @@ struct route_map_rule_cmd route_set_lcommunity_delete_cmd = {
/* `set comm-list (<1-99>|<100-500>|WORD) delete' */
/* For community set mechanism. */
-static route_map_result_t route_set_community_delete(void *rule,
- struct prefix *prefix,
- route_map_object_t type,
- void *object)
+static route_map_result_t route_set_community_delete(
+ void *rule,
+ const struct prefix *prefix,
+ route_map_object_t type,
+ void *object)
{
struct community_list *list;
struct community *merge;
@@ -1950,7 +1961,7 @@ struct route_map_rule_cmd route_set_community_delete_cmd = {
/* For community set mechanism. Used by _rt and _soo. */
static route_map_result_t route_set_ecommunity(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -2037,7 +2048,8 @@ struct route_map_rule_cmd route_set_ecommunity_soo_cmd = {
/* `set origin ORIGIN' */
/* For origin set. */
-static route_map_result_t route_set_origin(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_origin(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -2087,7 +2099,7 @@ struct route_map_rule_cmd route_set_origin_cmd = {
/* For atomic aggregate set. */
static route_map_result_t route_set_atomic_aggregate(void *rule,
- struct prefix *prefix,
+ const struct prefix *pfx,
route_map_object_t type,
void *object)
{
@@ -2127,7 +2139,7 @@ struct aggregator {
};
static route_map_result_t route_set_aggregator_as(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -2180,7 +2192,8 @@ struct route_map_rule_cmd route_set_aggregator_as_cmd = {
};
/* Set tag to object. object must be pointer to struct bgp_info */
-static route_map_result_t route_set_tag(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_tag(void *rule,
+ const struct prefix *prefix,
route_map_object_t type, void *object)
{
route_tag_t *tag;
@@ -2205,7 +2218,7 @@ static struct route_map_rule_cmd route_set_tag_cmd = {
/* Set label-index to object. object must be pointer to struct bgp_info */
static route_map_result_t route_set_label_index(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -2239,7 +2252,7 @@ static struct route_map_rule_cmd route_set_label_index_cmd = {
/* `match ipv6 address IP_ACCESS_LIST' */
static route_map_result_t route_match_ipv6_address(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -2275,7 +2288,7 @@ struct route_map_rule_cmd route_match_ipv6_address_cmd = {
/* `match ipv6 next-hop IP_ADDRESS' */
static route_map_result_t route_match_ipv6_next_hop(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -2327,7 +2340,7 @@ struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
/* `match ipv6 address prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix,
+route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
@@ -2363,7 +2376,7 @@ struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
/* Set nexthop to object. ojbect must be pointer to struct attr. */
static route_map_result_t route_set_ipv6_nexthop_global(void *rule,
- struct prefix *prefix,
+ const struct prefix *p,
route_map_object_t type,
void *object)
{
@@ -2423,7 +2436,7 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd = {
/* Set next-hop preference value. */
static route_map_result_t
-route_set_ipv6_nexthop_prefer_global(void *rule, struct prefix *prefix,
+route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct bgp_info *bgp_info;
@@ -2477,7 +2490,7 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd = {
/* Set nexthop to object. ojbect must be pointer to struct attr. */
static route_map_result_t route_set_ipv6_nexthop_local(void *rule,
- struct prefix *prefix,
+ const struct prefix *p,
route_map_object_t type,
void *object)
{
@@ -2540,7 +2553,7 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = {
/* Set nexthop to object. ojbect must be pointer to struct attr. */
static route_map_result_t route_set_ipv6_nexthop_peer(void *rule,
- struct prefix *prefix,
+ const struct prefix *pfx,
route_map_object_t type,
void *object)
{
@@ -2619,7 +2632,7 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
/* `set ipv4 vpn next-hop A.B.C.D' */
static route_map_result_t route_set_vpnv4_nexthop(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -2659,7 +2672,7 @@ static void *route_set_vpnv4_nexthop_compile(const char *arg)
/* `set ipv6 vpn next-hop A.B.C.D' */
static route_map_result_t route_set_vpnv6_nexthop(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -2715,7 +2728,7 @@ struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
/* For origin set. */
static route_map_result_t route_set_originator_id(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 62cb3c2edb..19aab63ea3 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -193,6 +193,7 @@ EXTRA_DIST = frr-sphinx.mk \
developer/workflow.rst \
developer/zebra.rst \
user/babeld.rst \
+ user/ldpd.rst \
user/basic.rst \
user/bgp.rst \
user/bugs.rst \
diff --git a/doc/extra/spelling_wordlist.txt b/doc/extra/spelling_wordlist.txt
index 4c9455e8e9..2944592962 100644
--- a/doc/extra/spelling_wordlist.txt
+++ b/doc/extra/spelling_wordlist.txt
@@ -83,6 +83,7 @@ IPv
isis
isisd
lan
+ldpd
le
libc
libcap
diff --git a/doc/user/index.rst b/doc/user/index.rst
index a8109fe479..746cc1c32d 100644
--- a/doc/user/index.rst
+++ b/doc/user/index.rst
@@ -41,6 +41,7 @@ Protocols
zebra
bgp
babeld
+ ldpd
eigrpd
isisd
nhrpd
diff --git a/doc/user/ldpd.rst b/doc/user/ldpd.rst
new file mode 100644
index 0000000000..8d88ef176b
--- /dev/null
+++ b/doc/user/ldpd.rst
@@ -0,0 +1,309 @@
+.. _ldp:
+
+***
+LDP
+***
+
+The *ldpd* daemon is a standardised protocol that permits exchanging MPLS label
+information between MPLS devices. The LDP protocol creates peering between
+devices, so as to exchange that label information. This information is stored in
+MPLS table of *zebra*, and it injects that MPLS information in the underlying
+system (Linux kernel or OpenBSD system for instance).
+*ldpd* provides necessary options to create a Layer 2 VPN across MPLS network.
+For instance, it is possible to interconnect several sites that share the same
+broadcast domain.
+
+FRR implements LDP as described in :rfc:`5036`; other LDP standard are the
+following ones: :rfc:`6720`, :rfc:`6667`, :rfc:`5919`, :rfc:`5561`, :rfc:`7552`,
+:rfc:`4447`.
+Because MPLS is already available, FRR also supports :rfc:`3031`.
+
+Running Ldpd
+============
+
+The *ldpd* daemon can be invoked with any of the common
+options (:ref:`common-invocation-options`).
+
+The *zebra* daemon must be running before *ldpd* is invoked.
+
+Configuration of *ldpd* is done in its configuration file
+:file:`ldpd.conf`.
+
+
+.. _understanding-ldp:
+
+Understanding LDP principles
+============================
+
+Let's first introduce some definitions that permit understand better the LDP
+protocol:
+
+- `LSR` : Labeled Switch Router. Networking devices handling labels used to
+ forward traffic between and through them.
+
+- `LER` : Labeled Edge Router. A Labeled edge router is located at the edge of
+ an MPLS network, generally between an IP network and an MPLS network.
+
+
+``LDP`` aims at sharing label information across devices. It tries to establish
+peering with remote LDP capable devices, first by discovering using UDP port 646
+, then by peering using TCP port 646. Once the TCP session is established, the
+label information is shared, through label advertisements.
+
+There are different methods to send label advertisement modes. The
+implementation actually supports the following : Liberal Label Retention +
+Downstream Unsolicited + Independent Control.
+The other advertising modes are depicted below, and compared with the current
+implementation.
+
+- Liberal label retention versus conservative mode
+ In liberal mode, every label sent by every LSR is stored in the MPLS table.
+ In conservative mode, only the label that was sent by the best next hop
+ (determined by the IGP metric) for that particular FEC is stored in the MPLS
+ table.
+
+- Independent LSP Control versus ordered LSP Control
+ MPLS has two ways of binding labels to FEC’s; either through ordered LSP
+ control, or independent LSP control.
+ Ordered LSP control only binds a label to a FEC if it is the egress LSR, or
+ the router received a label binding for a FEC from the next hop router. In
+ this mode, an MPLS router will create a label binding for each FEC and
+ distribute it to its neighbors so long as he has a entry in the RIB for the
+ destination.
+ In the other mode, label bindings are made without any dependencies on another
+ router advertising a label for a particular FEC. Each router makes it own
+ independent decision to create a label for each FEC.
+ By default IOS uses Independent LSP Control, while Juniper implements the
+ Ordered Control. Both modes are interoperable, the difference is that Ordered
+ Control prevent blackholing during the LDP convergence process, at cost of
+ slowing down the convergence itself
+
+- unsolicited downstream versus downstream on demand
+ Downstream on demand label distribution is where an LSR must explicitly
+ request that a label be sent from its downstream router for a particular FEC.
+ Unsolicited label distribution is where a label is sent from the downstream
+ router without the original router requesting it.
+
+.. _configuring-ldpd:
+
+.. _ldp-configuration:
+
+LDP Configuration
+===================
+
+.. index:: [no] mpls ldp
+.. clicmd:: [no] mpls ldp
+
+ Enable or disable LDP daemon
+
+.. index:: [no] router-id A.B.C.D
+.. clicmd:: [no] router-id A.B.C.D
+
+ The following command located under MPLS router node configures the MPLS
+ router-id of the local device.
+
+.. index:: [no] address-family [ipv4 | ipv6]
+.. clicmd:: [no] address-family [ipv4 | ipv6]
+
+ Configure LDP for IPv4 or IPv6 address-family. Located under MPLS route node,
+ this subnode permits configuring the LDP neighbors.
+
+.. index:: [no] interface IFACE
+.. clicmd:: [no] interface IFACE
+
+ Located under MPLS address-family node, use this command to enable or disable
+ LDP discovery per interface. IFACE stands for the interface name where LDP is
+ enabled. By default it is disabled. Once this command executed, the
+ address-family interface node is configured.
+
+.. index:: [no] discovery transport-address A.B.C.D | A:B::C:D
+.. clicmd:: [no] discovery transport-address A.B.C.D | A:B::C:D
+
+ Located under mpls address-family interface node, use this command to set
+ the IPv4 or IPv6 transport-address used by the LDP protocol to talk on this
+ interface.
+
+.. index:: [no] neighbor A.B.C.D password PASSWORD
+.. clicmd:: [no] neighbor A.B.C.D password PASSWORD
+
+ The following command located under MPLS router node configures the router
+ of a LDP device. This device, if found, will have to comply with the
+ configured password. PASSWORD is a clear text password wit its digest sent
+ through the network.
+
+.. index:: [no] neighbor A.B.C.D holdtime HOLDTIME
+.. clicmd:: [no] neighbor A.B.C.D holdtime HOLDTIME
+
+ The following command located under MPLS router node configures the holdtime
+ value in seconds of the LDP neighbor ID. Configuring it triggers a keepalive
+ mechanism. That value can be configured between 15 and 65535 seconds. After
+ this time of non response, the LDP established session will be considered as
+ set to down. By default, no holdtime is configured for the LDP devices.
+
+.. index:: [no] discovery hello holdtime HOLDTIME
+.. clicmd:: [no] discovery hello holdtime HOLDTIME
+
+.. index:: [no] discovery hello interval INTERVAL
+.. clicmd:: [no] discovery hello interval INTERVAL
+
+ INTERVAL value ranges from 1 to 65535 seconds. Default value is 5 seconds.
+ This is the value between each hello timer message sent.
+ HOLDTIME value ranges from 1 to 65535 seconds. Default value is 15 seconds.
+ That value is added as a TLV in the LDP messages.
+
+.. _show-ldp-information:
+
+Show LDP Information
+====================
+
+These commands dump various parts of *ldpd*.
+
+.. index:: show mpls ldp neighbor [A.B.C.D]
+.. clicmd:: show mpls ldp neighbor [A.B.C.D]
+
+ This command dumps the various neighbors discovered. Below example shows that
+ local machine has an operation neighbor with ID set to 1.1.1.1.
+
+ ::
+
+ west-vm# show mpls ldp neighbor
+ AF ID State Remote Address Uptime
+ ipv4 1.1.1.1 OPERATIONAL 1.1.1.1 00:01:37
+ west-vm#
+
+.. index:: show mpls ldp neighbor [A.B.C.D] capabilities
+.. clicmd:: show mpls ldp neighbor [A.B.C.D] capabilities
+
+.. index:: show mpls ldp neighbor [A.B.C.D] detail
+.. clicmd:: show mpls ldp neighbor [A.B.C.D] detail
+
+ Above commands dump other neighbor information.
+
+.. index:: show mpls ldp discovery [detail]
+.. clicmd:: show mpls ldp discovery [detail]
+
+.. index:: show mpls ldp ipv4 discovery [detail]
+.. clicmd:: show mpls ldp ipv4 discovery [detail]
+
+.. index:: show mpls ldp ipv6 discovery [detail]
+.. clicmd:: show mpls ldp ipv6 discovery [detail]
+
+ Above commands dump discovery information.
+
+.. index:: show mpls ldp ipv4 interface
+.. clicmd:: show mpls ldp ipv4 interface
+
+.. index:: show mpls ldp ipv6 interface
+.. clicmd:: show mpls ldp ipv6 interface
+
+ Above command dumps the IPv4 or IPv6 interface per where LDP is enabled.
+ Below output illustrates what is dumped for IPv4.
+
+ ::
+
+ west-vm# show mpls ldp ipv4 interface
+ AF Interface State Uptime Hello Timers ac
+ ipv4 eth1 ACTIVE 00:08:35 5/15 0
+ ipv4 eth3 ACTIVE 00:08:35 5/15 1
+
+
+.. index:: show mpls ldp ipv4|ipv6 binding
+.. clicmd:: show mpls ldp ipv4|ipv6 binding
+
+ Above command dumps the binding obtained through MPLS exchanges with LDP.
+
+ ::
+
+ west-vm# show mpls ldp ipv4 binding
+ AF Destination Nexthop Local Label Remote Label In Use
+ ipv4 1.1.1.1/32 1.1.1.1 16 imp-null yes
+ ipv4 2.2.2.2/32 1.1.1.1 imp-null 16 no
+ ipv4 10.0.2.0/24 1.1.1.1 imp-null imp-null no
+ ipv4 10.115.0.0/24 1.1.1.1 imp-null 17 no
+ ipv4 10.135.0.0/24 1.1.1.1 imp-null imp-null no
+ ipv4 10.200.0.0/24 1.1.1.1 17 imp-null yes
+ west-vm#
+
+LDP debugging commands
+========================
+
+.. index::
+ simple: debug mpls ldp KIND
+ simple: no debug mpls ldp KIND
+
+.. clicmd:: [no] debug mpls ldp KIND
+
+ Enable or disable debugging messages of a given kind. ``KIND`` can
+ be one of:
+
+ - ``discovery``
+ - ``errors``
+ - ``event``
+ - ``labels``
+ - ``messages``
+ - ``zebra``
+
+LDP Example Configuration
+=========================
+
+Below configuration gives a typical MPLS configuration of a device located in a
+MPLS backbone. LDP is enabled on two interfaces and will attempt to peer with
+two neighbors with router-id set to either 1.1.1.1 or 3.3.3.3.
+
+.. code-block:: frr
+
+ mpls ldp
+ router-id 2.2.2.2
+ neighbor 1.1.1.1 password test
+ neighbor 3.3.3.3 password test
+ !
+ address-family ipv4
+ discovery transport-address 2.2.2.2
+ !
+ interface eth1
+ !
+ interface eth3
+ !
+ exit-address-family
+ !
+
+
+Deploying LDP across a backbone generally is done in a full mesh configuration
+topology. LDP is typically deployed with an IGP like OSPF, that helps discover
+the remote IPs. Below example is an OSPF configuration extract that goes with
+LDP configuration
+
+.. code-block:: frr
+
+ router ospf
+ ospf router-id 2.2.2.2
+ network 0.0.0.0/0 area 0
+ !
+
+
+Below output shows the routing entry on the LER side. The OSPF routing entry
+(10.200.0.0) is associated with Label entry (17), and shows that MPLS push action
+that traffic to that destination will be applied.
+
+::
+
+ north-vm# show ip route
+ Codes: K - kernel route, C - connected, S - static, R - RIP,
+ O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
+ T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
+ F - PBR,
+ > - selected route, * - FIB route
+
+ O>* 1.1.1.1/32 [110/120] via 10.115.0.1, eth2, label 16, 00:00:15
+ O>* 2.2.2.2/32 [110/20] via 10.115.0.1, eth2, label implicit-null, 00:00:15
+ O 3.3.3.3/32 [110/10] via 0.0.0.0, loopback1 onlink, 00:01:19
+ C>* 3.3.3.3/32 is directly connected, loopback1, 00:01:29
+ O>* 10.0.2.0/24 [110/11] via 10.115.0.1, eth2, label implicit-null, 00:00:15
+ O 10.100.0.0/24 [110/10] is directly connected, eth1, 00:00:32
+ C>* 10.100.0.0/24 is directly connected, eth1, 00:00:32
+ O 10.115.0.0/24 [110/10] is directly connected, eth2, 00:00:25
+ C>* 10.115.0.0/24 is directly connected, eth2, 00:00:32
+ O>* 10.135.0.0/24 [110/110] via 10.115.0.1, eth2, label implicit-null, 00:00:15
+ O>* 10.200.0.0/24 [110/210] via 10.115.0.1, eth2, label 17, 00:00:15
+ north-vm#
+
diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c
index d92207d57c..3c2cf7b3fc 100644
--- a/isisd/isis_routemap.c
+++ b/isisd/isis_routemap.c
@@ -50,7 +50,7 @@
#include "isis_routemap.h"
static route_map_result_t route_match_ip_address(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -83,7 +83,7 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = {
/* ------------------------------------------------------------*/
static route_map_result_t
-route_match_ip_address_prefix_list(void *rule, struct prefix *prefix,
+route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
@@ -116,7 +116,7 @@ struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
/* ------------------------------------------------------------*/
static route_map_result_t route_match_ipv6_address(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -149,7 +149,7 @@ static struct route_map_rule_cmd route_match_ipv6_address_cmd = {
/* ------------------------------------------------------------*/
static route_map_result_t
-route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix,
+route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
@@ -181,7 +181,8 @@ struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
/* ------------------------------------------------------------*/
-static route_map_result_t route_set_metric(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_metric(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
diff --git a/ldpd/ldp_vty_cmds.c b/ldpd/ldp_vty_cmds.c
index 6c86582960..d77a3e7e93 100644
--- a/ldpd/ldp_vty_cmds.c
+++ b/ldpd/ldp_vty_cmds.c
@@ -861,6 +861,7 @@ ldp_vty_init (void)
install_element(LDP_IPV6_NODE, &ldp_label_remote_accept_cmd);
install_element(LDP_IPV6_NODE, &ldp_ttl_security_disable_cmd);
install_element(LDP_IPV6_NODE, &ldp_interface_cmd);
+ install_element(LDP_IPV6_NODE, &no_ldp_interface_cmd);
install_element(LDP_IPV6_NODE, &ldp_session_holdtime_cmd);
install_element(LDP_IPV6_NODE, &ldp_neighbor_ipv6_targeted_cmd);
install_element(LDP_IPV6_NODE, &ldp_exit_address_family_cmd);
diff --git a/lib/filter.c b/lib/filter.c
index 670c65374a..0528b0f2ad 100644
--- a/lib/filter.c
+++ b/lib/filter.c
@@ -157,7 +157,7 @@ static const char *filter_type_str(struct filter *filter)
}
/* If filter match to the prefix then return 1. */
-static int filter_match_cisco(struct filter *mfilter, struct prefix *p)
+static int filter_match_cisco(struct filter *mfilter, const struct prefix *p)
{
struct filter_cisco *filter;
struct in_addr mask;
@@ -181,7 +181,7 @@ static int filter_match_cisco(struct filter *mfilter, struct prefix *p)
}
/* If filter match to the prefix then return 1. */
-static int filter_match_zebra(struct filter *mfilter, struct prefix *p)
+static int filter_match_zebra(struct filter *mfilter, const struct prefix *p)
{
struct filter_zebra *filter = NULL;
@@ -372,10 +372,11 @@ static struct access_list *access_list_get(afi_t afi, const char *name)
}
/* Apply access list to object (which should be struct prefix *). */
-enum filter_type access_list_apply(struct access_list *access, void *object)
+enum filter_type access_list_apply(struct access_list *access,
+ const void *object)
{
struct filter *filter;
- struct prefix *p = (struct prefix *)object;
+ const struct prefix *p = (const struct prefix *)object;
if (access == NULL)
return FILTER_DENY;
diff --git a/lib/filter.h b/lib/filter.h
index c02516409b..97854b1e97 100644
--- a/lib/filter.h
+++ b/lib/filter.h
@@ -59,6 +59,7 @@ extern void access_list_reset(void);
extern void access_list_add_hook(void (*func)(struct access_list *));
extern void access_list_delete_hook(void (*func)(struct access_list *));
extern struct access_list *access_list_lookup(afi_t, const char *);
-extern enum filter_type access_list_apply(struct access_list *, void *);
+extern enum filter_type access_list_apply(struct access_list *access,
+ const void *object);
#endif /* _ZEBRA_FILTER_H */
diff --git a/lib/plist.c b/lib/plist.c
index 056b737f54..2b666f256f 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -656,7 +656,7 @@ static const char *prefix_list_type_str(struct prefix_list_entry *pentry)
}
static int prefix_list_entry_match(struct prefix_list_entry *pentry,
- struct prefix *p)
+ const struct prefix *p)
{
int ret;
@@ -683,14 +683,15 @@ static int prefix_list_entry_match(struct prefix_list_entry *pentry,
return 1;
}
-enum prefix_list_type prefix_list_apply_which_prefix(struct prefix_list *plist,
- struct prefix **which,
- void *object)
+enum prefix_list_type prefix_list_apply_which_prefix(
+ struct prefix_list *plist,
+ const struct prefix **which,
+ const void *object)
{
struct prefix_list_entry *pentry, *pbest = NULL;
- struct prefix *p = (struct prefix *)object;
- uint8_t *byte = p->u.val;
+ const struct prefix *p = (const struct prefix *)object;
+ const uint8_t *byte = p->u.val;
size_t depth;
size_t validbits = p->prefixlen;
struct pltrie_table *table;
diff --git a/lib/plist.h b/lib/plist.h
index 67e345a485..fecbe0e2ce 100644
--- a/lib/plist.h
+++ b/lib/plist.h
@@ -61,8 +61,9 @@ extern struct prefix_list *prefix_list_lookup(afi_t, const char *);
* If it is a empty plist return a NULL pointer.
*/
extern enum prefix_list_type
-prefix_list_apply_which_prefix(struct prefix_list *plist, struct prefix **which,
- void *object);
+prefix_list_apply_which_prefix(struct prefix_list *plist,
+ const struct prefix **which,
+ const void *object);
#define prefix_list_apply(A, B) prefix_list_apply_which_prefix((A), NULL, (B))
extern struct prefix_list *prefix_bgp_orf_lookup(afi_t, const char *);
diff --git a/lib/routemap.c b/lib/routemap.c
index 056c793454..6c4585365a 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -1387,7 +1387,7 @@ int route_map_delete_set(struct route_map_index *index, const char *set_name,
static route_map_result_t
route_map_apply_match(struct route_map_rule_list *match_list,
- struct prefix *prefix, route_map_object_t type,
+ const struct prefix *prefix, route_map_object_t type,
void *object)
{
route_map_result_t ret = RMAP_NOMATCH;
@@ -1417,7 +1417,8 @@ route_map_apply_match(struct route_map_rule_list *match_list,
}
/* Apply route map to the object. */
-route_map_result_t route_map_apply(struct route_map *map, struct prefix *prefix,
+route_map_result_t route_map_apply(struct route_map *map,
+ const struct prefix *prefix,
route_map_object_t type, void *object)
{
static int recursion = 0;
diff --git a/lib/routemap.h b/lib/routemap.h
index 0aeba7e1f6..0f7c391f84 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -87,8 +87,10 @@ struct route_map_rule_cmd {
const char *str;
/* Function for value set or match. */
- route_map_result_t (*func_apply)(void *, struct prefix *,
- route_map_object_t, void *);
+ route_map_result_t (*func_apply)(void *rule,
+ const struct prefix *prefix,
+ route_map_object_t type,
+ void *object);
/* Compile argument and return result as void *. */
void *(*func_compile)(const char *);
@@ -208,7 +210,7 @@ extern struct route_map *route_map_lookup_by_name(const char *name);
/* Apply route map to the object. */
extern route_map_result_t route_map_apply(struct route_map *map,
- struct prefix *,
+ const struct prefix *prefix,
route_map_object_t object_type,
void *object);
diff --git a/lib/zclient.h b/lib/zclient.h
index 10a1723010..49419b3df3 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -448,6 +448,8 @@ enum zapi_iptable_notify_owner {
/* Zebra MAC types */
#define ZEBRA_MACIP_TYPE_STICKY 0x01 /* Sticky MAC*/
#define ZEBRA_MACIP_TYPE_GW 0x02 /* gateway (SVI) mac*/
+#define ZEBRA_MACIP_TYPE_ROUTER_FLAG 0x04 /* Router Flag - proxy NA */
+#define ZEBRA_MACIP_TYPE_OVERRIDE_FLAG 0x08 /* Override Flag */
struct zclient_options {
bool receive_notify;
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index a723396507..e6bd3faf40 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -1345,7 +1345,8 @@ static void ospf6_redistribute_show_config(struct vty *vty)
/* Routemap Functions */
static route_map_result_t
-ospf6_routemap_rule_match_address_prefixlist(void *rule, struct prefix *prefix,
+ospf6_routemap_rule_match_address_prefixlist(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1384,7 +1385,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_match_address_prefixlist_cmd = {
/* Match function should return 1 if match is success else return
zero. */
static route_map_result_t
-ospf6_routemap_rule_match_interface(void *rule, struct prefix *prefix,
+ospf6_routemap_rule_match_interface(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct interface *ifp;
@@ -1422,7 +1423,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_match_interface_cmd = {
/* Match function for matching route tags */
static route_map_result_t ospf6_routemap_rule_match_tag(void *rule,
- struct prefix *prefix,
+ const struct prefix *p,
route_map_object_t type,
void *object)
{
@@ -1442,7 +1443,7 @@ static struct route_map_rule_cmd ospf6_routemap_rule_match_tag_cmd = {
};
static route_map_result_t
-ospf6_routemap_rule_set_metric_type(void *rule, struct prefix *prefix,
+ospf6_routemap_rule_set_metric_type(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
char *metric_type = rule;
@@ -1478,7 +1479,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_set_metric_type_cmd = {
};
static route_map_result_t
-ospf6_routemap_rule_set_metric(void *rule, struct prefix *prefix,
+ospf6_routemap_rule_set_metric(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
char *metric = rule;
@@ -1513,7 +1514,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_set_metric_cmd = {
};
static route_map_result_t
-ospf6_routemap_rule_set_forwarding(void *rule, struct prefix *prefix,
+ospf6_routemap_rule_set_forwarding(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
char *forwarding = rule;
@@ -1551,7 +1552,7 @@ struct route_map_rule_cmd ospf6_routemap_rule_set_forwarding_cmd = {
};
static route_map_result_t ospf6_routemap_rule_set_tag(void *rule,
- struct prefix *prefix,
+ const struct prefix *p,
route_map_object_t type,
void *object)
{
diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c
index f3271acfa2..c5ec1db336 100644
--- a/ospfd/ospf_routemap.c
+++ b/ospfd/ospf_routemap.c
@@ -118,7 +118,7 @@ static void ospf_route_map_event(route_map_event_t event, const char *name)
/* `match ip netxthop ' */
/* Match function return 1 if match is success else return zero. */
static route_map_result_t route_match_ip_nexthop(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -163,7 +163,7 @@ struct route_map_rule_cmd route_match_ip_nexthop_cmd = {
/* `match ip next-hop prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix,
+route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
@@ -205,7 +205,7 @@ struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
/* Match function should return 1 if match is success else return
zero. */
static route_map_result_t route_match_ip_address(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -244,7 +244,7 @@ struct route_map_rule_cmd route_match_ip_address_cmd = {
/* `match ip address prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ip_address_prefix_list(void *rule, struct prefix *prefix,
+route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
@@ -280,7 +280,7 @@ struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
/* Match function should return 1 if match is success else return
zero. */
static route_map_result_t route_match_interface(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -318,7 +318,8 @@ struct route_map_rule_cmd route_match_interface_cmd = {
route_match_interface_free};
/* Match function return 1 if match is success else return zero. */
-static route_map_result_t route_match_tag(void *rule, struct prefix *prefix,
+static route_map_result_t route_match_tag(void *rule,
+ const struct prefix *prefix,
route_map_object_t type, void *object)
{
route_tag_t *tag;
@@ -348,7 +349,8 @@ struct ospf_metric {
/* `set metric METRIC' */
/* Set metric to attribute. */
-static route_map_result_t route_set_metric(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_metric(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -427,7 +429,7 @@ struct route_map_rule_cmd route_set_metric_cmd = {
/* `set metric-type TYPE' */
/* Set metric-type to attribute. */
static route_map_result_t route_set_metric_type(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -476,7 +478,7 @@ struct route_map_rule_cmd route_set_metric_type_cmd = {
route_set_metric_type_free,
};
-static route_map_result_t route_set_tag(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_tag(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
route_tag_t *tag;
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index cc39b09043..c1623ec15e 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -194,7 +194,7 @@ static int pim_rp_prefix_list_used(struct pim_instance *pim, const char *plist)
*/
static struct rp_info *pim_rp_find_exact(struct pim_instance *pim,
struct in_addr rp,
- struct prefix *group)
+ const struct prefix *group)
{
struct listnode *node;
struct rp_info *rp_info;
@@ -212,13 +212,13 @@ static struct rp_info *pim_rp_find_exact(struct pim_instance *pim,
* Given a group, return the rp_info for that group
*/
static struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
- struct prefix *group)
+ const struct prefix *group)
{
struct listnode *node;
struct rp_info *best = NULL;
struct rp_info *rp_info;
struct prefix_list *plist;
- struct prefix *p, *bp;
+ const struct prefix *p, *bp;
struct route_node *rn;
bp = NULL;
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index 38a29b72af..b947ca0625 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -868,6 +868,7 @@ void igmp_source_forward_reevaluate_all(struct pim_instance *pim)
void igmp_source_forward_start(struct pim_instance *pim,
struct igmp_source *source)
{
+ struct pim_interface *pim_oif;
struct igmp_group *group;
struct prefix_sg sg;
int result;
@@ -893,10 +894,20 @@ void igmp_source_forward_start(struct pim_instance *pim,
}
group = source->source_group;
+ pim_oif = group->group_igmp_sock->interface->info;
+ if (!pim_oif) {
+ if (PIM_DEBUG_IGMP_TRACE) {
+ zlog_debug(
+ "%s: multicast not enabled on oif=%s ?",
+ __PRETTY_FUNCTION__,
+ source->source_group->group_igmp_sock
+ ->interface->name);
+ }
+ return;
+ }
if (!source->source_channel_oil) {
struct in_addr vif_source;
- struct pim_interface *pim_oif;
struct prefix nht_p, src, grp;
struct pim_nexthop_cache out_pnc;
struct pim_nexthop nexthop;
@@ -983,19 +994,6 @@ void igmp_source_forward_start(struct pim_instance *pim,
source and receiver attached to the same interface. See TODO
T22.
*/
- pim_oif =
- source->source_group->group_igmp_sock->interface->info;
- if (!pim_oif) {
- if (PIM_DEBUG_IGMP_TRACE) {
- zlog_debug(
- "%s: multicast not enabled on oif=%s ?",
- __PRETTY_FUNCTION__,
- source->source_group->group_igmp_sock
- ->interface->name);
- }
- return;
- }
-
if (input_iface_vif_index == pim_oif->mroute_vif_index) {
/* ignore request for looped MFC entry */
if (PIM_DEBUG_IGMP_TRACE) {
@@ -1036,12 +1034,15 @@ void igmp_source_forward_start(struct pim_instance *pim,
return;
}
+ if (!(PIM_I_am_DR(pim_oif)))
+ return;
+
/*
Feed IGMPv3-gathered local membership information into PIM
per-interface (S,G) state.
*/
if (!pim_ifchannel_local_membership_add(
- group->group_igmp_sock->interface, &sg)) {
+ group->group_igmp_sock->interface, &sg)) {
if (PIM_DEBUG_MROUTE)
zlog_warn("%s: Failure to add local membership for %s",
__PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c
index 2c02324876..88473c164e 100644
--- a/ripd/rip_routemap.c
+++ b/ripd/rip_routemap.c
@@ -58,7 +58,8 @@ static void rip_route_map_update(const char *notused)
/* `match metric METRIC' */
/* Match function return 1 if match is success else return zero. */
-static route_map_result_t route_match_metric(void *rule, struct prefix *prefix,
+static route_map_result_t route_match_metric(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -111,7 +112,7 @@ struct route_map_rule_cmd route_match_metric_cmd = {
/* `match interface IFNAME' */
/* Match function return 1 if match is success else return zero. */
static route_map_result_t route_match_interface(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -159,7 +160,7 @@ struct route_map_rule_cmd route_match_interface_cmd = {
/* Match function return 1 if match is success else return zero. */
static route_map_result_t route_match_ip_next_hop(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -206,7 +207,7 @@ static struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
/* `match ip next-hop prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix,
+route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
@@ -251,7 +252,7 @@ static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
/* Match function should return 1 if match is success else return
zero. */
static route_map_result_t route_match_ip_address(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -290,7 +291,7 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = {
/* `match ip address prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ip_address_prefix_list(void *rule, struct prefix *prefix,
+route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
@@ -324,7 +325,7 @@ static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
/* `match tag TAG' */
/* Match function return 1 if match is success else return zero. */
-static route_map_result_t route_match_tag(void *rule, struct prefix *prefix,
+static route_map_result_t route_match_tag(void *rule, const struct prefix *p,
route_map_object_t type, void *object)
{
route_tag_t *tag;
@@ -354,7 +355,8 @@ static struct route_map_rule_cmd route_match_tag_cmd = {
/* `set metric METRIC' */
/* Set metric to attribute. */
-static route_map_result_t route_set_metric(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_metric(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -453,7 +455,7 @@ static struct route_map_rule_cmd route_set_metric_cmd = {
/* Set nexthop to object. ojbect must be pointer to struct attr. */
static route_map_result_t route_set_ip_nexthop(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -505,7 +507,7 @@ static struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
/* `set tag TAG' */
/* Set tag to object. ojbect must be pointer to struct attr. */
-static route_map_result_t route_set_tag(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_tag(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
route_tag_t *tag;
diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c
index e9a38d137b..a18332516e 100644
--- a/ripngd/ripng_routemap.c
+++ b/ripngd/ripng_routemap.c
@@ -38,7 +38,8 @@ struct rip_metric_modifier {
/* `match metric METRIC' */
/* Match function return 1 if match is success else return zero. */
-static route_map_result_t route_match_metric(void *rule, struct prefix *prefix,
+static route_map_result_t route_match_metric(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -86,7 +87,7 @@ static struct route_map_rule_cmd route_match_metric_cmd = {
/* `match interface IFNAME' */
/* Match function return 1 if match is success else return zero. */
static route_map_result_t route_match_interface(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -128,7 +129,8 @@ static struct route_map_rule_cmd route_match_interface_cmd = {
/* `match tag TAG' */
/* Match function return 1 if match is success else return zero. */
-static route_map_result_t route_match_tag(void *rule, struct prefix *prefix,
+static route_map_result_t route_match_tag(void *rule,
+ const struct prefix *prefix,
route_map_object_t type, void *object)
{
route_tag_t *tag;
@@ -157,7 +159,8 @@ static struct route_map_rule_cmd route_match_tag_cmd = {
/* `set metric METRIC' */
/* Set metric to attribute. */
-static route_map_result_t route_set_metric(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_metric(void *rule,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -254,7 +257,7 @@ static struct route_map_rule_cmd route_set_metric_cmd = {
/* Set nexthop to object. ojbect must be pointer to struct attr. */
static route_map_result_t route_set_ipv6_nexthop_local(void *rule,
- struct prefix *prefix,
+ const struct prefix *p,
route_map_object_t type,
void *object)
{
@@ -307,7 +310,8 @@ static struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = {
/* `set tag TAG' */
/* Set tag to object. ojbect must be pointer to struct attr. */
-static route_map_result_t route_set_tag(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_tag(void *rule,
+ const struct prefix *prefix,
route_map_object_t type, void *object)
{
route_tag_t *tag;
diff --git a/tools/frr-reload.py b/tools/frr-reload.py
index 208fb116e6..a9f183ed7b 100755
--- a/tools/frr-reload.py
+++ b/tools/frr-reload.py
@@ -403,7 +403,7 @@ end
self.save_contexts(ctx_keys, current_context_lines)
new_ctx = True
- elif line == "end":
+ elif line in ["end", "exit-vrf"]:
self.save_contexts(ctx_keys, current_context_lines)
log.debug('LINE %-50s: exiting old context, %-50s', line, ctx_keys)
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 56bff0d3f6..8943b434d7 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -891,8 +891,12 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
zns = zebra_ns_lookup(ns_id);
ifa = NLMSG_DATA(h);
- if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6)
+ if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) {
+ zlog_warn(
+ "Invalid address family: %d received from kernel interface addr change: %d",
+ ifa->ifa_family, h->nlmsg_type);
return 0;
+ }
if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
return 0;
@@ -1114,6 +1118,14 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
return 0;
}
+ if (!(ifi->ifi_family == AF_UNSPEC || ifi->ifi_family == AF_BRIDGE
+ || ifi->ifi_family == AF_INET6)) {
+ zlog_warn(
+ "Invalid address family: %d received from kernel link change: %d",
+ ifi->ifi_family, h->nlmsg_type);
+ return 0;
+ }
+
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
if (len < 0) {
zlog_err("%s: Message received from netlink is of a broken size %d %zu",
diff --git a/zebra/rt.h b/zebra/rt.h
index 57e62e4f6e..e40bae3a3e 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -122,7 +122,7 @@ extern int kernel_del_mac(struct interface *ifp, vlanid_t vid,
int local);
extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
- struct ethaddr *mac);
+ struct ethaddr *mac, uint8_t flags);
extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip);
/*
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 485abc3f12..4fe42f2ebc 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -387,8 +387,15 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
memcpy(&p.u.prefix4, dest, 4);
p.prefixlen = rtm->rtm_dst_len;
- src_p.prefixlen =
- 0; // Forces debug below to not display anything
+ if (rtm->rtm_src_len != 0) {
+ char buf[PREFIX_STRLEN];
+ zlog_warn("unsupported IPv4 sourcedest route (dest %s vrf %u)",
+ prefix2str(&p, buf, sizeof(buf)), vrf_id);
+ return 0;
+ }
+
+ /* Force debug below to not display anything for source */
+ src_p.prefixlen = 0;
} else if (rtm->rtm_family == AF_INET6) {
p.family = AF_INET6;
memcpy(&p.u.prefix6, dest, 16);
@@ -399,14 +406,6 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
src_p.prefixlen = rtm->rtm_src_len;
}
- if (rtm->rtm_src_len != 0) {
- char buf[PREFIX_STRLEN];
- zlog_warn(
- "unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
- prefix2str(&p, buf, sizeof(buf)), vrf_id);
- return 0;
- }
-
/*
* For ZEBRA_ROUTE_KERNEL types:
*
@@ -492,7 +491,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
nh.vrf_id = nh_vrf_id;
rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p,
- NULL, &nh, table, metric, mtu, distance, tag);
+ &src_p, &nh, table, metric, mtu, distance, tag);
} else {
/* This is a multipath route */
@@ -591,8 +590,8 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
if (re->nexthop_num == 0)
XFREE(MTYPE_RE, re);
else
- rib_add_multipath(afi, SAFI_UNICAST, &p, NULL,
- re);
+ rib_add_multipath(afi, SAFI_UNICAST, &p,
+ &src_p, re);
}
} else {
if (!tb[RTA_MULTIPATH]) {
@@ -624,12 +623,12 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
if (gate)
memcpy(&nh.gate, gate, sz);
rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags,
- &p, NULL, &nh, table, metric, true);
+ &p, &src_p, &nh, table, metric, true);
} else {
/* XXX: need to compare the entire list of nexthops
* here for NLM_F_APPEND stupidity */
rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags,
- &p, NULL, NULL, table, metric, true);
+ &p, &src_p, NULL, table, metric, true);
}
}
@@ -740,6 +739,15 @@ int netlink_route_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
return 0;
}
+ if (!(rtm->rtm_family == AF_INET || rtm->rtm_family == AF_INET6
+ || rtm->rtm_family == AF_ETHERNET
+ || rtm->rtm_family == AF_MPLS)) {
+ zlog_warn(
+ "Invalid address family: %d received from kernel route change: %d",
+ rtm->rtm_family, h->nlmsg_type);
+ return 0;
+ }
+
/* Connected route. */
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("%s %s %s proto %s NS %u",
@@ -2151,6 +2159,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
char buf2[INET6_ADDRSTRLEN];
int mac_present = 0;
uint8_t ext_learned;
+ uint8_t router_flag;
ndm = NLMSG_DATA(h);
@@ -2241,6 +2250,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
}
ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0;
+ router_flag = (ndm->ndm_flags & NTF_ROUTER) ? 1 : 0;
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
@@ -2263,7 +2273,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (ndm->ndm_state & NUD_VALID)
return zebra_vxlan_handle_kernel_neigh_update(
ifp, link_if, &ip, &mac, ndm->ndm_state,
- ext_learned);
+ ext_learned, router_flag);
return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
}
@@ -2386,12 +2396,19 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6)
return netlink_ipneigh_change(h, len, ns_id);
+ else {
+ zlog_warn(
+ "Invalid address family: %d received from kernel neighbor change: %d",
+ ndm->ndm_family, h->nlmsg_type);
+ return 0;
+ }
return 0;
}
static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
- struct ethaddr *mac, uint32_t flags, int cmd)
+ struct ethaddr *mac, uint8_t flags,
+ uint16_t state, int cmd)
{
struct {
struct nlmsghdr n;
@@ -2414,11 +2431,10 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
- req.ndm.ndm_state = flags;
+ req.ndm.ndm_state = state;
req.ndm.ndm_ifindex = ifp->ifindex;
req.ndm.ndm_type = RTN_UNICAST;
- req.ndm.ndm_flags = NTF_EXT_LEARNED;
-
+ req.ndm.ndm_flags = flags;
ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
@@ -2426,12 +2442,12 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s",
+ zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s flags 0x%x",
nl_msg_type_to_str(cmd),
nl_family_to_str(req.ndm.ndm_family), ifp->name,
ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)),
mac ? prefix_mac2str(mac, buf2, sizeof(buf2))
- : "null");
+ : "null", flags);
return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
0);
@@ -2452,14 +2468,15 @@ int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
}
int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
- struct ethaddr *mac)
+ struct ethaddr *mac, uint8_t flags)
{
- return netlink_neigh_update2(ifp, ip, mac, NUD_NOARP, RTM_NEWNEIGH);
+ return netlink_neigh_update2(ifp, ip, mac, flags,
+ NUD_NOARP, RTM_NEWNEIGH);
}
int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip)
{
- return netlink_neigh_update2(ifp, ip, NULL, 0, RTM_DELNEIGH);
+ return netlink_neigh_update2(ifp, ip, NULL, 0, 0, RTM_DELNEIGH);
}
/*
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index cba0376300..346699198f 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -88,7 +88,8 @@ static int kernel_rtm_add_labels(struct mpls_label_stack *nh_label,
#endif
/* Interface between zebra message and rtm message. */
-static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
+static int kernel_rtm_ipv4(int cmd, const struct prefix *p,
+ struct route_entry *re)
{
struct sockaddr_in *mask = NULL;
@@ -272,7 +273,8 @@ static int sin6_masklen(struct in6_addr mask)
#endif /* SIN6_LEN */
/* Interface between zebra message and rtm message. */
-static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
+static int kernel_rtm_ipv6(int cmd, const struct prefix *p,
+ struct route_entry *re)
{
struct sockaddr_in6 *mask;
struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
@@ -374,7 +376,7 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
return 0; /*XXX*/
}
-static int kernel_rtm(int cmd, struct prefix *p, struct route_entry *re)
+static int kernel_rtm(int cmd, const struct prefix *p, struct route_entry *re)
{
switch (PREFIX_FAMILY(p)) {
case AF_INET:
@@ -460,7 +462,7 @@ int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
}
int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
- struct ethaddr *mac)
+ struct ethaddr *mac, uint8_t flags)
{
return 0;
}
diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c
index c7a8517e17..d683e92bcc 100644
--- a/zebra/rule_netlink.c
+++ b/zebra/rule_netlink.c
@@ -204,8 +204,12 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
}
frh = NLMSG_DATA(h);
- if (frh->family != AF_INET && frh->family != AF_INET6)
+ if (frh->family != AF_INET && frh->family != AF_INET6) {
+ zlog_warn(
+ "Invalid address family: %d received from kernel rule change: %d",
+ frh->family, h->nlmsg_type);
return 0;
+ }
if (frh->action != FR_ACT_TO_TBL)
return 0;
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 9bf6bfa22f..71d48632c1 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -2331,7 +2331,7 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
if (!re)
return 0;
- assert(!src_p || afi == AFI_IP6);
+ assert(!src_p || !src_p->prefixlen || afi == AFI_IP6);
/* Lookup table. */
table = zebra_vrf_table_with_table_id(afi, safi, re->vrf_id, re->table);
@@ -2421,7 +2421,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
char buf2[INET6_ADDRSTRLEN];
rib_dest_t *dest;
- assert(!src_p || afi == AFI_IP6);
+ assert(!src_p || !src_p->prefixlen || afi == AFI_IP6);
/* Lookup table. */
table = zebra_vrf_table_with_table_id(afi, safi, vrf_id, table_id);
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index bf6718164f..0b48e87b1b 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -137,7 +137,8 @@ static int zebra_route_match_delete(struct vty *vty, const char *command,
/* 'match tag TAG'
* Match function return 1 if match is success else return 0
*/
-static route_map_result_t route_match_tag(void *rule, struct prefix *prefix,
+static route_map_result_t route_match_tag(void *rule,
+ const struct prefix *prefix,
route_map_object_t type, void *object)
{
route_tag_t *tag;
@@ -163,7 +164,7 @@ static struct route_map_rule_cmd route_match_tag_cmd = {
/* `match interface IFNAME' */
/* Match function return 1 if match is success else return zero. */
static route_map_result_t route_match_interface(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -879,7 +880,7 @@ DEFUN (show_ipv6_protocol_nht,
/* Match function return 1 if match is success else return zero. */
static route_map_result_t route_match_ip_next_hop(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -937,7 +938,7 @@ static struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
/* `match ip next-hop prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix,
+route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
@@ -993,7 +994,7 @@ static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
/* Match function should return 1 if match is success else return
zero. */
static route_map_result_t route_match_ip_address(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
@@ -1032,7 +1033,7 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = {
/* `match ip address prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ip_address_prefix_list(void *rule, struct prefix *prefix,
+route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
@@ -1068,7 +1069,7 @@ static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
/* `match ip address prefix-len PREFIXLEN' */
static route_map_result_t
-route_match_address_prefix_len(void *rule, struct prefix *prefix,
+route_match_address_prefix_len(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
uint32_t *prefixlen = (uint32_t *)rule;
@@ -1122,7 +1123,7 @@ static struct route_map_rule_cmd route_match_ipv6_address_prefix_len_cmd = {
/* `match ip nexthop prefix-len PREFIXLEN' */
static route_map_result_t
-route_match_ip_nexthop_prefix_len(void *rule, struct prefix *prefix,
+route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
uint32_t *prefixlen = (uint32_t *)rule;
@@ -1162,7 +1163,7 @@ static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = {
/* `match source-protocol PROTOCOL' */
static route_map_result_t route_match_source_protocol(void *rule,
- struct prefix *prefix,
+ const struct prefix *p,
route_map_object_t type,
void *object)
{
@@ -1204,7 +1205,7 @@ static struct route_map_rule_cmd route_match_source_protocol_cmd = {
/* `source-instance` */
static route_map_result_t route_match_source_instance(void *rule,
- struct prefix *prefix,
+ const struct prefix *p,
route_map_object_t type,
void *object)
{
@@ -1246,7 +1247,7 @@ static struct route_map_rule_cmd route_match_source_instance_cmd = {
/* `set src A.B.C.D' */
/* Set src. */
-static route_map_result_t route_set_src(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_src(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct nh_rmap_obj *nh_data;
@@ -1359,8 +1360,7 @@ route_map_result_t zebra_route_map_check(int family, int rib_type,
rmap = route_map_lookup_by_name(
proto_rm[family][ZEBRA_ROUTE_MAX]);
if (rmap) {
- ret = route_map_apply(rmap, (struct prefix *)p,
- RMAP_ZEBRA, &nh_obj);
+ ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
}
return (ret);
@@ -1385,7 +1385,8 @@ void zebra_del_import_table_route_map(afi_t afi, uint32_t table)
route_map_result_t
zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
- struct prefix *p, struct nexthop *nexthop,
+ const struct prefix *p,
+ struct nexthop *nexthop,
vrf_id_t vrf_id, route_tag_t tag,
const char *rmap_name)
{
@@ -1410,7 +1411,7 @@ zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
}
route_map_result_t zebra_nht_route_map_check(int family, int client_proto,
- struct prefix *p,
+ const struct prefix *p,
struct route_entry *re,
struct nexthop *nexthop)
{
@@ -1430,11 +1431,10 @@ route_map_result_t zebra_nht_route_map_check(int family, int client_proto,
if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX])
rmap = route_map_lookup_by_name(
nht_rm[family][ZEBRA_ROUTE_MAX]);
- if (rmap) {
+ if (rmap)
ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
- }
- return (ret);
+ return ret;
}
static void zebra_route_map_mark_update(const char *rmap_name)
diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h
index 688c8b7203..d33487d7af 100644
--- a/zebra/zebra_routemap.h
+++ b/zebra/zebra_routemap.h
@@ -35,7 +35,8 @@ extern void zebra_route_map_write_delay_timer(struct vty *);
extern route_map_result_t
zebra_import_table_route_map_check(int family, int rib_type, uint8_t instance,
- struct prefix *p, struct nexthop *nexthop,
+ const struct prefix *p,
+ struct nexthop *nexthop,
vrf_id_t vrf_id, route_tag_t tag,
const char *rmap_name);
extern route_map_result_t
@@ -43,7 +44,7 @@ zebra_route_map_check(int family, int rib_type, uint8_t instance,
const struct prefix *p, struct nexthop *nexthop,
vrf_id_t vrf_id, route_tag_t tag);
extern route_map_result_t
-zebra_nht_route_map_check(int family, int client_proto, struct prefix *p,
+zebra_nht_route_map_check(int family, int client_proto, const struct prefix *p,
struct route_entry *, struct nexthop *nexthop);
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 8a37e1df22..8ee47d2f1b 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -1198,7 +1198,8 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
break;
}
- if (re->vrf_id != nexthop->vrf_id) {
+ if ((re->vrf_id != nexthop->vrf_id)
+ && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
struct vrf *vrf =
vrf_lookup_by_id(nexthop->vrf_id);
@@ -1415,7 +1416,8 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
break;
}
- if (nexthop->vrf_id != re->vrf_id) {
+ if ((nexthop->vrf_id != re->vrf_id)
+ && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
struct vrf *vrf =
vrf_lookup_by_id(nexthop->vrf_id);
@@ -1569,7 +1571,8 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
break;
}
- if (nexthop->vrf_id != re->vrf_id) {
+ if ((nexthop->vrf_id != re->vrf_id)
+ && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
if (vrf)
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 59f0cf52f0..06d1b3618c 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -33,6 +33,9 @@
#include "jhash.h"
#include "vlan.h"
#include "vxlan.h"
+#ifdef GNU_LINUX
+#include <linux/neighbour.h>
+#endif
#include "zebra/rib.h"
#include "zebra/rt.h"
@@ -282,6 +285,7 @@ static void zvni_find_neigh_addr_width(struct hash_backet *backet, void *ctxt)
ipaddr2str(&n->ip, buf, sizeof(buf)), width = strlen(buf);
if (width > wctx->addr_width)
wctx->addr_width = width;
+
}
/*
@@ -327,6 +331,10 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
else
json_object_boolean_true_add(json, "defaultGateway");
}
+ if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)) {
+ if (!json)
+ vty_out(vty, " Router");
+ }
if (json == NULL)
vty_out(vty, "\n");
}
@@ -432,11 +440,11 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
return;
}
num_neigh = hashcount(zvni->neigh_table);
- if (json == NULL)
+ if (json == NULL) {
vty_out(vty,
"\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
zvni->vni, num_neigh);
- else {
+ } else {
json_vni = json_object_new_object();
json_object_int_add(json_vni, "numArpNd", num_neigh);
snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
@@ -458,9 +466,10 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
wctx.json = json_vni;
hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
- if (json == NULL)
+ if (json == NULL) {
vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP",
"Type", "MAC", "Remote VTEP");
+ }
hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
if (json)
@@ -581,6 +590,9 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt)
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
vty_out(vty, " Default-gateway Mac ");
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW))
+ vty_out(vty, " Remote-gateway Mac ");
+
vty_out(vty, "\n");
/* print all the associated neigh */
vty_out(vty, " Neighbors:\n");
@@ -1553,6 +1565,9 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_GW))
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
+ /* Set router flag (R-bit) based on local neigh entry add */
+ if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_ROUTER_FLAG))
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
ZEBRA_MACIP_ADD);
@@ -1576,6 +1591,8 @@ static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n)
struct zebra_if *zif;
struct zebra_l2info_vxlan *vxl;
struct interface *vlan_if;
+ uint8_t flags;
+ int ret = 0;
if (!(n->flags & ZEBRA_NEIGH_REMOTE))
return 0;
@@ -1588,8 +1605,13 @@ static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n)
vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
if (!vlan_if)
return -1;
-
- return kernel_add_neigh(vlan_if, &n->ip, &n->emac);
+#ifdef GNU_LINUX
+ flags = NTF_EXT_LEARNED;
+ if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
+ flags |= NTF_ROUTER;
+ ret = kernel_add_neigh(vlan_if, &n->ip, &n->emac, flags);
+#endif
+ return ret;
}
/*
@@ -1811,6 +1833,9 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
/* Set "local" forwarding info. */
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW);
+ /* Set Router flag (R-bit) */
+ if (ip->ipa_type == IPADDR_V6)
+ SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
memcpy(&n->emac, macaddr, ETH_ALEN);
n->ifindex = ifp->ifindex;
@@ -1820,10 +1845,10 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP",
+ "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
ifp->name, ifp->ifindex, zvni->vni,
prefix_mac2str(macaddr, buf, sizeof(buf)),
- ipaddr2str(ip, buf2, sizeof(buf2)));
+ ipaddr2str(ip, buf2, sizeof(buf2)), n->flags);
zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags);
@@ -1966,7 +1991,8 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
static int zvni_local_neigh_update(zebra_vni_t *zvni,
struct interface *ifp,
struct ipaddr *ip,
- struct ethaddr *macaddr)
+ struct ethaddr *macaddr,
+ uint8_t router_flag)
{
char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
@@ -2084,15 +2110,19 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
return 0;
}
+ /*Set router flag (R-bit) */
+ if (router_flag)
+ SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
+
/* Inform BGP. */
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u",
+ zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u with flags 0x%x",
ipaddr2str(ip, buf2, sizeof(buf2)),
prefix_mac2str(macaddr, buf, sizeof(buf)),
- zvni->vni);
+ zvni->vni, n->flags);
ZEBRA_NEIGH_SET_ACTIVE(n);
- return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, 0);
+ return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags);
}
static int zvni_remote_neigh_update(zebra_vni_t *zvni,
@@ -2534,7 +2564,8 @@ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
return -1;
vxl = &zif->l2info.vxl;
- sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
+ sticky = CHECK_FLAG(mac->flags,
+ (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW)) ? 1 : 0;
return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
mac->fwd_info.r_vtep_ip, sticky);
@@ -3362,14 +3393,22 @@ static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
*/
static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
{
+ uint8_t flags;
+ int ret = 0;
+
if (!is_l3vni_oper_up(zl3vni))
return -1;
if (!(n->flags & ZEBRA_NEIGH_REMOTE)
|| !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
return 0;
-
- return kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac);
+#ifdef GNU_LINUX
+ flags = NTF_EXT_LEARNED;
+ if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
+ flags |= NTF_ROUTER;
+ ret = kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac, flags);
+#endif
+ return ret;
}
/*
@@ -4513,9 +4552,11 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
wctx.zvni = zvni;
wctx.vty = vty;
+ wctx.addr_width = 15;
wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
wctx.r_vtep_ip = vtep_ip;
wctx.json = json;
+ hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
if (use_json) {
@@ -4944,7 +4985,8 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
struct ipaddr *ip,
struct ethaddr *macaddr,
uint16_t state,
- uint8_t ext_learned)
+ uint8_t ext_learned,
+ uint8_t router_flag)
{
char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
@@ -4975,7 +5017,8 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
/* Is this about a local neighbor or a remote one? */
if (!ext_learned)
- return zvni_local_neigh_update(zvni, ifp, ip, macaddr);
+ return zvni_local_neigh_update(zvni, ifp, ip, macaddr,
+ router_flag);
return zvni_remote_neigh_update(zvni, ifp, ip, macaddr, state);
}
@@ -5152,6 +5195,7 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
uint8_t sticky = 0;
+ u_char remote_gw = 0;
uint8_t flags = 0;
struct interface *ifp = NULL;
struct zebra_if *zif = NULL;
@@ -5193,6 +5237,7 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
/* Get flags - sticky mac and/or gateway mac */
STREAM_GETC(s, flags);
sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
+ remote_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
l++;
if (IS_ZEBRA_DEBUG_VXLAN)
@@ -5266,6 +5311,8 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
|| (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0)
!= sticky
+ || (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? 1 : 0)
+ != remote_gw
|| !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip))
update_mac = 1;
@@ -5297,6 +5344,11 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
else
UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
+ if (remote_gw)
+ SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
+ else
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
+
zvni_process_neigh_on_remote_mac_add(zvni, mac);
/* Install the entry. */
@@ -5353,6 +5405,10 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
n->r_vtep_ip = vtep_ip;
SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
+ /* Set router flag (R-bit) to this Neighbor entry */
+ if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG))
+ SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
+
/* Install the entry. */
zvni_neigh_install(zvni, n);
}
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index 34d1152751..2732ef72ed 100644
--- a/zebra/zebra_vxlan.h
+++ b/zebra/zebra_vxlan.h
@@ -124,7 +124,8 @@ extern int zebra_vxlan_svi_down(struct interface *ifp,
struct interface *link_if);
extern int zebra_vxlan_handle_kernel_neigh_update(
struct interface *ifp, struct interface *link_if, struct ipaddr *ip,
- struct ethaddr *macaddr, uint16_t state, uint8_t ext_learned);
+ struct ethaddr *macaddr, uint16_t state, uint8_t ext_learned,
+ uint8_t router_flag);
extern int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
struct interface *link_if,
struct ipaddr *ip);
diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h
index fa7075f2de..e86967041b 100644
--- a/zebra/zebra_vxlan_private.h
+++ b/zebra/zebra_vxlan_private.h
@@ -247,6 +247,8 @@ struct zebra_mac_t_ {
#define ZEBRA_MAC_STICKY 0x08 /* Static MAC */
#define ZEBRA_MAC_REMOTE_RMAC 0x10 /* remote router mac */
#define ZEBRA_MAC_DEF_GW 0x20
+/* remote VTEP advertised MAC as default GW */
+#define ZEBRA_MAC_REMOTE_DEF_GW 0x40
/* Local or remote info. */
union {
@@ -329,6 +331,7 @@ struct zebra_neigh_t_ {
#define ZEBRA_NEIGH_REMOTE 0x02
#define ZEBRA_NEIGH_REMOTE_NH 0x04 /* neigh entry for remote vtep */
#define ZEBRA_NEIGH_DEF_GW 0x08
+#define ZEBRA_NEIGH_ROUTER_FLAG 0x10
enum zebra_neigh_state state;