summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_aspath.c116
-rw-r--r--bgpd/bgp_aspath.h7
-rw-r--r--bgpd/bgp_attr.c14
-rw-r--r--bgpd/bgp_attr_evpn.c6
-rw-r--r--bgpd/bgp_attr_evpn.h2
-rw-r--r--bgpd/bgp_community.c109
-rw-r--r--bgpd/bgp_community.h6
-rw-r--r--bgpd/bgp_ecommunity.c109
-rw-r--r--bgpd/bgp_ecommunity.h10
-rw-r--r--bgpd/bgp_evpn.c19
-rw-r--r--bgpd/bgp_evpn.h3
-rw-r--r--bgpd/bgp_lcommunity.c109
-rw-r--r--bgpd/bgp_lcommunity.h10
-rw-r--r--bgpd/bgp_mac.c33
-rw-r--r--bgpd/bgp_mac.h1
-rw-r--r--bgpd/bgp_mplsvpn.c3
-rw-r--r--bgpd/bgp_open.c2
-rw-r--r--bgpd/bgp_open.h2
-rw-r--r--bgpd/bgp_route.c519
-rw-r--r--bgpd/bgp_route.h70
-rw-r--r--bgpd/bgp_vty.c2
-rw-r--r--bgpd/bgp_zebra.c58
-rw-r--r--bgpd/bgpd.c1
-rw-r--r--bgpd/bgpd.h3
-rw-r--r--bgpd/rfapi/rfapi_import.c4
-rw-r--r--eigrpd/eigrp_main.c5
-rw-r--r--eigrpd/eigrpd.c7
-rw-r--r--isisd/isis_circuit.c7
-rw-r--r--isisd/isis_circuit.h2
-rw-r--r--isisd/isis_northbound.c4
-rw-r--r--isisd/isisd.c5
-rw-r--r--lib/event_counter.c2
-rw-r--r--lib/if_rmap.c95
-rw-r--r--lib/if_rmap.h33
-rw-r--r--lib/nexthop.h1
-rw-r--r--lib/prefix.c6
-rw-r--r--lib/yang_translator.c2
-rw-r--r--ospfd/ospf_dump.c3
-rw-r--r--ospfd/ospf_vty.c23
-rw-r--r--ospfd/ospfd.c8
-rw-r--r--pimd/pim_register.c4
-rw-r--r--redhat/frr.spec.in3
-rw-r--r--ripd/ripd.c61
-rw-r--r--ripd/ripd.h6
-rw-r--r--ripngd/ripngd.c37
-rw-r--r--ripngd/ripngd.h3
-rwxr-xr-xtools/frr-reload.py19
-rw-r--r--vtysh/vtysh.c4
-rw-r--r--zebra/if_ioctl.c2
-rw-r--r--zebra/if_ioctl_solaris.c3
-rw-r--r--zebra/if_netlink.c20
-rw-r--r--zebra/ioctl.c10
-rw-r--r--zebra/ioctl_solaris.c6
-rw-r--r--zebra/rt_netlink.c7
-rw-r--r--zebra/zapi_msg.c26
-rw-r--r--zebra/zebra_rib.c17
-rw-r--r--zebra/zebra_vxlan.c25
57 files changed, 1303 insertions, 371 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 9c23f3caab..92c37fabd2 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -212,6 +212,9 @@ static struct assegment *assegment_append_asns(struct assegment *seg,
{
as_t *newas;
+ if (!seg)
+ return seg;
+
newas = XREALLOC(MTYPE_AS_SEG_DATA, seg->as,
ASSEGMENT_DATA_SIZE(seg->length + num, 1));
@@ -1370,7 +1373,8 @@ static struct aspath *aspath_merge(struct aspath *as1, struct aspath *as2)
while (last && last->next)
last = last->next;
- last->next = as2->segments;
+ if (last)
+ last->next = as2->segments;
as2->segments = new;
aspath_str_update(as2, false);
return as2;
@@ -1445,7 +1449,8 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
* bypass the merged seg2, and attach any chain after it
* to chain descending from as2's head
*/
- as2segtail->next = as2seghead->next;
+ if (as2segtail)
+ as2segtail->next = as2seghead->next;
/* as2->segments is now referenceless and useless */
assegment_free(as2seghead);
@@ -2094,3 +2099,110 @@ void aspath_print_all_vty(struct vty *vty)
void *))aspath_show_all_iterator,
vty);
}
+
+static struct aspath *bgp_aggr_aspath_lookup(struct bgp_aggregate *aggregate,
+ struct aspath *aspath)
+{
+ return hash_lookup(aggregate->aspath_hash, aspath);
+}
+
+static void *bgp_aggr_aspath_hash_alloc(void *p)
+{
+ struct aspath *ref = (struct aspath *)p;
+ struct aspath *aspath = NULL;
+
+ aspath = aspath_dup(ref);
+ return aspath;
+}
+
+static void bgp_aggr_aspath_prepare(struct hash_backet *hb, void *arg)
+{
+ struct aspath *asmerge = NULL;
+ struct aspath *hb_aspath = hb->data;
+ struct aspath **aggr_aspath = arg;
+
+ if (*aggr_aspath) {
+ asmerge = aspath_aggregate(*aggr_aspath, hb_aspath);
+ aspath_free(*aggr_aspath);
+ *aggr_aspath = asmerge;
+ } else
+ *aggr_aspath = aspath_dup(hb_aspath);
+}
+
+void bgp_aggr_aspath_remove(void *arg)
+{
+ struct aspath *aspath = arg;
+
+ aspath_free(aspath);
+}
+
+void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate,
+ struct aspath *aspath)
+{
+ struct aspath *aggr_aspath = NULL;
+
+ if ((aggregate == NULL) || (aspath == NULL))
+ return;
+
+ /* Create hash if not already created.
+ */
+ if (aggregate->aspath_hash == NULL)
+ aggregate->aspath_hash = hash_create(
+ aspath_key_make, aspath_cmp,
+ "BGP Aggregator as-path hash");
+
+ aggr_aspath = bgp_aggr_aspath_lookup(aggregate, aspath);
+ if (aggr_aspath == NULL) {
+ /* Insert as-path into hash.
+ */
+ aggr_aspath = hash_get(aggregate->aspath_hash, aspath,
+ bgp_aggr_aspath_hash_alloc);
+
+ /* Compute aggregate's as-path.
+ */
+ hash_iterate(aggregate->aspath_hash,
+ bgp_aggr_aspath_prepare,
+ &aggregate->aspath);
+ }
+
+ /* Increment refernce counter.
+ */
+ aggr_aspath->refcnt++;
+}
+
+void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate,
+ struct aspath *aspath)
+{
+ struct aspath *aggr_aspath = NULL;
+ struct aspath *ret_aspath = NULL;
+
+ if ((aggregate == NULL) || (aspath == NULL))
+ return;
+
+ if (aggregate->aspath_hash == NULL)
+ return;
+
+ /* Look-up the aspath in the hash.
+ */
+ aggr_aspath = bgp_aggr_aspath_lookup(aggregate, aspath);
+ if (aggr_aspath) {
+ aggr_aspath->refcnt--;
+
+ if (aggr_aspath->refcnt == 0) {
+ ret_aspath = hash_release(aggregate->aspath_hash,
+ aggr_aspath);
+ aspath_free(ret_aspath);
+
+ /* Remove aggregate's old as-path.
+ */
+ aspath_free(aggregate->aspath);
+ aggregate->aspath = NULL;
+
+ /* Compute aggregate's as-path.
+ */
+ hash_iterate(aggregate->aspath_hash,
+ bgp_aggr_aspath_prepare,
+ &aggregate->aspath);
+ }
+ }
+}
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index 9c9c687a6b..be5725c1ae 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -22,6 +22,7 @@
#define _QUAGGA_BGP_ASPATH_H
#include "lib/json.h"
+#include "bgpd/bgp_route.h"
/* AS path segment type. */
#define AS_SET 1
@@ -130,4 +131,10 @@ extern unsigned int aspath_has_as4(struct aspath *);
/* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */
extern uint8_t *aspath_snmp_pathseg(struct aspath *, size_t *);
+extern void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate,
+ struct aspath *aspath);
+extern void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate,
+ struct aspath *aspath);
+extern void bgp_aggr_aspath_remove(void *arg);
+
#endif /* _QUAGGA_BGP_ASPATH_H */
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index e44424e080..226bf99d2c 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -54,6 +54,7 @@
#include "bgp_encap_types.h"
#include "bgp_evpn.h"
#include "bgp_flowspec_private.h"
+#include "bgp_mac.h"
/* Attribute strings for logging. */
static const struct message attr_str[] = {
@@ -1942,7 +1943,18 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
bgp_attr_evpn_na_flag(attr, &attr->router_flag);
/* Extract the Rmac, if any */
- bgp_attr_rmac(attr, &attr->rmac);
+ if (bgp_attr_rmac(attr, &attr->rmac)) {
+ if (bgp_debug_update(peer, NULL, NULL, 1) &&
+ bgp_mac_exist(&attr->rmac)) {
+ char buf1[ETHER_ADDR_STRLEN];
+
+ zlog_debug("%s: router mac %s is self mac",
+ __func__,
+ prefix_mac2str(&attr->rmac, buf1,
+ sizeof(buf1)));
+ }
+
+ }
return BGP_ATTR_PARSE_PROCEED;
}
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
index ca04ebf550..15fa322159 100644
--- a/bgpd/bgp_attr_evpn.c
+++ b/bgpd/bgp_attr_evpn.c
@@ -106,14 +106,14 @@ char *ecom_mac2str(char *ecom_mac)
}
/* Fetch router-mac from extended community */
-void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
+bool bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
{
int i = 0;
struct ecommunity *ecom;
ecom = attr->ecommunity;
if (!ecom || !ecom->size)
- return;
+ return false;
/* If there is a router mac extended community, set RMAC in attr */
for (i = 0; i < ecom->size; i++) {
@@ -130,7 +130,9 @@ void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
continue;
memcpy(rmac, pnt, ETH_ALEN);
+ return true;
}
+ return false;
}
/*
diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h
index b036702151..5b0ce1da28 100644
--- a/bgpd/bgp_attr_evpn.h
+++ b/bgpd/bgp_attr_evpn.h
@@ -60,7 +60,7 @@ extern void bgp_add_routermac_ecom(struct attr *attr,
struct ethaddr *routermac);
extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag,
struct prefix *dst);
-extern void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac);
+extern bool bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac);
extern uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
uint8_t *sticky);
extern uint8_t bgp_attr_default_gw(struct attr *attr);
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index d3c5a8ef14..67cd2be214 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -907,3 +907,112 @@ void community_finish(void)
hash_free(comhash);
comhash = NULL;
}
+
+static struct community *bgp_aggr_community_lookup(
+ struct bgp_aggregate *aggregate,
+ struct community *community)
+{
+ return hash_lookup(aggregate->community_hash, community);
+}
+
+static void *bgp_aggr_communty_hash_alloc(void *p)
+{
+ struct community *ref = (struct community *)p;
+ struct community *community = NULL;
+
+ community = community_dup(ref);
+ return community;
+}
+
+static void bgp_aggr_community_prepare(struct hash_backet *hb, void *arg)
+{
+ struct community *commerge = NULL;
+ struct community *hb_community = hb->data;
+ struct community **aggr_community = arg;
+
+ if (*aggr_community) {
+ commerge = community_merge(*aggr_community, hb_community);
+ *aggr_community = community_uniq_sort(commerge);
+ community_free(&commerge);
+ } else
+ *aggr_community = community_dup(hb_community);
+}
+
+void bgp_aggr_community_remove(void *arg)
+{
+ struct community *community = arg;
+
+ community_free(&community);
+}
+
+void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate,
+ struct community *community)
+{
+ struct community *aggr_community = NULL;
+
+ if ((aggregate == NULL) || (community == NULL))
+ return;
+
+ /* Create hash if not already created.
+ */
+ if (aggregate->community_hash == NULL)
+ aggregate->community_hash = hash_create(
+ (unsigned int (*)(void *))community_hash_make,
+ (bool (*)(const void *, const void *))community_cmp,
+ "BGP Aggregator community hash");
+
+ aggr_community = bgp_aggr_community_lookup(aggregate, community);
+ if (aggr_community == NULL) {
+ /* Insert community into hash.
+ */
+ aggr_community = hash_get(aggregate->community_hash, community,
+ bgp_aggr_communty_hash_alloc);
+
+ /* Re-compute aggregate's community.
+ */
+ if (aggregate->community)
+ community_free(&aggregate->community);
+
+ hash_iterate(aggregate->community_hash,
+ bgp_aggr_community_prepare,
+ &aggregate->community);
+ }
+
+ /* Increment refernce counter.
+ */
+ aggr_community->refcnt++;
+}
+
+void bgp_remove_community_from_aggregate(struct bgp_aggregate *aggregate,
+ struct community *community)
+{
+ struct community *aggr_community = NULL;
+ struct community *ret_comm = NULL;
+
+ if ((aggregate == NULL) || (community == NULL))
+ return;
+
+ if (aggregate->community_hash == NULL)
+ return;
+
+ /* Look-up the community in the hash.
+ */
+ aggr_community = bgp_aggr_community_lookup(aggregate, community);
+ if (aggr_community) {
+ aggr_community->refcnt--;
+
+ if (aggr_community->refcnt == 0) {
+ ret_comm = hash_release(aggregate->community_hash,
+ aggr_community);
+ community_free(&ret_comm);
+
+ community_free(&aggregate->community);
+
+ /* Compute aggregate's community.
+ */
+ hash_iterate(aggregate->community_hash,
+ bgp_aggr_community_prepare,
+ &aggregate->community);
+ }
+ }
+}
diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h
index e1545249d7..4ff4d214a5 100644
--- a/bgpd/bgp_community.h
+++ b/bgpd/bgp_community.h
@@ -22,6 +22,7 @@
#define _QUAGGA_BGP_COMMUNITY_H
#include "lib/json.h"
+#include "bgpd/bgp_route.h"
/* Communities attribute. */
struct community {
@@ -89,5 +90,10 @@ extern void community_del_val(struct community *, uint32_t *);
extern unsigned long community_count(void);
extern struct hash *community_hash(void);
extern uint32_t community_val_get(struct community *com, int i);
+extern void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate,
+ struct community *community);
+extern void bgp_remove_community_from_aggregate(struct bgp_aggregate *aggregate,
+ struct community *community);
+extern void bgp_aggr_community_remove(void *arg);
#endif /* _QUAGGA_BGP_COMMUNITY_H */
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 2a8d27ba24..8ef398952d 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -1023,3 +1023,112 @@ int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
return -1;
return 0;
}
+
+static struct ecommunity *bgp_aggr_ecommunity_lookup(
+ struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity)
+{
+ return hash_lookup(aggregate->ecommunity_hash, ecommunity);
+}
+
+static void *bgp_aggr_ecommunty_hash_alloc(void *p)
+{
+ struct ecommunity *ref = (struct ecommunity *)p;
+ struct ecommunity *ecommunity = NULL;
+
+ ecommunity = ecommunity_dup(ref);
+ return ecommunity;
+}
+
+static void bgp_aggr_ecommunity_prepare(struct hash_backet *hb, void *arg)
+{
+ struct ecommunity *ecommerge = NULL;
+ struct ecommunity *hb_ecommunity = hb->data;
+ struct ecommunity **aggr_ecommunity = arg;
+
+ if (*aggr_ecommunity) {
+ ecommerge = ecommunity_merge(*aggr_ecommunity, hb_ecommunity);
+ *aggr_ecommunity = ecommunity_uniq_sort(ecommerge);
+ ecommunity_free(&ecommerge);
+ } else
+ *aggr_ecommunity = ecommunity_dup(hb_ecommunity);
+}
+
+void bgp_aggr_ecommunity_remove(void *arg)
+{
+ struct ecommunity *ecommunity = arg;
+
+ ecommunity_free(&ecommunity);
+}
+
+void bgp_compute_aggregate_ecommunity(struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity)
+{
+ struct ecommunity *aggr_ecommunity = NULL;
+
+ if ((aggregate == NULL) || (ecommunity == NULL))
+ return;
+
+ /* Create hash if not already created.
+ */
+ if (aggregate->ecommunity_hash == NULL)
+ aggregate->ecommunity_hash = hash_create(
+ ecommunity_hash_make, ecommunity_cmp,
+ "BGP Aggregator ecommunity hash");
+
+ aggr_ecommunity = bgp_aggr_ecommunity_lookup(aggregate, ecommunity);
+ if (aggr_ecommunity == NULL) {
+ /* Insert ecommunity into hash.
+ */
+ aggr_ecommunity = hash_get(aggregate->ecommunity_hash,
+ ecommunity,
+ bgp_aggr_ecommunty_hash_alloc);
+
+ /* Re-compute aggregate's ecommunity.
+ */
+ if (aggregate->ecommunity)
+ ecommunity_free(&aggregate->ecommunity);
+
+ hash_iterate(aggregate->ecommunity_hash,
+ bgp_aggr_ecommunity_prepare,
+ &aggregate->ecommunity);
+ }
+
+ /* Increment refernce counter.
+ */
+ aggr_ecommunity->refcnt++;
+}
+
+void bgp_remove_ecommunity_from_aggregate(struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity)
+{
+ struct ecommunity *aggr_ecommunity = NULL;
+ struct ecommunity *ret_ecomm = NULL;
+
+ if ((aggregate == NULL) || (ecommunity == NULL))
+ return;
+
+ if (aggregate->ecommunity_hash == NULL)
+ return;
+
+ /* Look-up the ecommunity in the hash.
+ */
+ aggr_ecommunity = bgp_aggr_ecommunity_lookup(aggregate, ecommunity);
+ if (aggr_ecommunity) {
+ aggr_ecommunity->refcnt--;
+
+ if (aggr_ecommunity->refcnt == 0) {
+ ret_ecomm = hash_release(aggregate->ecommunity_hash,
+ aggr_ecommunity);
+ ecommunity_free(&ret_ecomm);
+
+ ecommunity_free(&aggregate->ecommunity);
+
+ /* Compute aggregate's ecommunity.
+ */
+ hash_iterate(aggregate->ecommunity_hash,
+ bgp_aggr_ecommunity_prepare,
+ &aggregate->ecommunity);
+ }
+ }
+}
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index 519991da5a..62b2137753 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -21,6 +21,8 @@
#ifndef _QUAGGA_BGP_ECOMMUNITY_H
#define _QUAGGA_BGP_ECOMMUNITY_H
+#include "bgpd/bgp_route.h"
+
/* High-order octet of the Extended Communities type field. */
#define ECOMMUNITY_ENCODE_AS 0x00
#define ECOMMUNITY_ENCODE_IP 0x01
@@ -184,4 +186,12 @@ struct bgp_pbr_entry_action;
extern int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
struct bgp_pbr_entry_action *api);
+extern void bgp_compute_aggregate_ecommunity(
+ struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity);
+extern void bgp_remove_ecommunity_from_aggregate(
+ struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity);
+extern void bgp_aggr_ecommunity_remove(void *arg);
+
#endif /* _QUAGGA_BGP_ECOMMUNITY_H */
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 214aaeac5b..84f3649758 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -3929,7 +3929,7 @@ static int process_type4_route(struct peer *peer, afi_t afi, safi_t safi,
*/
static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
struct attr *attr, uint8_t *pfx, int psize,
- uint32_t addpath_id, int withdraw)
+ uint32_t addpath_id)
{
struct prefix_rd prd;
struct prefix_evpn p;
@@ -4015,7 +4015,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
*/
/* Process the route. */
- if (!withdraw)
+ if (attr)
ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
&prd, &label, 1, 0, &evpn);
@@ -4867,8 +4867,9 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
break;
case BGP_EVPN_IP_PREFIX_ROUTE:
- if (process_type5_route(peer, afi, safi, attr, pnt,
- psize, addpath_id, withdraw)) {
+ if (process_type5_route(peer, afi, safi,
+ withdraw ? NULL : attr, pnt,
+ psize, addpath_id)) {
flog_err(
EC_BGP_PKT_PROCESS,
"%u:%s - Error in processing EVPN type-5 NLRI size %d",
@@ -5386,7 +5387,8 @@ static void link_l2vni_hash_to_l3vni(struct hash_bucket *bucket,
}
int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac,
- struct in_addr originator_ip, int filter)
+ struct in_addr originator_ip, int filter,
+ ifindex_t svi_ifindex)
{
struct bgp *bgp_vrf = NULL; /* bgp VRF instance */
struct bgp *bgp_def = NULL; /* default bgp instance */
@@ -5434,14 +5436,11 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac,
SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_AUTO);
}
- /* associate with l3vni */
+ /* associate the vrf with l3vni and related parameters */
bgp_vrf->l3vni = l3vni;
-
- /* set the router mac - to be used in mac-ip routes for this vrf */
memcpy(&bgp_vrf->rmac, rmac, sizeof(struct ethaddr));
-
- /* set the originator ip */
bgp_vrf->originator_ip = originator_ip;
+ bgp_vrf->l3vni_svi_ifindex = svi_ifindex;
/* set the right filter - are we using l3vni only for prefix routes? */
if (filter)
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index 5c3d4ce3aa..fbf30083e1 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -136,7 +136,8 @@ extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
uint8_t flags, uint32_t seq);
extern int bgp_evpn_local_l3vni_add(vni_t vni, vrf_id_t vrf_id,
struct ethaddr *rmac,
- struct in_addr originator_ip, int filter);
+ struct in_addr originator_ip, int filter,
+ ifindex_t svi_ifindex);
extern int bgp_evpn_local_l3vni_del(vni_t vni, vrf_id_t vrf_id);
extern int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni);
extern int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c
index edc364ec27..44766c9b6e 100644
--- a/bgpd/bgp_lcommunity.c
+++ b/bgpd/bgp_lcommunity.c
@@ -534,3 +534,112 @@ void lcommunity_del_val(struct lcommunity *lcom, uint8_t *ptr)
i++;
}
}
+
+static struct lcommunity *bgp_aggr_lcommunity_lookup(
+ struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity)
+{
+ return hash_lookup(aggregate->lcommunity_hash, lcommunity);
+}
+
+static void *bgp_aggr_lcommunty_hash_alloc(void *p)
+{
+ struct lcommunity *ref = (struct lcommunity *)p;
+ struct lcommunity *lcommunity = NULL;
+
+ lcommunity = lcommunity_dup(ref);
+ return lcommunity;
+}
+
+static void bgp_aggr_lcommunity_prepare(struct hash_backet *hb, void *arg)
+{
+ struct lcommunity *lcommerge = NULL;
+ struct lcommunity *hb_lcommunity = hb->data;
+ struct lcommunity **aggr_lcommunity = arg;
+
+ if (*aggr_lcommunity) {
+ lcommerge = lcommunity_merge(*aggr_lcommunity, hb_lcommunity);
+ *aggr_lcommunity = lcommunity_uniq_sort(lcommerge);
+ lcommunity_free(&lcommerge);
+ } else
+ *aggr_lcommunity = lcommunity_dup(hb_lcommunity);
+}
+
+void bgp_aggr_lcommunity_remove(void *arg)
+{
+ struct lcommunity *lcommunity = arg;
+
+ lcommunity_free(&lcommunity);
+}
+
+void bgp_compute_aggregate_lcommunity(struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity)
+{
+ struct lcommunity *aggr_lcommunity = NULL;
+
+ if ((aggregate == NULL) || (lcommunity == NULL))
+ return;
+
+ /* Create hash if not already created.
+ */
+ if (aggregate->lcommunity_hash == NULL)
+ aggregate->lcommunity_hash = hash_create(
+ lcommunity_hash_make, lcommunity_cmp,
+ "BGP Aggregator lcommunity hash");
+
+ aggr_lcommunity = bgp_aggr_lcommunity_lookup(aggregate, lcommunity);
+ if (aggr_lcommunity == NULL) {
+ /* Insert lcommunity into hash.
+ */
+ aggr_lcommunity = hash_get(aggregate->lcommunity_hash,
+ lcommunity,
+ bgp_aggr_lcommunty_hash_alloc);
+
+ /* Re-compute aggregate's lcommunity.
+ */
+ if (aggregate->lcommunity)
+ lcommunity_free(&aggregate->lcommunity);
+
+ hash_iterate(aggregate->lcommunity_hash,
+ bgp_aggr_lcommunity_prepare,
+ &aggregate->lcommunity);
+ }
+
+ /* Increment refernce counter.
+ */
+ aggr_lcommunity->refcnt++;
+}
+
+void bgp_remove_lcommunity_from_aggregate(struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity)
+{
+ struct lcommunity *aggr_lcommunity = NULL;
+ struct lcommunity *ret_lcomm = NULL;
+
+ if ((aggregate == NULL) || (lcommunity == NULL))
+ return;
+
+ if (aggregate->lcommunity_hash == NULL)
+ return;
+
+ /* Look-up the lcommunity in the hash.
+ */
+ aggr_lcommunity = bgp_aggr_lcommunity_lookup(aggregate, lcommunity);
+ if (aggr_lcommunity) {
+ aggr_lcommunity->refcnt--;
+
+ if (aggr_lcommunity->refcnt == 0) {
+ ret_lcomm = hash_release(aggregate->lcommunity_hash,
+ aggr_lcommunity);
+ lcommunity_free(&ret_lcomm);
+
+ lcommunity_free(&aggregate->lcommunity);
+
+ /* Compute aggregate's lcommunity.
+ */
+ hash_iterate(aggregate->lcommunity_hash,
+ bgp_aggr_lcommunity_prepare,
+ &aggregate->lcommunity);
+ }
+ }
+}
diff --git a/bgpd/bgp_lcommunity.h b/bgpd/bgp_lcommunity.h
index 23c777d9fd..aa4e8c69fe 100644
--- a/bgpd/bgp_lcommunity.h
+++ b/bgpd/bgp_lcommunity.h
@@ -22,6 +22,7 @@
#define _QUAGGA_BGP_LCOMMUNITY_H
#include "lib/json.h"
+#include "bgpd/bgp_route.h"
/* Large Communities value is twelve octets long. */
#define LCOMMUNITY_SIZE 12
@@ -70,4 +71,13 @@ extern int lcommunity_match(const struct lcommunity *,
extern char *lcommunity_str(struct lcommunity *, bool make_json);
extern int lcommunity_include(struct lcommunity *lcom, uint8_t *ptr);
extern void lcommunity_del_val(struct lcommunity *lcom, uint8_t *ptr);
+
+extern void bgp_compute_aggregate_lcommunity(
+ struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity);
+extern void bgp_remove_lcommunity_from_aggregate(
+ struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity);
+extern void bgp_aggr_lcommunity_remove(void *arg);
+
#endif /* _QUAGGA_BGP_LCOMMUNITY_H */
diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c
index 4a408df858..49b5854020 100644
--- a/bgpd/bgp_mac.c
+++ b/bgpd/bgp_mac.c
@@ -311,11 +311,35 @@ void bgp_mac_del_mac_entry(struct interface *ifp)
bgp_mac_remove_ifp_internal(bsm, ifp->name);
}
-bool bgp_mac_entry_exists(struct prefix *p)
+/* This API checks MAC address against any of local
+ * assigned (SVIs) MAC address.
+ * An example: router-mac attribute in any of evpn update
+ * requires to compare against local mac.
+ */
+bool bgp_mac_exist(struct ethaddr *mac)
{
- struct prefix_evpn *pevpn = (struct prefix_evpn *)p;
struct bgp_self_mac lookup;
struct bgp_self_mac *bsm;
+ static uint8_t tmp [ETHER_ADDR_STRLEN] = {0};
+
+ if (memcmp(mac, &tmp, ETH_ALEN) == 0)
+ return false;
+
+ memcpy(&lookup.macaddr, mac, ETH_ALEN);
+ bsm = hash_lookup(bm->self_mac_hash, &lookup);
+ if (!bsm)
+ return false;
+
+ return true;
+}
+
+/* This API checks EVPN type-2 prefix and comapares
+ * mac against any of local assigned (SVIs) MAC
+ * address.
+ */
+bool bgp_mac_entry_exists(struct prefix *p)
+{
+ struct prefix_evpn *pevpn = (struct prefix_evpn *)p;
if (pevpn->family != AF_EVPN)
return false;
@@ -323,10 +347,7 @@ bool bgp_mac_entry_exists(struct prefix *p)
if (pevpn->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
return false;
- memcpy(&lookup.macaddr, &p->u.prefix_evpn.macip_addr.mac, ETH_ALEN);
- bsm = hash_lookup(bm->self_mac_hash, &lookup);
- if (!bsm)
- return false;
+ return bgp_mac_exist(&p->u.prefix_evpn.macip_addr.mac);
return true;
}
diff --git a/bgpd/bgp_mac.h b/bgpd/bgp_mac.h
index 1dd987ef12..68449b574a 100644
--- a/bgpd/bgp_mac.h
+++ b/bgpd/bgp_mac.h
@@ -37,5 +37,6 @@ void bgp_mac_dump_table(struct vty *vty);
* Function to lookup the prefix and see if we have a matching mac
*/
bool bgp_mac_entry_exists(struct prefix *p);
+bool bgp_mac_exist(struct ethaddr *mac);
#endif
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 4baac3e57a..765170d1a5 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -1092,8 +1092,6 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
*/
uint8_t nhfamily = NEXTHOP_FAMILY(path_vpn->attr->mp_nexthop_len);
- if (nhfamily != AF_UNSPEC)
- static_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
memset(&nexthop_orig, 0, sizeof(nexthop_orig));
nexthop_orig.family = nhfamily;
@@ -1113,6 +1111,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
static_attr.mp_nexthop_len =
path_vpn->attr->mp_nexthop_len;
}
+ static_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
break;
case AF_INET6:
/* save */
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 3018124f45..7af5827d00 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -49,7 +49,7 @@
So there is many configurable point. First of all we want set each
peer whether we send capability negotiation to the peer or not.
- Next, if we send capability to the peer we want to set my capabilty
+ Next, if we send capability to the peer we want to set my capability
inforation at each peer. */
void bgp_capability_vty_out(struct vty *vty, struct peer *peer, bool use_json,
diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h
index 0fc321bdf3..8359f59a41 100644
--- a/bgpd/bgp_open.h
+++ b/bgpd/bgp_open.h
@@ -49,7 +49,7 @@ struct graceful_restart_af {
#define CAPABILITY_CODE_DYNAMIC_OLD 66 /* Dynamic Capability, deprecated since 2003 */
#define CAPABILITY_CODE_DYNAMIC 67 /* Dynamic Capability */
#define CAPABILITY_CODE_ADDPATH 69 /* Addpath Capability */
-#define CAPABILITY_CODE_FQDN 73 /* Advertise hostname capabilty */
+#define CAPABILITY_CODE_FQDN 73 /* Advertise hostname capability */
#define CAPABILITY_CODE_ENHE 5 /* Extended Next Hop Encoding */
#define CAPABILITY_CODE_REFRESH_OLD 128 /* Route Refresh Capability(cisco) */
#define CAPABILITY_CODE_ORF_OLD 130 /* Cooperative Route Filtering Capability(cisco) */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 38047f97ac..90a8f8cec5 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2490,6 +2490,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
bgp_evpn_advertise_type5_route(
bgp, &rn->p, new_select->attr,
afi, safi);
+ else
+ bgp_evpn_withdraw_type5_route(
+ bgp, &rn->p, afi, safi);
} else {
bgp_evpn_advertise_type5_route(bgp,
&rn->p,
@@ -3091,7 +3094,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
goto filtered;
}
- if (bgp_mac_entry_exists(p)) {
+ if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
reason = "self mac;";
goto filtered;
}
@@ -3280,7 +3283,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
extra = bgp_path_info_extra_get(pi);
if (extra->label != label) {
memcpy(&extra->label, label,
- num_labels * sizeof(mpls_label_t));
+ num_labels * sizeof(mpls_label_t));
extra->num_labels = num_labels;
}
if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
@@ -3452,7 +3455,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
if (has_valid_label) {
extra = bgp_path_info_extra_get(new);
if (extra->label != label) {
- memcpy(&extra->label, label, num_labels * sizeof(mpls_label_t));
+ memcpy(&extra->label, label,
+ num_labels * sizeof(mpls_label_t));
extra->num_labels = num_labels;
}
if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
@@ -5570,33 +5574,6 @@ DEFPY(ipv6_bgp_network,
label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
}
-/* Aggreagete address:
-
- advertise-map Set condition to advertise attribute
- as-set Generate AS set path information
- attribute-map Set attributes of aggregate
- route-map Set parameters of aggregate
- summary-only Filter more specific routes from updates
- suppress-map Conditionally filter more specific routes from updates
- <cr>
- */
-struct bgp_aggregate {
- /* Summary-only flag. */
- uint8_t summary_only;
-
- /* AS set generation. */
- uint8_t as_set;
-
- /* Route-map for aggregated route. */
- struct route_map *map;
-
- /* Suppress-count. */
- unsigned long count;
-
- /* SAFI configuration. */
- safi_t safi;
-};
-
static struct bgp_aggregate *bgp_aggregate_new(void)
{
return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
@@ -5722,8 +5699,7 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
/* Update an aggregate as routes are added/removed from the BGP table */
static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
- struct bgp_path_info *pinew, afi_t afi,
- safi_t safi, struct bgp_path_info *del,
+ afi_t afi, safi_t safi,
struct bgp_aggregate *aggregate)
{
struct bgp_table *table;
@@ -5731,13 +5707,9 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
struct bgp_node *rn;
uint8_t origin;
struct aspath *aspath = NULL;
- struct aspath *asmerge = NULL;
struct community *community = NULL;
- struct community *commerge = NULL;
struct ecommunity *ecommunity = NULL;
- struct ecommunity *ecommerge = NULL;
struct lcommunity *lcommunity = NULL;
- struct lcommunity *lcommerge = NULL;
struct bgp_path_info *pi;
unsigned long match = 0;
uint8_t atomic_aggregate = 0;
@@ -5766,9 +5738,6 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
if (BGP_PATH_HOLDDOWN(pi))
continue;
- if (del && pi == del)
- continue;
-
if (pi->attr->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
atomic_aggregate = 1;
@@ -5799,8 +5768,18 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
* route MUST have the ORIGIN attribute with the value
* EGP.
*/
- if (origin < pi->attr->origin)
- origin = pi->attr->origin;
+ switch (pi->attr->origin) {
+ case BGP_ORIGIN_INCOMPLETE:
+ aggregate->incomplete_origin_count++;
+ break;
+ case BGP_ORIGIN_EGP:
+ aggregate->egp_origin_count++;
+ break;
+ default:
+ /*Do nothing.
+ */
+ break;
+ }
if (!aggregate->as_set)
continue;
@@ -5809,130 +5788,68 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
* as-set aggregate route generate origin, as path,
* and community aggregation.
*/
- if (aspath) {
- asmerge = aspath_aggregate(aspath,
- pi->attr->aspath);
- aspath_free(aspath);
- aspath = asmerge;
- } else
- aspath = aspath_dup(pi->attr->aspath);
-
- if (pi->attr->community) {
- if (community) {
- commerge = community_merge(
- community, pi->attr->community);
- community =
- community_uniq_sort(commerge);
- community_free(&commerge);
- } else
- community = community_dup(
- pi->attr->community);
- }
-
- if (pi->attr->ecommunity) {
- if (ecommunity) {
- ecommerge = ecommunity_merge(
- ecommunity,
- pi->attr->ecommunity);
- ecommunity =
- ecommunity_uniq_sort(ecommerge);
- ecommunity_free(&ecommerge);
- } else
- ecommunity = ecommunity_dup(
- pi->attr->ecommunity);
- }
-
- if (pi->attr->lcommunity) {
- if (lcommunity) {
- lcommerge = lcommunity_merge(
- lcommunity,
- pi->attr->lcommunity);
- lcommunity =
- lcommunity_uniq_sort(lcommerge);
- lcommunity_free(&lcommerge);
- } else
- lcommunity = lcommunity_dup(
- pi->attr->lcommunity);
- }
+ /* Compute aggregate route's as-path.
+ */
+ bgp_compute_aggregate_aspath(aggregate,
+ pi->attr->aspath);
+
+ /* Compute aggregate route's community.
+ */
+ if (pi->attr->community)
+ bgp_compute_aggregate_community(
+ aggregate,
+ pi->attr->community);
+
+ /* Compute aggregate route's extended community.
+ */
+ if (pi->attr->ecommunity)
+ bgp_compute_aggregate_ecommunity(
+ aggregate,
+ pi->attr->ecommunity);
+
+ /* Compute aggregate route's large community.
+ */
+ if (pi->attr->lcommunity)
+ bgp_compute_aggregate_lcommunity(
+ aggregate,
+ pi->attr->lcommunity);
}
if (match)
bgp_process(bgp, rn, afi, safi);
}
bgp_unlock_node(top);
- if (pinew) {
- aggregate->count++;
- if (aggregate->summary_only)
- (bgp_path_info_extra_get(pinew))->suppress++;
+ if (aggregate->incomplete_origin_count > 0)
+ origin = BGP_ORIGIN_INCOMPLETE;
+ else if (aggregate->egp_origin_count > 0)
+ origin = BGP_ORIGIN_EGP;
- if (origin < pinew->attr->origin)
- origin = pinew->attr->origin;
+ if (aggregate->as_set) {
+ if (aggregate->aspath)
+ /* Retrieve aggregate route's as-path.
+ */
+ aspath = aspath_dup(aggregate->aspath);
- if (aggregate->as_set) {
- if (aspath) {
- asmerge = aspath_aggregate(aspath,
- pinew->attr->aspath);
- aspath_free(aspath);
- aspath = asmerge;
- } else
- aspath = aspath_dup(pinew->attr->aspath);
+ if (aggregate->community)
+ /* Retrieve aggregate route's community.
+ */
+ community = community_dup(aggregate->community);
- if (pinew->attr->community) {
- if (community) {
- commerge = community_merge(
- community,
- pinew->attr->community);
- community =
- community_uniq_sort(commerge);
- community_free(&commerge);
- } else
- community = community_dup(
- pinew->attr->community);
- }
+ if (aggregate->ecommunity)
+ /* Retrieve aggregate route's ecommunity.
+ */
+ ecommunity = ecommunity_dup(aggregate->ecommunity);
- if (pinew->attr->ecommunity) {
- if (ecommunity) {
- ecommerge = ecommunity_merge(
- ecommunity,
- pinew->attr->ecommunity);
- ecommunity =
- ecommunity_uniq_sort(ecommerge);
- ecommunity_free(&ecommerge);
- } else
- ecommunity = ecommunity_dup(
- pinew->attr->ecommunity);
- }
-
- if (pinew->attr->lcommunity) {
- if (lcommunity) {
- lcommerge = lcommunity_merge(
- lcommunity,
- pinew->attr->lcommunity);
- lcommunity =
- lcommunity_uniq_sort(lcommerge);
- lcommunity_free(&lcommerge);
- } else
- lcommunity = lcommunity_dup(
- pinew->attr->lcommunity);
- }
- }
+ if (aggregate->lcommunity)
+ /* Retrieve aggregate route's lcommunity.
+ */
+ lcommunity = lcommunity_dup(aggregate->lcommunity);
}
bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
ecommunity, lcommunity, atomic_aggregate,
aggregate);
-
- if (aggregate->count == 0) {
- if (aspath)
- aspath_free(aspath);
- if (community)
- community_free(&community);
- if (ecommunity)
- ecommunity_free(&ecommunity);
- if (lcommunity)
- lcommunity_free(&lcommunity);
- }
}
static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
@@ -5971,6 +5888,41 @@ static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
}
}
aggregate->count--;
+
+ if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
+ aggregate->incomplete_origin_count--;
+ else if (pi->attr->origin == BGP_ORIGIN_EGP)
+ aggregate->egp_origin_count--;
+
+ if (aggregate->as_set) {
+ /* Remove as-path from aggregate.
+ */
+ bgp_remove_aspath_from_aggregate(
+ aggregate,
+ pi->attr->aspath);
+
+ if (pi->attr->community)
+ /* Remove community from aggregate.
+ */
+ bgp_remove_community_from_aggregate(
+ aggregate,
+ pi->attr->community);
+
+ if (pi->attr->ecommunity)
+ /* Remove ecommunity from aggregate.
+ */
+ bgp_remove_ecommunity_from_aggregate(
+ aggregate,
+ pi->attr->ecommunity);
+
+ if (pi->attr->lcommunity)
+ /* Remove lcommunity from aggregate.
+ */
+ bgp_remove_lcommunity_from_aggregate(
+ aggregate,
+ pi->attr->lcommunity);
+ }
+
}
/* If this node was suppressed, process the change. */
@@ -5980,6 +5932,210 @@ static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
bgp_unlock_node(top);
}
+static void bgp_add_route_to_aggregate(struct bgp *bgp, struct prefix *aggr_p,
+ struct bgp_path_info *pinew, afi_t afi,
+ safi_t safi,
+ struct bgp_aggregate *aggregate)
+{
+ uint8_t origin;
+ struct aspath *aspath = NULL;
+ uint8_t atomic_aggregate = 0;
+ struct community *community = NULL;
+ struct ecommunity *ecommunity = NULL;
+ struct lcommunity *lcommunity = NULL;
+
+ /* ORIGIN attribute: If at least one route among routes that are
+ * aggregated has ORIGIN with the value INCOMPLETE, then the
+ * aggregated route must have the ORIGIN attribute with the value
+ * INCOMPLETE. Otherwise, if at least one route among routes that
+ * are aggregated has ORIGIN with the value EGP, then the aggregated
+ * route must have the origin attribute with the value EGP. In all
+ * other case the value of the ORIGIN attribute of the aggregated
+ * route is INTERNAL.
+ */
+ origin = BGP_ORIGIN_IGP;
+
+ aggregate->count++;
+
+ if (aggregate->summary_only)
+ (bgp_path_info_extra_get(pinew))->suppress++;
+
+ switch (pinew->attr->origin) {
+ case BGP_ORIGIN_INCOMPLETE:
+ aggregate->incomplete_origin_count++;
+ break;
+ case BGP_ORIGIN_EGP:
+ aggregate->egp_origin_count++;
+ break;
+ default:
+ /* Do nothing.
+ */
+ break;
+ }
+
+ if (aggregate->incomplete_origin_count > 0)
+ origin = BGP_ORIGIN_INCOMPLETE;
+ else if (aggregate->egp_origin_count > 0)
+ origin = BGP_ORIGIN_EGP;
+
+ if (aggregate->as_set) {
+ /* Compute aggregate route's as-path.
+ */
+ bgp_compute_aggregate_aspath(aggregate,
+ pinew->attr->aspath);
+
+ /* Compute aggregate route's community.
+ */
+ if (pinew->attr->community)
+ bgp_compute_aggregate_community(
+ aggregate,
+ pinew->attr->community);
+
+ /* Compute aggregate route's extended community.
+ */
+ if (pinew->attr->ecommunity)
+ bgp_compute_aggregate_ecommunity(
+ aggregate,
+ pinew->attr->ecommunity);
+
+ /* Compute aggregate route's large community.
+ */
+ if (pinew->attr->lcommunity)
+ bgp_compute_aggregate_lcommunity(
+ aggregate,
+ pinew->attr->lcommunity);
+
+ /* Retrieve aggregate route's as-path.
+ */
+ if (aggregate->aspath)
+ aspath = aspath_dup(aggregate->aspath);
+
+ /* Retrieve aggregate route's community.
+ */
+ if (aggregate->community)
+ community = community_dup(aggregate->community);
+
+ /* Retrieve aggregate route's ecommunity.
+ */
+ if (aggregate->ecommunity)
+ ecommunity = ecommunity_dup(aggregate->ecommunity);
+
+ /* Retrieve aggregate route's lcommunity.
+ */
+ if (aggregate->lcommunity)
+ lcommunity = lcommunity_dup(aggregate->lcommunity);
+ }
+
+ bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
+ aspath, community, ecommunity,
+ lcommunity, atomic_aggregate, aggregate);
+}
+
+static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
+ safi_t safi,
+ struct bgp_path_info *pi,
+ struct bgp_aggregate *aggregate,
+ struct prefix *aggr_p)
+{
+ uint8_t origin;
+ struct aspath *aspath = NULL;
+ uint8_t atomic_aggregate = 0;
+ struct community *community = NULL;
+ struct ecommunity *ecommunity = NULL;
+ struct lcommunity *lcommunity = NULL;
+ unsigned long match = 0;
+
+ if (BGP_PATH_HOLDDOWN(pi))
+ return;
+
+ if (pi->sub_type == BGP_ROUTE_AGGREGATE)
+ return;
+
+ if (aggregate->summary_only
+ && pi->extra
+ && pi->extra->suppress > 0) {
+ pi->extra->suppress--;
+
+ if (pi->extra->suppress == 0) {
+ bgp_path_info_set_flag(pi->net, pi,
+ BGP_PATH_ATTR_CHANGED);
+ match++;
+ }
+ }
+
+ if (aggregate->count > 0)
+ aggregate->count--;
+
+ if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
+ aggregate->incomplete_origin_count--;
+ else if (pi->attr->origin == BGP_ORIGIN_EGP)
+ aggregate->egp_origin_count--;
+
+ if (aggregate->as_set) {
+ /* Remove as-path from aggregate.
+ */
+ bgp_remove_aspath_from_aggregate(aggregate,
+ pi->attr->aspath);
+
+ if (pi->attr->community)
+ /* Remove community from aggregate.
+ */
+ bgp_remove_community_from_aggregate(
+ aggregate,
+ pi->attr->community);
+
+ if (pi->attr->ecommunity)
+ /* Remove ecommunity from aggregate.
+ */
+ bgp_remove_ecommunity_from_aggregate(
+ aggregate,
+ pi->attr->ecommunity);
+
+ if (pi->attr->lcommunity)
+ /* Remove lcommunity from aggregate.
+ */
+ bgp_remove_lcommunity_from_aggregate(
+ aggregate,
+ pi->attr->lcommunity);
+ }
+
+ /* If this node was suppressed, process the change. */
+ if (match)
+ bgp_process(bgp, pi->net, afi, safi);
+
+ origin = BGP_ORIGIN_IGP;
+ if (aggregate->incomplete_origin_count > 0)
+ origin = BGP_ORIGIN_INCOMPLETE;
+ else if (aggregate->egp_origin_count > 0)
+ origin = BGP_ORIGIN_EGP;
+
+ if (aggregate->as_set) {
+ /* Retrieve aggregate route's as-path.
+ */
+ if (aggregate->aspath)
+ aspath = aspath_dup(aggregate->aspath);
+
+ /* Retrieve aggregate route's community.
+ */
+ if (aggregate->community)
+ community = community_dup(aggregate->community);
+
+ /* Retrieve aggregate route's ecommunity.
+ */
+ if (aggregate->ecommunity)
+ ecommunity = ecommunity_dup(aggregate->ecommunity);
+
+ /* Retrieve aggregate route's lcommunity.
+ */
+ if (aggregate->lcommunity)
+ lcommunity = lcommunity_dup(aggregate->lcommunity);
+ }
+
+ bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
+ aspath, community, ecommunity,
+ lcommunity, atomic_aggregate, aggregate);
+}
+
void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
struct bgp_path_info *pi, afi_t afi, safi_t safi)
{
@@ -6006,9 +6162,8 @@ void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
aggregate = bgp_node_get_bgp_aggregate_info(rn);
if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
- bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
- bgp_aggregate_route(bgp, &rn->p, pi, afi, safi, NULL,
- aggregate);
+ bgp_add_route_to_aggregate(bgp, &rn->p, pi, afi,
+ safi, aggregate);
}
}
bgp_unlock_node(child);
@@ -6037,9 +6192,8 @@ void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
aggregate = bgp_node_get_bgp_aggregate_info(rn);
if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
- bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
- bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del,
- aggregate);
+ bgp_remove_route_from_aggregate(bgp, afi, safi,
+ del, aggregate, &rn->p);
}
}
bgp_unlock_node(child);
@@ -6081,6 +6235,59 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
/* Unlock aggregate address configuration. */
bgp_node_set_bgp_aggregate_info(rn, NULL);
+
+ if (aggregate->community)
+ community_free(&aggregate->community);
+
+ if (aggregate->community_hash) {
+ /* Delete all communities in the hash.
+ */
+ hash_clean(aggregate->community_hash,
+ bgp_aggr_community_remove);
+ /* Free up the community_hash.
+ */
+ hash_free(aggregate->community_hash);
+ }
+
+ if (aggregate->ecommunity)
+ ecommunity_free(&aggregate->ecommunity);
+
+ if (aggregate->ecommunity_hash) {
+ /* Delete all ecommunities in the hash.
+ */
+ hash_clean(aggregate->ecommunity_hash,
+ bgp_aggr_ecommunity_remove);
+ /* Free up the ecommunity_hash.
+ */
+ hash_free(aggregate->ecommunity_hash);
+ }
+
+ if (aggregate->lcommunity)
+ lcommunity_free(&aggregate->lcommunity);
+
+ if (aggregate->lcommunity_hash) {
+ /* Delete all lcommunities in the hash.
+ */
+ hash_clean(aggregate->lcommunity_hash,
+ bgp_aggr_lcommunity_remove);
+ /* Free up the lcommunity_hash.
+ */
+ hash_free(aggregate->lcommunity_hash);
+ }
+
+ if (aggregate->aspath)
+ aspath_free(aggregate->aspath);
+
+ if (aggregate->aspath_hash) {
+ /* Delete all as-paths in the hash.
+ */
+ hash_clean(aggregate->aspath_hash,
+ bgp_aggr_aspath_remove);
+ /* Free up the aspath_hash.
+ */
+ hash_free(aggregate->aspath_hash);
+ }
+
bgp_aggregate_free(aggregate);
bgp_unlock_node(rn);
bgp_unlock_node(rn);
@@ -6134,7 +6341,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
bgp_node_set_bgp_aggregate_info(rn, aggregate);
/* Aggregate address insert into BGP routing table. */
- bgp_aggregate_route(bgp, &p, NULL, afi, safi, NULL, aggregate);
+ bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
return CMD_SUCCESS;
}
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 85325a93cf..04a3c85f2c 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -272,6 +272,71 @@ struct bgp_static {
struct prefix gatewayIp;
};
+/* Aggreagete address:
+ *
+ * advertise-map Set condition to advertise attribute
+ * as-set Generate AS set path information
+ * attribute-map Set attributes of aggregate
+ * route-map Set parameters of aggregate
+ * summary-only Filter more specific routes from updates
+ * suppress-map Conditionally filter more specific routes from updates
+ * <cr>
+ */
+struct bgp_aggregate {
+ /* Summary-only flag. */
+ uint8_t summary_only;
+
+ /* AS set generation. */
+ uint8_t as_set;
+
+ /* Route-map for aggregated route. */
+ struct route_map *map;
+
+ /* Suppress-count. */
+ unsigned long count;
+
+ /* Count of routes of origin type incomplete under this aggregate. */
+ unsigned long incomplete_origin_count;
+
+ /* Count of routes of origin type egp under this aggregate. */
+ unsigned long egp_origin_count;
+
+ /* Hash containing the communities of all the
+ * routes under this aggregate.
+ */
+ struct hash *community_hash;
+
+ /* Hash containing the extended communities of all the
+ * routes under this aggregate.
+ */
+ struct hash *ecommunity_hash;
+
+ /* Hash containing the large communities of all the
+ * routes under this aggregate.
+ */
+ struct hash *lcommunity_hash;
+
+ /* Hash containing the AS-Path of all the
+ * routes under this aggregate.
+ */
+ struct hash *aspath_hash;
+
+ /* Aggregate route's community. */
+ struct community *community;
+
+ /* Aggregate route's extended community. */
+ struct ecommunity *ecommunity;
+
+ /* Aggregate route's large community. */
+ struct lcommunity *lcommunity;
+
+ /* Aggregate route's as-path. */
+ struct aspath *aspath;
+
+ /* SAFI configuration. */
+ safi_t safi;
+};
+
#define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \
((nhlen) < IPV4_MAX_BYTELEN \
? 0 \
@@ -279,7 +344,10 @@ struct bgp_static {
#define BGP_ATTR_NEXTHOP_AFI_IP6(attr) \
(!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) \
- && ((attr)->mp_nexthop_len == 16 || (attr)->mp_nexthop_len == 32))
+ && ((attr)->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL \
+ || (attr)->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL \
+ || (attr)->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL \
+ || (attr)->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL))
#define BGP_PATH_COUNTABLE(BI) \
(!CHECK_FLAG((BI)->flags, BGP_PATH_HISTORY) \
&& !CHECK_FLAG((BI)->flags, BGP_PATH_REMOVED))
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index de24458671..d426e65c53 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -7163,7 +7163,7 @@ DEFUN_NOSH (address_family_vpnv6,
vty->node = BGP_VPNV6_NODE;
return CMD_SUCCESS;
}
-#endif
+#endif /* KEEP_OLD_VPN_COMMANDS */
DEFUN_NOSH (address_family_evpn,
address_family_evpn_cmd,
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 1df5f642b3..5f0b20e029 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -945,14 +945,17 @@ bgp_path_info_to_ipv6_nexthop(struct bgp_path_info *path, ifindex_t *ifindex)
struct in6_addr *nexthop = NULL;
/* Only global address nexthop exists. */
- if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
+ if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL
+ || path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL) {
nexthop = &path->attr->mp_nexthop_global;
if (IN6_IS_ADDR_LINKLOCAL(nexthop))
*ifindex = path->attr->nh_ifindex;
}
/* If both global and link-local address present. */
- if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+ if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
+ || path->attr->mp_nexthop_len
+ == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
/* Check if route-map is set to prefer global over link-local */
if (path->attr->mp_nexthop_prefer_global) {
nexthop = &path->attr->mp_nexthop_global;
@@ -1111,20 +1114,24 @@ int bgp_zebra_get_table_range(uint32_t chunk_size,
}
static int update_ipv4nh_for_route_install(int nh_othervrf,
+ struct bgp *nh_bgp,
struct in_addr *nexthop,
struct attr *attr,
bool is_evpn,
struct zapi_nexthop *api_nh)
{
api_nh->gate.ipv4 = *nexthop;
+ api_nh->vrf_id = nh_bgp->vrf_id;
/* Need to set fields appropriately for EVPN routes imported into
* a VRF (which are programmed as onlink on l3-vni SVI) as well as
* connected routes leaked into a VRF.
*/
- if (is_evpn)
+ if (is_evpn) {
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
- else if (nh_othervrf &&
+ api_nh->onlink = true;
+ api_nh->ifindex = nh_bgp->l3vni_svi_ifindex;
+ } else if (nh_othervrf &&
api_nh->gate.ipv4.s_addr == INADDR_ANY) {
api_nh->type = NEXTHOP_TYPE_IFINDEX;
api_nh->ifindex = attr->nh_ifindex;
@@ -1135,7 +1142,8 @@ static int update_ipv4nh_for_route_install(int nh_othervrf,
}
static int
-update_ipv6nh_for_route_install(int nh_othervrf, struct in6_addr *nexthop,
+update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
+ struct in6_addr *nexthop,
ifindex_t ifindex, struct bgp_path_info *pi,
struct bgp_path_info *best_pi, bool is_evpn,
struct zapi_nexthop *api_nh)
@@ -1143,10 +1151,13 @@ update_ipv6nh_for_route_install(int nh_othervrf, struct in6_addr *nexthop,
struct attr *attr;
attr = pi->attr;
+ api_nh->vrf_id = nh_bgp->vrf_id;
- if (is_evpn)
+ if (is_evpn) {
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
- else if (nh_othervrf) {
+ api_nh->onlink = true;
+ api_nh->ifindex = nh_bgp->l3vni_svi_ifindex;
+ } else if (nh_othervrf) {
if (IN6_IS_ADDR_UNSPECIFIED(nexthop)) {
api_nh->type = NEXTHOP_TYPE_IFINDEX;
api_nh->ifindex = attr->nh_ifindex;
@@ -1297,8 +1308,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
continue;
api_nh = &api.nexthops[valid_nh_count];
- api_nh->vrf_id = nh_othervrf ? info->extra->bgp_orig->vrf_id
- : bgp->vrf_id;
if (nh_family == AF_INET) {
if (bgp_debug_zebra(&api.prefix)) {
if (mpinfo->extra) {
@@ -1338,6 +1347,8 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
nh_updated = update_ipv4nh_for_route_install(
nh_othervrf,
+ nh_othervrf ?
+ info->extra->bgp_orig : bgp,
&mpinfo_cp->attr->nexthop,
mpinfo_cp->attr, is_evpn, api_nh);
} else {
@@ -1372,7 +1383,9 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
nexthop = bgp_path_info_to_ipv6_nexthop(mpinfo_cp,
&ifindex);
nh_updated = update_ipv6nh_for_route_install(
- nh_othervrf, nexthop, ifindex,
+ nh_othervrf, nh_othervrf ?
+ info->extra->bgp_orig : bgp,
+ nexthop, ifindex,
mpinfo, info, is_evpn, api_nh);
}
@@ -2483,6 +2496,7 @@ static int bgp_zebra_process_local_l3vni(int cmd, struct zclient *zclient,
struct ethaddr rmac;
struct in_addr originator_ip;
struct stream *s;
+ ifindex_t svi_ifindex;
memset(&rmac, 0, sizeof(struct ethaddr));
memset(&originator_ip, 0, sizeof(struct in_addr));
@@ -2492,20 +2506,24 @@ static int bgp_zebra_process_local_l3vni(int cmd, struct zclient *zclient,
stream_get(&rmac, s, sizeof(struct ethaddr));
originator_ip.s_addr = stream_get_ipv4(s);
stream_get(&filter, s, sizeof(int));
- }
+ svi_ifindex = stream_getl(s);
- if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx L3-VNI %s VRF %s VNI %u RMAC %s filter %s",
- (cmd == ZEBRA_L3VNI_ADD) ? "add" : "del",
- vrf_id_to_name(vrf_id), l3vni,
- prefix_mac2str(&rmac, buf, sizeof(buf)),
- filter ? "prefix-routes-only" : "none");
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Rx L3-VNI ADD VRF %s VNI %u RMAC %s filter %s svi-if %u",
+ vrf_id_to_name(vrf_id), l3vni,
+ prefix_mac2str(&rmac, buf, sizeof(buf)),
+ filter ? "prefix-routes-only" : "none",
+ svi_ifindex);
- if (cmd == ZEBRA_L3VNI_ADD)
bgp_evpn_local_l3vni_add(l3vni, vrf_id, &rmac, originator_ip,
- filter);
- else
+ filter, svi_ifindex);
+ } else {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Rx L3-VNI DEL VRF %s VNI %u",
+ vrf_id_to_name(vrf_id), l3vni);
+
bgp_evpn_local_l3vni_del(l3vni, vrf_id);
+ }
return 0;
}
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 8e397f0c0e..d99b402e28 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -3799,6 +3799,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset},
{PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset},
{PEER_FLAG_ENFORCE_FIRST_AS, 0, peer_change_reset_in},
+ {PEER_FLAG_IFPEER_V6ONLY, 0, peer_change_reset},
{PEER_FLAG_ROUTEADV, 0, peer_change_none},
{PEER_FLAG_TIMER, 0, peer_change_none},
{PEER_FLAG_TIMER_CONNECT, 0, peer_change_none},
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index dde1501d30..c7d137c76c 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -517,6 +517,9 @@ struct bgp {
/* originator ip - to be used as NH for type-5 routes */
struct in_addr originator_ip;
+ /* SVI associated with the L3-VNI corresponding to this vrf */
+ ifindex_t l3vni_svi_ifindex;
+
/* vrf flags */
uint32_t vrf_flags;
#define BGP_VRF_AUTO (1 << 0)
diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c
index 55775f384f..93729c1476 100644
--- a/bgpd/rfapi/rfapi_import.c
+++ b/bgpd/rfapi/rfapi_import.c
@@ -2190,7 +2190,7 @@ static void rfapiItBiIndexDump(struct agg_node *rn)
prefix2str(&k->extra->vnc.import.aux_prefix,
buf_aux_pfx, sizeof(buf_aux_pfx));
} else
- strncpy(buf_aux_pfx, "(none)", PREFIX_STRLEN);
+ strlcpy(buf_aux_pfx, "(none)", sizeof(buf_aux_pfx));
vnc_zlog_debug_verbose("bpi %p, peer %p, rd %s, aux_prefix %s",
k, k->peer, buf, buf_aux_pfx);
@@ -2221,7 +2221,7 @@ static struct bgp_path_info *rfapiItBiIndexSearch(
prefix2str(aux_prefix, buf_aux_pfx,
sizeof(buf_aux_pfx));
} else
- strncpy(buf_aux_pfx, "(nil)", sizeof(buf_aux_pfx));
+ strlcpy(buf_aux_pfx, "(nil)", sizeof(buf_aux_pfx));
vnc_zlog_debug_verbose("%s want prd=%s, peer=%p, aux_prefix=%s",
__func__,
diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c
index b19b383e65..3db59a838b 100644
--- a/eigrpd/eigrp_main.c
+++ b/eigrpd/eigrp_main.c
@@ -211,10 +211,7 @@ int main(int argc, char **argv, char **envp)
/*eigrp_route_map_init();
route_map_add_hook (eigrp_rmap_update);
route_map_delete_hook (eigrp_rmap_update);*/
- /*if_rmap_init (EIGRP_NODE);
- if_rmap_hook_add (eigrp_if_rmap_update);
- if_rmap_hook_delete (eigrp_if_rmap_update);*/
-
+ /*if_rmap_init (EIGRP_NODE); */
/* Distribute list install. */
distribute_list_init(EIGRP_NODE);
diff --git a/eigrpd/eigrpd.c b/eigrpd/eigrpd.c
index 69d947e59f..93f8b6f90e 100644
--- a/eigrpd/eigrpd.c
+++ b/eigrpd/eigrpd.c
@@ -206,6 +206,13 @@ static struct eigrp *eigrp_new(const char *AS)
eigrp_distribute_update);
distribute_list_delete_hook(eigrp->distribute_ctx,
eigrp_distribute_update);
+
+ /*
+ eigrp->if_rmap_ctx = if_rmap_ctx_create(
+ VRF_DEFAULT_NAME);
+ if_rmap_hook_add (eigrp_if_rmap_update);
+ if_rmap_hook_delete (eigrp_if_rmap_update);
+ */
QOBJ_REG(eigrp, eigrp);
return eigrp;
}
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index 36d4a0d7c0..8377638b92 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -1305,8 +1305,8 @@ ferr_r isis_circuit_passwd_unset(struct isis_circuit *circuit)
return ferr_ok();
}
-static int isis_circuit_passwd_set(struct isis_circuit *circuit,
- uint8_t passwd_type, const char *passwd)
+ferr_r isis_circuit_passwd_set(struct isis_circuit *circuit,
+ uint8_t passwd_type, const char *passwd)
{
int len;
@@ -1319,7 +1319,8 @@ static int isis_circuit_passwd_set(struct isis_circuit *circuit,
"circuit password too long (max 254 chars)");
circuit->passwd.len = len;
- strncpy((char *)circuit->passwd.passwd, passwd, 255);
+ strlcpy((char *)circuit->passwd.passwd, passwd,
+ sizeof(circuit->passwd.passwd));
circuit->passwd.type = passwd_type;
return ferr_ok();
}
diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h
index 73ead8f7da..e0ea4f78b4 100644
--- a/isisd/isis_circuit.h
+++ b/isisd/isis_circuit.h
@@ -190,6 +190,8 @@ ferr_r isis_circuit_metric_set(struct isis_circuit *circuit, int level,
int metric);
ferr_r isis_circuit_passwd_unset(struct isis_circuit *circuit);
+ferr_r isis_circuit_passwd_set(struct isis_circuit *circuit,
+ uint8_t passwd_type, const char *passwd);
ferr_r isis_circuit_passwd_cleartext_set(struct isis_circuit *circuit,
const char *passwd);
ferr_r isis_circuit_passwd_hmac_md5_set(struct isis_circuit *circuit,
diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c
index 3364a9f0be..2d1d6f5927 100644
--- a/isisd/isis_northbound.c
+++ b/isisd/isis_northbound.c
@@ -2092,8 +2092,8 @@ lib_interface_isis_password_password_modify(enum nb_event event,
password = yang_dnode_get_string(dnode, NULL);
circuit = yang_dnode_get_entry(dnode, true);
- circuit->passwd.len = strlen(password);
- strncpy((char *)circuit->passwd.passwd, password, 255);
+
+ isis_circuit_passwd_set(circuit, circuit->passwd.type, password);
return NB_OK;
}
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 13cd510dd1..ad02220438 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -1363,7 +1363,7 @@ struct isis_lsp *lsp_for_arg(const char *argv, dict_t *lspdb)
* xxxx.xxxx.xxxx
*/
if (argv)
- strncpy(sysid, argv, 254);
+ strlcpy(sysid, argv, sizeof(sysid));
if (argv && strlen(argv) > 3) {
pos = argv + strlen(argv) - 3;
if (strncmp(pos, "-", 1) == 0) {
@@ -1639,7 +1639,8 @@ static int isis_area_passwd_set(struct isis_area *area, int level,
return -1;
modified.len = len;
- strncpy((char *)modified.passwd, passwd, 255);
+ strlcpy((char *)modified.passwd, passwd,
+ sizeof(modified.passwd));
modified.type = passwd_type;
modified.snp_auth = snp_auth;
}
diff --git a/lib/event_counter.c b/lib/event_counter.c
index c520937a38..57dbfb5fd1 100644
--- a/lib/event_counter.c
+++ b/lib/event_counter.c
@@ -62,7 +62,7 @@ const char *event_counter_format(const struct event_counter *counter)
|| strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %T %z",
last_change)
== 0) {
- strncpy(timebuf, "???", sizeof(timebuf));
+ strlcpy(timebuf, "???", sizeof(timebuf));
}
snprintf(rv, sizeof(rv), "%5llu last: %s", counter->count,
diff --git a/lib/if_rmap.c b/lib/if_rmap.c
index f8e500f43d..955c1417c4 100644
--- a/lib/if_rmap.c
+++ b/lib/if_rmap.c
@@ -26,14 +26,12 @@
#include "if.h"
#include "if_rmap.h"
+DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX, "Interface route map container")
+DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX_NAME, "Interface route map container name")
DEFINE_MTYPE_STATIC(LIB, IF_RMAP, "Interface route map")
DEFINE_MTYPE_STATIC(LIB, IF_RMAP_NAME, "I.f. route map name")
-struct hash *ifrmaphash;
-
-/* Hook functions. */
-static void (*if_rmap_add_hook)(struct if_rmap *) = NULL;
-static void (*if_rmap_delete_hook)(struct if_rmap *) = NULL;
+struct list *if_rmap_ctx_list;
static struct if_rmap *if_rmap_new(void)
{
@@ -54,7 +52,7 @@ static void if_rmap_free(struct if_rmap *if_rmap)
XFREE(MTYPE_IF_RMAP, if_rmap);
}
-struct if_rmap *if_rmap_lookup(const char *ifname)
+struct if_rmap *if_rmap_lookup(struct if_rmap_ctx *ctx, const char *ifname)
{
struct if_rmap key;
struct if_rmap *if_rmap;
@@ -62,21 +60,25 @@ struct if_rmap *if_rmap_lookup(const char *ifname)
/* temporary copy */
key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL;
- if_rmap = hash_lookup(ifrmaphash, &key);
+ if_rmap = hash_lookup(ctx->ifrmaphash, &key);
XFREE(MTYPE_IF_RMAP_NAME, key.ifname);
return if_rmap;
}
-void if_rmap_hook_add(void (*func)(struct if_rmap *))
+void if_rmap_hook_add(struct if_rmap_ctx *ctx,
+ void (*func)(struct if_rmap_ctx *ctx,
+ struct if_rmap *))
{
- if_rmap_add_hook = func;
+ ctx->if_rmap_add_hook = func;
}
-void if_rmap_hook_delete(void (*func)(struct if_rmap *))
+void if_rmap_hook_delete(struct if_rmap_ctx *ctx,
+ void (*func)(struct if_rmap_ctx *ctx,
+ struct if_rmap *))
{
- if_rmap_delete_hook = func;
+ ctx->if_rmap_delete_hook = func;
}
static void *if_rmap_hash_alloc(void *arg)
@@ -90,7 +92,7 @@ static void *if_rmap_hash_alloc(void *arg)
return if_rmap;
}
-static struct if_rmap *if_rmap_get(const char *ifname)
+static struct if_rmap *if_rmap_get(struct if_rmap_ctx *ctx, const char *ifname)
{
struct if_rmap key;
struct if_rmap *ret;
@@ -98,7 +100,7 @@ static struct if_rmap *if_rmap_get(const char *ifname)
/* temporary copy */
key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL;
- ret = hash_get(ifrmaphash, &key, if_rmap_hash_alloc);
+ ret = hash_get(ctx->ifrmaphash, &key, if_rmap_hash_alloc);
XFREE(MTYPE_IF_RMAP_NAME, key.ifname);
@@ -120,12 +122,13 @@ static bool if_rmap_hash_cmp(const void *arg1, const void *arg2)
return strcmp(if_rmap1->ifname, if_rmap2->ifname) == 0;
}
-static struct if_rmap *if_rmap_set(const char *ifname, enum if_rmap_type type,
+static struct if_rmap *if_rmap_set(struct if_rmap_ctx *ctx,
+ const char *ifname, enum if_rmap_type type,
const char *routemap_name)
{
struct if_rmap *if_rmap;
- if_rmap = if_rmap_get(ifname);
+ if_rmap = if_rmap_get(ctx, ifname);
if (type == IF_RMAP_IN) {
XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]);
@@ -138,18 +141,19 @@ static struct if_rmap *if_rmap_set(const char *ifname, enum if_rmap_type type,
XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name);
}
- if (if_rmap_add_hook)
- (*if_rmap_add_hook)(if_rmap);
+ if (ctx->if_rmap_add_hook)
+ (ctx->if_rmap_add_hook)(ctx, if_rmap);
return if_rmap;
}
-static int if_rmap_unset(const char *ifname, enum if_rmap_type type,
+static int if_rmap_unset(struct if_rmap_ctx *ctx,
+ const char *ifname, enum if_rmap_type type,
const char *routemap_name)
{
struct if_rmap *if_rmap;
- if_rmap = if_rmap_lookup(ifname);
+ if_rmap = if_rmap_lookup(ctx, ifname);
if (!if_rmap)
return 0;
@@ -173,12 +177,12 @@ static int if_rmap_unset(const char *ifname, enum if_rmap_type type,
if_rmap->routemap[IF_RMAP_OUT] = NULL;
}
- if (if_rmap_delete_hook)
- (*if_rmap_delete_hook)(if_rmap);
+ if (ctx->if_rmap_delete_hook)
+ ctx->if_rmap_delete_hook(ctx, if_rmap);
if (if_rmap->routemap[IF_RMAP_IN] == NULL
&& if_rmap->routemap[IF_RMAP_OUT] == NULL) {
- hash_release(ifrmaphash, if_rmap);
+ hash_release(ctx->ifrmaphash, if_rmap);
if_rmap_free(if_rmap);
}
@@ -198,6 +202,8 @@ DEFUN (if_rmap,
int idx_in_out = 2;
int idx_ifname = 3;
enum if_rmap_type type;
+ struct if_rmap_ctx *ctx =
+ (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list);
if (strncmp(argv[idx_in_out]->text, "in", 1) == 0)
type = IF_RMAP_IN;
@@ -208,7 +214,8 @@ DEFUN (if_rmap,
return CMD_WARNING_CONFIG_FAILED;
}
- if_rmap_set(argv[idx_ifname]->arg, type, argv[idx_rmap_name]->arg);
+ if_rmap_set(ctx, argv[idx_ifname]->arg,
+ type, argv[idx_rmap_name]->arg);
return CMD_SUCCESS;
}
@@ -228,6 +235,8 @@ DEFUN (no_if_rmap,
int idx_ifname = 4;
int ret;
enum if_rmap_type type;
+ struct if_rmap_ctx *ctx =
+ (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list);
if (strncmp(argv[idx_in_out]->arg, "i", 1) == 0)
type = IF_RMAP_IN;
@@ -238,7 +247,7 @@ DEFUN (no_if_rmap,
return CMD_WARNING_CONFIG_FAILED;
}
- ret = if_rmap_unset(argv[idx_ifname]->arg, type,
+ ret = if_rmap_unset(ctx, argv[idx_ifname]->arg, type,
argv[idx_routemap_name]->arg);
if (!ret) {
vty_out(vty, "route-map doesn't exist\n");
@@ -249,11 +258,13 @@ DEFUN (no_if_rmap,
/* Configuration write function. */
-int config_write_if_rmap(struct vty *vty)
+int config_write_if_rmap(struct vty *vty,
+ struct if_rmap_ctx *ctx)
{
unsigned int i;
struct hash_bucket *mp;
int write = 0;
+ struct hash *ifrmaphash = ctx->ifrmaphash;
for (i = 0; i < ifrmaphash->size; i++)
for (mp = ifrmaphash->index[i]; mp; mp = mp->next) {
@@ -278,18 +289,44 @@ int config_write_if_rmap(struct vty *vty)
return write;
}
-void if_rmap_reset(void)
+void if_rmap_ctx_delete(struct if_rmap_ctx *ctx)
+{
+ hash_clean(ctx->ifrmaphash, (void (*)(void *))if_rmap_free);
+ if (ctx->name)
+ XFREE(MTYPE_IF_RMAP_CTX_NAME, ctx);
+ XFREE(MTYPE_IF_RMAP_CTX, ctx);
+}
+
+/* name is optional: either vrf name, or other */
+struct if_rmap_ctx *if_rmap_ctx_create(const char *name)
{
- hash_clean(ifrmaphash, (void (*)(void *))if_rmap_free);
+ struct if_rmap_ctx *ctx;
+
+ ctx = XCALLOC(MTYPE_IF_RMAP_CTX, sizeof(struct if_rmap_ctx));
+
+ if (ctx->name)
+ ctx->name = XSTRDUP(MTYPE_IF_RMAP_CTX_NAME, name);
+ ctx->ifrmaphash = hash_create_size(4, if_rmap_hash_make, if_rmap_hash_cmp,
+ "Interface Route-Map Hash");
+ if (!if_rmap_ctx_list)
+ if_rmap_ctx_list = list_new();
+ listnode_add(if_rmap_ctx_list, ctx);
+ return ctx;
}
void if_rmap_init(int node)
{
- ifrmaphash = hash_create_size(4, if_rmap_hash_make, if_rmap_hash_cmp,
- "Interface Route-Map Hash");
if (node == RIPNG_NODE) {
} else if (node == RIP_NODE) {
install_element(RIP_NODE, &if_rmap_cmd);
install_element(RIP_NODE, &no_if_rmap_cmd);
}
+ if_rmap_ctx_list = list_new();
+}
+
+void if_rmap_terminate(void)
+{
+ if (!if_rmap_ctx_list)
+ return;
+ list_delete(&if_rmap_ctx_list);
}
diff --git a/lib/if_rmap.h b/lib/if_rmap.h
index 8dded2cb48..dfc7298823 100644
--- a/lib/if_rmap.h
+++ b/lib/if_rmap.h
@@ -34,12 +34,33 @@ struct if_rmap {
char *routemap[IF_RMAP_MAX];
};
-extern void if_rmap_init(int);
-extern void if_rmap_reset(void);
-extern void if_rmap_hook_add(void (*)(struct if_rmap *));
-extern void if_rmap_hook_delete(void (*)(struct if_rmap *));
-extern struct if_rmap *if_rmap_lookup(const char *);
-extern int config_write_if_rmap(struct vty *);
+struct if_rmap_ctx {
+ /* if_rmap */
+ struct hash *ifrmaphash;
+
+ /* Hook functions. */
+ void (*if_rmap_add_hook)(struct if_rmap_ctx *ctx,
+ struct if_rmap *ifrmap);
+ void (*if_rmap_delete_hook)(struct if_rmap_ctx *ctx,
+ struct if_rmap *ifrmap);
+
+ /* naming information */
+ char *name;
+};
+
+extern struct if_rmap_ctx *if_rmap_ctx_create(const char *name);
+extern void if_rmap_ctx_delete(struct if_rmap_ctx *ctx);
+extern void if_rmap_init(int node);
+extern void if_rmap_terminate(void);
+void if_rmap_hook_add(struct if_rmap_ctx *ctx,
+ void (*func)(struct if_rmap_ctx *ctx,
+ struct if_rmap *));
+void if_rmap_hook_delete(struct if_rmap_ctx *ctx,
+ void (*func)(struct if_rmap_ctx *ctx,
+ struct if_rmap *));
+extern struct if_rmap *if_rmap_lookup(struct if_rmap_ctx *ctx,
+ const char *ifname);
+extern int config_write_if_rmap(struct vty *, struct if_rmap_ctx *ctx);
#ifdef __cplusplus
}
diff --git a/lib/nexthop.h b/lib/nexthop.h
index c79ec590a8..fd27ca207b 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -83,7 +83,6 @@ struct nexthop {
#define NEXTHOP_FLAG_MATCHED (1 << 4) /* Already matched vs a nexthop */
#define NEXTHOP_FLAG_FILTERED (1 << 5) /* rmap filtered, used by static only */
#define NEXTHOP_FLAG_DUPLICATE (1 << 6) /* nexthop duplicates another active one */
-#define NEXTHOP_FLAG_EVPN_RVTEP (1 << 7) /* EVPN remote vtep nexthop */
#define NEXTHOP_IS_ACTIVE(flags) \
(CHECK_FLAG(flags, NEXTHOP_FLAG_ACTIVE) \
&& !CHECK_FLAG(flags, NEXTHOP_FLAG_DUPLICATE))
diff --git a/lib/prefix.c b/lib/prefix.c
index 365a9ba38f..52bb266f11 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -866,7 +866,7 @@ int str2prefix_ipv4(const char *str, struct prefix_ipv4 *p)
return ret;
} else {
cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1);
- strncpy(cp, str, pnt - str);
+ memcpy(cp, str, pnt - str);
*(cp + (pnt - str)) = '\0';
ret = inet_aton(cp, &p->prefix);
XFREE(MTYPE_TMP, cp);
@@ -913,7 +913,7 @@ int str2prefix_eth(const char *str, struct prefix_eth *p)
}
cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1);
- strncpy(cp, str, pnt - str);
+ memcpy(cp, str, pnt - str);
*(cp + (pnt - str)) = '\0';
str_addr = cp;
@@ -1029,7 +1029,7 @@ int str2prefix_ipv6(const char *str, struct prefix_ipv6 *p)
int plen;
cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1);
- strncpy(cp, str, pnt - str);
+ memcpy(cp, str, pnt - str);
*(cp + (pnt - str)) = '\0';
ret = inet_pton(AF_INET6, cp, &p->prefix);
XFREE(MTYPE_TMP, cp);
diff --git a/lib/yang_translator.c b/lib/yang_translator.c
index 6d6f92836f..76a6cc5fd1 100644
--- a/lib/yang_translator.c
+++ b/lib/yang_translator.c
@@ -511,7 +511,7 @@ static void str_replace(char *o_string, const char *s_string,
if (!ch)
return;
- strncpy(buffer, o_string, ch - o_string);
+ memcpy(buffer, o_string, ch - o_string);
buffer[ch - o_string] = 0;
sprintf(buffer + (ch - o_string), "%s%s", r_string,
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index 48d210d279..f74d9733ee 100644
--- a/ospfd/ospf_dump.c
+++ b/ospfd/ospf_dump.c
@@ -538,8 +538,7 @@ static void ospf_header_dump(struct ospf_header *ospfh)
case OSPF_AUTH_NULL:
break;
case OSPF_AUTH_SIMPLE:
- memset(buf, 0, 9);
- strncpy(buf, (char *)ospfh->u.auth_data, 8);
+ strlcpy(buf, (char *)ospfh->u.auth_data, sizeof(buf));
zlog_debug(" Simple Password %s", buf);
break;
case OSPF_AUTH_CRYPTOGRAPHIC:
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index c1dc1f0d6f..bb22f211a7 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -954,8 +954,9 @@ static int ospf_vl_set_security(struct ospf_vl_data *vl_data,
if (vl_config->auth_key) {
memset(IF_DEF_PARAMS(ifp)->auth_simple, 0,
OSPF_AUTH_SIMPLE_SIZE + 1);
- strncpy((char *)IF_DEF_PARAMS(ifp)->auth_simple,
- vl_config->auth_key, OSPF_AUTH_SIMPLE_SIZE);
+ strlcpy((char *)IF_DEF_PARAMS(ifp)->auth_simple,
+ vl_config->auth_key,
+ sizeof(IF_DEF_PARAMS(ifp)->auth_simple));
} else if (vl_config->md5_key) {
if (ospf_crypt_key_lookup(IF_DEF_PARAMS(ifp)->auth_crypt,
vl_config->crypto_key_id)
@@ -967,8 +968,8 @@ static int ospf_vl_set_security(struct ospf_vl_data *vl_data,
ck = ospf_crypt_key_new();
ck->key_id = vl_config->crypto_key_id;
memset(ck->auth_key, 0, OSPF_AUTH_MD5_SIZE + 1);
- strncpy((char *)ck->auth_key, vl_config->md5_key,
- OSPF_AUTH_MD5_SIZE);
+ strlcpy((char *)ck->auth_key, vl_config->md5_key,
+ sizeof(ck->auth_key));
ospf_crypt_key_add(IF_DEF_PARAMS(ifp)->auth_crypt, ck);
} else if (vl_config->crypto_key_id != 0) {
@@ -1147,14 +1148,12 @@ DEFUN (ospf_area_vlink,
if (vl_config.crypto_key_id < 0)
return CMD_WARNING_CONFIG_FAILED;
- memset(md5_key, 0, OSPF_AUTH_MD5_SIZE + 1);
- strncpy(md5_key, argv[idx + 3]->arg, OSPF_AUTH_MD5_SIZE);
+ strlcpy(md5_key, argv[idx + 3]->arg, sizeof(md5_key));
vl_config.md5_key = md5_key;
}
if (argv_find(argv, argc, "authentication-key", &idx)) {
- memset(auth_key, 0, OSPF_AUTH_SIMPLE_SIZE + 1);
- strncpy(auth_key, argv[idx + 1]->arg, OSPF_AUTH_SIMPLE_SIZE);
+ strlcpy(auth_key, argv[idx + 1]->arg, sizeof(auth_key));
vl_config.auth_key = auth_key;
}
@@ -6895,9 +6894,8 @@ DEFUN (ip_ospf_authentication_key,
ospf_if_update_params(ifp, addr);
}
- memset(params->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE + 1);
- strncpy((char *)params->auth_simple, argv[3]->arg,
- OSPF_AUTH_SIMPLE_SIZE);
+ strlcpy((char *)params->auth_simple, argv[3]->arg,
+ sizeof(params->auth_simple));
SET_IF_PARAM(params, auth_simple);
return CMD_SUCCESS;
@@ -7006,8 +7004,7 @@ DEFUN (ip_ospf_message_digest_key,
ck = ospf_crypt_key_new();
ck->key_id = (uint8_t)key_id;
- memset(ck->auth_key, 0, OSPF_AUTH_MD5_SIZE + 1);
- strncpy((char *)ck->auth_key, cryptkey, OSPF_AUTH_MD5_SIZE);
+ strlcpy((char *)ck->auth_key, cryptkey, sizeof(ck->auth_key));
ospf_crypt_key_add(params->auth_crypt, ck);
SET_IF_PARAM(params, auth_crypt);
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index a18e2de725..073a51561b 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -234,8 +234,12 @@ static struct ospf *ospf_new(unsigned short instance, const char *name)
new->instance = instance;
new->router_id.s_addr = htonl(0);
new->router_id_static.s_addr = htonl(0);
- if (name && !strmatch(name, VRF_DEFAULT_NAME)) {
- new->vrf_id = VRF_UNKNOWN;
+ if (name) {
+ vrf = vrf_lookup_by_name(name);
+ if (vrf)
+ new->vrf_id = vrf->vrf_id;
+ else
+ new->vrf_id = VRF_UNKNOWN;
/* Freed in ospf_finish_final */
new->name = XSTRDUP(MTYPE_OSPF_TOP, name);
if (IS_DEBUG_OSPF_EVENT)
diff --git a/pimd/pim_register.c b/pimd/pim_register.c
index b9908ae22b..4b402de634 100644
--- a/pimd/pim_register.c
+++ b/pimd/pim_register.c
@@ -189,8 +189,8 @@ void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src,
if (PIM_DEBUG_PIM_REG) {
char rp_str[INET_ADDRSTRLEN];
- strncpy(rp_str, inet_ntoa(rpg->rpf_addr.u.prefix4),
- INET_ADDRSTRLEN - 1);
+ strlcpy(rp_str, inet_ntoa(rpg->rpf_addr.u.prefix4),
+ sizeof(rp_str));
zlog_debug("%s: Sending %s %sRegister Packet to %s on %s",
__PRETTY_FUNCTION__, up->sg_str,
null_register ? "NULL " : "", rp_str, ifp->name);
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index 6d18c005b9..78b1f7c87c 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -162,7 +162,7 @@ BuildRequires: make
BuildRequires: ncurses-devel
BuildRequires: readline-devel
BuildRequires: texinfo
-BuildRequires: libyang >= 0.16.7
+BuildRequires: libyang-devel >= 0.16.74
%if 0%{?rhel} && 0%{?rhel} < 7
#python27-devel is available from ius community repo for RedHat/CentOS 6
BuildRequires: python27-devel
@@ -624,7 +624,6 @@ fi
%{_libdir}/frr/modules/bgpd_rpki.so
%endif
%{_libdir}/frr/modules/zebra_irdp.so
-%{_libdir}/frr/libyang_plugins/frr_user_types.so
%{_bindir}/*
%config(noreplace) %{configdir}/[!v]*.conf*
%config(noreplace) %attr(750,%{frr_user},%{frr_user}) %{configdir}/daemons
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 38b4aed5bc..d2fc9eb303 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -71,6 +71,9 @@ static int rip_update_jitter(unsigned long);
static void rip_distribute_update(struct distribute_ctx *ctx,
struct distribute *dist);
+static void rip_if_rmap_update(struct if_rmap_ctx *ctx,
+ struct if_rmap *if_rmap);
+
/* RIP output routes type. */
enum { rip_all_route, rip_changed_route };
@@ -851,7 +854,7 @@ static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from,
MD5_CTX ctx;
uint8_t digest[RIP_AUTH_MD5_SIZE];
uint16_t packet_len;
- char auth_str[RIP_AUTH_MD5_SIZE];
+ char auth_str[RIP_AUTH_MD5_SIZE] = {};
if (IS_RIP_DEBUG_EVENT)
zlog_debug("RIPv2 MD5 authentication from %s",
@@ -895,8 +898,6 @@ static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from,
/* retrieve authentication data */
md5data = (struct rip_md5_data *)(((uint8_t *)packet) + packet_len);
- memset(auth_str, 0, RIP_AUTH_MD5_SIZE);
-
if (ri->key_chain) {
keychain = keychain_lookup(ri->key_chain);
if (keychain == NULL)
@@ -906,9 +907,9 @@ static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from,
if (key == NULL || key->string == NULL)
return 0;
- strncpy(auth_str, key->string, RIP_AUTH_MD5_SIZE);
+ strlcpy(auth_str, key->string, sizeof(auth_str));
} else if (ri->auth_str)
- strncpy(auth_str, ri->auth_str, RIP_AUTH_MD5_SIZE);
+ strlcpy(auth_str, ri->auth_str, sizeof(auth_str));
if (auth_str[0] == 0)
return 0;
@@ -941,9 +942,9 @@ static void rip_auth_prepare_str_send(struct rip_interface *ri, struct key *key,
memset(auth_str, 0, len);
if (key && key->string)
- strncpy(auth_str, key->string, len);
+ strlcpy(auth_str, key->string, len);
else if (ri->auth_str)
- strncpy(auth_str, ri->auth_str, len);
+ strlcpy(auth_str, ri->auth_str, len);
return;
}
@@ -1389,13 +1390,12 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to,
if (IS_RIP_DEBUG_PACKET) {
#define ADDRESS_SIZE 20
char dst[ADDRESS_SIZE];
- dst[ADDRESS_SIZE - 1] = '\0';
if (to) {
- strncpy(dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
+ strlcpy(dst, inet_ntoa(to->sin_addr), sizeof(dst));
} else {
sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
- strncpy(dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
+ strlcpy(dst, inet_ntoa(sin.sin_addr), sizeof(dst));
}
#undef ADDRESS_SIZE
zlog_debug("rip_send_packet %s > %s (%s)",
@@ -2100,8 +2100,7 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
key = key_lookup_for_send(keychain);
}
/* to be passed to auth functions later */
- rip_auth_prepare_str_send(ri, key, auth_str,
- RIP_AUTH_SIMPLE_SIZE);
+ rip_auth_prepare_str_send(ri, key, auth_str, sizeof(auth_str));
if (strlen(auth_str) == 0)
return;
}
@@ -2712,6 +2711,12 @@ int rip_create(int socket)
rip_distribute_update);
distribute_list_delete_hook(rip->distribute_ctx,
rip_distribute_update);
+
+ /* if rmap install. */
+ rip->if_rmap_ctx = if_rmap_ctx_create(VRF_DEFAULT_NAME);
+ if_rmap_hook_add(rip->if_rmap_ctx, rip_if_rmap_update);
+ if_rmap_hook_delete(rip->if_rmap_ctx, rip_if_rmap_update);
+
return 0;
}
@@ -3228,7 +3233,7 @@ static int config_write_rip(struct vty *vty)
rip->distribute_ctx);
/* Interface routemap configuration */
- write += config_write_if_rmap(vty);
+ write += config_write_if_rmap(vty, rip->if_rmap_ctx);
}
return write;
}
@@ -3381,25 +3386,33 @@ void rip_clean(void)
route_table_finish(rip->neighbor);
distribute_list_delete(&rip->distribute_ctx);
+
+ if_rmap_ctx_delete(rip->if_rmap_ctx);
+
XFREE(MTYPE_RIP, rip);
rip = NULL;
}
-
rip_clean_network();
rip_passive_nondefault_clean();
rip_offset_clean();
rip_interfaces_clean();
rip_distance_reset();
rip_redistribute_clean();
+ if_rmap_terminate();
}
-static void rip_if_rmap_update(struct if_rmap *if_rmap)
+static void rip_if_rmap_update(struct if_rmap_ctx *ctx,
+ struct if_rmap *if_rmap)
{
- struct interface *ifp;
+ struct interface *ifp = NULL;
struct rip_interface *ri;
struct route_map *rmap;
+ struct vrf *vrf = NULL;
- ifp = if_lookup_by_name(if_rmap->ifname, VRF_DEFAULT);
+ if (ctx->name)
+ vrf = vrf_lookup_by_name(ctx->name);
+ if (vrf)
+ ifp = if_lookup_by_name(if_rmap->ifname, vrf->vrf_id);
if (ifp == NULL)
return;
@@ -3426,10 +3439,18 @@ static void rip_if_rmap_update(struct if_rmap *if_rmap)
void rip_if_rmap_update_interface(struct interface *ifp)
{
struct if_rmap *if_rmap;
+ struct if_rmap_ctx *ctx;
- if_rmap = if_rmap_lookup(ifp->name);
+ if (!rip)
+ return;
+ if (ifp->vrf_id != VRF_DEFAULT)
+ return;
+ ctx = rip->if_rmap_ctx;
+ if (!ctx)
+ return;
+ if_rmap = if_rmap_lookup(ctx, ifp->name);
if (if_rmap)
- rip_if_rmap_update(if_rmap);
+ rip_if_rmap_update(ctx, if_rmap);
}
static void rip_routemap_update_redistribute(void)
@@ -3497,8 +3518,6 @@ void rip_init(void)
route_map_delete_hook(rip_routemap_update);
if_rmap_init(RIP_NODE);
- if_rmap_hook_add(rip_if_rmap_update);
- if_rmap_hook_delete(rip_if_rmap_update);
/* Distance control. */
rip_distance_table = route_table_init();
diff --git a/ripd/ripd.h b/ripd/ripd.h
index 7b8fe3a906..383df3707b 100644
--- a/ripd/ripd.h
+++ b/ripd/ripd.h
@@ -154,6 +154,9 @@ struct rip {
/* For distribute-list container */
struct distribute_ctx *distribute_ctx;
+
+ /* For if_rmap container */
+ struct if_rmap_ctx *if_rmap_ctx;
};
/* RIP routing table entry which belong to rip_packet. */
@@ -419,8 +422,7 @@ extern void rip_zebra_ipv4_add(struct route_node *);
extern void rip_zebra_ipv4_delete(struct route_node *);
extern void rip_interface_multicast_set(int, struct connected *);
extern void rip_distribute_update_interface(struct interface *);
-extern void rip_if_rmap_update_interface(struct interface *);
-
+extern void rip_if_rmap_update_interface(struct interface *ifp);
extern int rip_show_network_config(struct vty *);
extern void rip_show_redistribute_config(struct vty *);
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index 70655beff1..9faebcf0d0 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -60,6 +60,9 @@ void ripng_output_process(struct interface *, struct sockaddr_in6 *, int);
int ripng_triggered_update(struct thread *);
+static void ripng_if_rmap_update(struct if_rmap_ctx *ctx,
+ struct if_rmap *if_rmap);
+
/* RIPng next hop specification. */
struct ripng_nexthop {
enum ripng_nexthop_type {
@@ -1816,6 +1819,12 @@ int ripng_create(int socket)
ripng_distribute_update);
distribute_list_delete_hook(ripng->distribute_ctx,
ripng_distribute_update);
+
+ /* if rmap install. */
+ ripng->if_rmap_ctx = if_rmap_ctx_create(VRF_DEFAULT_NAME);
+ if_rmap_hook_add(ripng->if_rmap_ctx, ripng_if_rmap_update);
+ if_rmap_hook_delete(ripng->if_rmap_ctx, ripng_if_rmap_update);
+
/* Make socket. */
ripng->sock = socket;
@@ -2303,7 +2312,7 @@ static int ripng_config_write(struct vty *vty)
config_write_distribute(vty,
ripng->distribute_ctx);
- config_write_if_rmap(vty);
+ config_write_if_rmap(vty, ripng->if_rmap_ctx);
write = 1;
}
@@ -2474,15 +2483,21 @@ void ripng_clean(void)
ripng_offset_clean();
ripng_interface_clean();
ripng_redistribute_clean();
+ if_rmap_terminate();
}
-static void ripng_if_rmap_update(struct if_rmap *if_rmap)
+static void ripng_if_rmap_update(struct if_rmap_ctx *ctx,
+ struct if_rmap *if_rmap)
{
- struct interface *ifp;
+ struct interface *ifp = NULL;
struct ripng_interface *ri;
struct route_map *rmap;
+ struct vrf *vrf = NULL;
- ifp = if_lookup_by_name(if_rmap->ifname, VRF_DEFAULT);
+ if (ctx->name)
+ vrf = vrf_lookup_by_name(ctx->name);
+ if (vrf)
+ ifp = if_lookup_by_name(if_rmap->ifname, vrf->vrf_id);
if (ifp == NULL)
return;
@@ -2510,10 +2525,18 @@ static void ripng_if_rmap_update(struct if_rmap *if_rmap)
void ripng_if_rmap_update_interface(struct interface *ifp)
{
struct if_rmap *if_rmap;
+ struct if_rmap_ctx *ctx;
- if_rmap = if_rmap_lookup(ifp->name);
+ if (ifp->vrf_id != VRF_DEFAULT)
+ return;
+ if (!ripng)
+ return;
+ ctx = ripng->if_rmap_ctx;
+ if (!ctx)
+ return;
+ if_rmap = if_rmap_lookup(ctx, ifp->name);
if (if_rmap)
- ripng_if_rmap_update(if_rmap);
+ ripng_if_rmap_update(ctx, if_rmap);
}
static void ripng_routemap_update_redistribute(void)
@@ -2590,6 +2613,4 @@ void ripng_init(void)
route_map_delete_hook(ripng_routemap_update);
if_rmap_init(RIPNG_NODE);
- if_rmap_hook_add(ripng_if_rmap_update);
- if_rmap_hook_delete(ripng_if_rmap_update);
}
diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h
index 1db7a83b11..3f0ef13a05 100644
--- a/ripngd/ripngd.h
+++ b/ripngd/ripngd.h
@@ -132,6 +132,9 @@ struct ripng {
/* For distribute-list container */
struct distribute_ctx *distribute_ctx;
+
+ /* For if_rmap container */
+ struct if_rmap_ctx *if_rmap_ctx;
};
/* Routing table entry. */
diff --git a/tools/frr-reload.py b/tools/frr-reload.py
index c48c8b97ad..59f1bcf52b 100755
--- a/tools/frr-reload.py
+++ b/tools/frr-reload.py
@@ -300,13 +300,11 @@ class Config(object):
'''
More fixups in user specification and what running config shows.
- "null0" in routes must be replaced by Null0, and "blackhole" must
- be replaced by Null0 as well.
+ "null0" in routes must be replaced by Null0.
'''
if (key[0].startswith('ip route') or key[0].startswith('ipv6 route') and
- 'null0' in key[0] or 'blackhole' in key[0]):
+ 'null0' in key[0]):
key[0] = re.sub(r'\s+null0(\s*$)', ' Null0', key[0])
- key[0] = re.sub(r'\s+blackhole(\s*$)', ' Null0', key[0])
if lines:
if tuple(key) not in self.contexts:
@@ -435,7 +433,7 @@ end
self.save_contexts(ctx_keys, current_context_lines)
new_ctx = True
- elif line in ["end", "exit-vrf"]:
+ elif line == "end":
self.save_contexts(ctx_keys, current_context_lines)
log.debug('LINE %-50s: exiting old context, %-50s', line, ctx_keys)
@@ -445,6 +443,17 @@ end
ctx_keys = []
current_context_lines = []
+ elif line == "exit-vrf":
+ self.save_contexts(ctx_keys, current_context_lines)
+ current_context_lines.append(line)
+ log.debug('LINE %-50s: append to current_context_lines, %-50s', line, ctx_keys)
+
+ #Start a new context
+ new_ctx = True
+ main_ctx_key = []
+ ctx_keys = []
+ current_context_lines = []
+
elif line in ["exit-address-family", "exit", "exit-vnc"]:
# if this exit is for address-family ipv4 unicast, ignore the pop
if main_ctx_key:
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 9ff869e503..1f1152d364 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -1305,6 +1305,7 @@ DEFUNSH(VTYSH_BGPD, router_bgp, router_bgp_cmd,
return CMD_SUCCESS;
}
+#ifdef KEEP_OLD_VPN_COMMANDS
DEFUNSH(VTYSH_BGPD, address_family_vpnv4, address_family_vpnv4_cmd,
"address-family vpnv4 [unicast]",
"Enter Address Family command mode\n"
@@ -1324,6 +1325,7 @@ DEFUNSH(VTYSH_BGPD, address_family_vpnv6, address_family_vpnv6_cmd,
vty->node = BGP_VPNV6_NODE;
return CMD_SUCCESS;
}
+#endif /* KEEP_OLD_VPN_COMMANDS */
DEFUNSH(VTYSH_BGPD, address_family_ipv4, address_family_ipv4_cmd,
"address-family ipv4 [unicast]",
@@ -3735,8 +3737,10 @@ void vtysh_init_vty(void)
install_element(CONFIG_NODE, &router_isis_cmd);
install_element(CONFIG_NODE, &router_openfabric_cmd);
install_element(CONFIG_NODE, &router_bgp_cmd);
+#ifdef KEEP_OLD_VPN_COMMANDS
install_element(BGP_NODE, &address_family_vpnv4_cmd);
install_element(BGP_NODE, &address_family_vpnv6_cmd);
+#endif /* KEEP_OLD_VPN_COMMANDS */
#if defined(ENABLE_BGP_VNC)
install_element(BGP_NODE, &vnc_vrf_policy_cmd);
install_element(BGP_NODE, &vnc_defaults_cmd);
diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c
index debc151d75..8bec256355 100644
--- a/zebra/if_ioctl.c
+++ b/zebra/if_ioctl.c
@@ -147,7 +147,7 @@ static int if_get_hwaddr(struct interface *ifp)
struct ifreq ifreq;
int i;
- strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ);
+ strlcpy(ifreq.ifr_name, ifp->name, sizeof(ifreq.ifr_name));
ifreq.ifr_addr.sa_family = AF_INET;
/* Fetch Hardware address if available. */
diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c
index 2c29930c3f..8b539a9049 100644
--- a/zebra/if_ioctl_solaris.c
+++ b/zebra/if_ioctl_solaris.c
@@ -247,7 +247,8 @@ static int if_get_addr(struct interface *ifp, struct sockaddr *addr,
* We need to use the logical interface name / label, if we've been
* given one, in order to get the right address
*/
- strncpy(lifreq.lifr_name, (label ? label : ifp->name), IFNAMSIZ);
+ strlcpy(lifreq.lifr_name, (label ? label : ifp->name),
+ sizeof(lifreq.lifr_name));
/* Interface's address. */
memcpy(&lifreq.lifr_addr, addr, ADDRLEN(addr));
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 23c86f35c0..b2f470bc8d 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -68,6 +68,7 @@
#include "zebra/kernel_netlink.h"
#include "zebra/if_netlink.h"
#include "zebra/zebra_errors.h"
+#include "zebra/zebra_vxlan.h"
extern struct zebra_privs_t zserv_privs;
@@ -1111,6 +1112,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
ifindex_t bond_ifindex = IFINDEX_INTERNAL;
ifindex_t link_ifindex = IFINDEX_INTERNAL;
+ uint8_t old_hw_addr[INTERFACE_HWADDR_MAX];
zns = zebra_ns_lookup(ns_id);
@@ -1311,6 +1313,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
was_bond_slave = IS_ZEBRA_IF_BOND_SLAVE(ifp);
zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
+ memcpy(old_hw_addr, ifp->hw_addr, INTERFACE_HWADDR_MAX);
+
netlink_interface_update_hw_addr(tb, ifp);
if (if_is_no_ptm_operative(ifp)) {
@@ -1329,6 +1333,22 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
"Intf %s(%u) PTM up, notifying clients",
name, ifp->ifindex);
zebra_interface_up_update(ifp);
+
+ /* Update EVPN VNI when SVI MAC change
+ */
+ if (IS_ZEBRA_IF_VLAN(ifp) &&
+ memcmp(old_hw_addr, ifp->hw_addr,
+ INTERFACE_HWADDR_MAX)) {
+ struct interface *link_if;
+
+ link_if =
+ if_lookup_by_index_per_ns(
+ zebra_ns_lookup(NS_DEFAULT),
+ link_ifindex);
+ if (link_if)
+ zebra_vxlan_svi_up(ifp,
+ link_if);
+ }
}
} else {
ifp->flags = ifi->ifi_flags & 0x0000fffff;
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index ebe1edcaef..9499c731ef 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -213,7 +213,7 @@ int if_set_prefix(struct interface *ifp, struct connected *ifc)
rib_lookup_and_pushup(p, ifp->vrf_id);
memset(&addreq, 0, sizeof addreq);
- strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
+ strlcpy(addreq.ifra_name, ifp->name, sizeof(addreq.ifra_name));
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_addr = p->prefix;
@@ -267,7 +267,7 @@ int if_unset_prefix(struct interface *ifp, struct connected *ifc)
p = (struct prefix_ipv4 *)ifc->address;
memset(&addreq, 0, sizeof addreq);
- strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
+ strlcpy(addreq.ifra_name, ifp->name, sizeof(addreq.ifra_name));
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_addr = p->prefix;
@@ -412,7 +412,7 @@ void if_get_flags(struct interface *ifp)
if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
(void)memset(&ifmr, 0, sizeof(ifmr));
- strncpy(ifmr.ifm_name, ifp->name, IFNAMSIZ);
+ strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name));
/* Seems not all interfaces implement this ioctl */
if (if_ioctl(SIOCGIFMEDIA, (caddr_t)&ifmr) == -1 &&
@@ -514,7 +514,7 @@ int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc)
p = (struct prefix_ipv6 *)ifc->address;
memset(&addreq, 0, sizeof addreq);
- strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
+ strlcpy(addreq.ifra_name, ifp->name, sizeof(addreq.ifra_name));
memset(&addr, 0, sizeof(struct sockaddr_in6));
addr.sin6_addr = p->prefix;
@@ -557,7 +557,7 @@ int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc)
p = (struct prefix_ipv6 *)ifc->address;
memset(&addreq, 0, sizeof addreq);
- strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
+ strlcpy(addreq.ifra_name, ifp->name, sizeof(addreq.ifra_name));
memset(&addr, 0, sizeof(struct sockaddr_in6));
addr.sin6_addr = p->prefix;
diff --git a/zebra/ioctl_solaris.c b/zebra/ioctl_solaris.c
index fc554219bc..c523ee983d 100644
--- a/zebra/ioctl_solaris.c
+++ b/zebra/ioctl_solaris.c
@@ -44,7 +44,7 @@ extern struct zebra_privs_t zserv_privs;
/* clear and set interface name string */
void lifreq_set_name(struct lifreq *lifreq, const char *ifname)
{
- strncpy(lifreq->lifr_name, ifname, IFNAMSIZ);
+ strlcpy(lifreq->lifr_name, ifname, sizeof(lifreq->lifr_name));
}
int vrf_if_ioctl(unsigned long request, caddr_t buffer, vrf_id_t vrf_id)
@@ -199,7 +199,7 @@ int if_set_prefix(struct interface *ifp, struct connected *ifc)
ifaddr = *p;
- strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ);
+ strlcpy(ifreq.ifr_name, ifp->name, sizeof(ifreq.ifr_name));
addr.sin_addr = p->prefix;
addr.sin_family = p->family;
@@ -250,7 +250,7 @@ int if_unset_prefix(struct interface *ifp, struct connected *ifc)
p = (struct prefix_ipv4 *)ifc->address;
- strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ);
+ strlcpy(ifreq.ifr_name, ifp->name, sizeof(ifreq.ifr_name));
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = p->family;
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 3868412b20..18cf389d5e 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1466,10 +1466,9 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
- if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) {
- if ((p->family == AF_INET) || v6_rr_semantics)
- req.n.nlmsg_flags |= NLM_F_REPLACE;
- }
+ if ((cmd == RTM_NEWROUTE) &&
+ ((p->family == AF_INET) || v6_rr_semantics))
+ req.n.nlmsg_flags |= NLM_F_REPLACE;
req.n.nlmsg_type = cmd;
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 9b91289dec..9f2bbcf426 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -1432,12 +1432,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
case NEXTHOP_TYPE_IPV4_IFINDEX:
memset(&vtep_ip, 0, sizeof(struct ipaddr));
- if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) {
- ifindex = get_l3vni_svi_ifindex(vrf_id);
- } else {
- ifindex = api_nh->ifindex;
- }
-
+ ifindex = api_nh->ifindex;
if (IS_ZEBRA_DEBUG_RECV) {
char nhbuf[INET6_ADDRSTRLEN] = {0};
@@ -1452,12 +1447,10 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
re, &api_nh->gate.ipv4, NULL, ifindex,
api_nh->vrf_id);
- /* if this an EVPN route entry,
- * program the nh as neigh
+ /* Special handling for IPv4 routes sourced from EVPN:
+ * the nexthop and associated MAC need to be installed.
*/
if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) {
- SET_FLAG(nexthop->flags,
- NEXTHOP_FLAG_EVPN_RVTEP);
vtep_ip.ipa_type = IPADDR_V4;
memcpy(&(vtep_ip.ipaddr_v4),
&(api_nh->gate.ipv4),
@@ -1473,22 +1466,15 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
memset(&vtep_ip, 0, sizeof(struct ipaddr));
- if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) {
- ifindex = get_l3vni_svi_ifindex(vrf_id);
- } else {
- ifindex = api_nh->ifindex;
- }
-
+ ifindex = api_nh->ifindex;
nexthop = route_entry_nexthop_ipv6_ifindex_add(
re, &api_nh->gate.ipv6, ifindex,
api_nh->vrf_id);
- /* if this an EVPN route entry,
- * program the nh as neigh
+ /* Special handling for IPv6 routes sourced from EVPN:
+ * the nexthop and associated MAC need to be installed.
*/
if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) {
- SET_FLAG(nexthop->flags,
- NEXTHOP_FLAG_EVPN_RVTEP);
vtep_ip.ipa_type = IPADDR_V6;
memcpy(&vtep_ip.ipaddr_v6, &(api_nh->gate.ipv6),
sizeof(struct in6_addr));
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index a739b0a683..2014aa3bed 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -276,10 +276,8 @@ struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
/*Pending: need to think if null ifp here is ok during bootup?
There was a crash because ifp here was coming to be NULL */
if (ifp)
- if (connected_is_unnumbered(ifp)
- || CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)) {
+ if (connected_is_unnumbered(ifp))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
- }
route_entry_nexthop_add(re, nexthop);
@@ -314,8 +312,6 @@ struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
nexthop->gate.ipv6 = *ipv6;
nexthop->ifindex = ifindex;
- if (CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE))
- SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
route_entry_nexthop_add(re, nexthop);
@@ -433,10 +429,6 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
re->nexthop_mtu = 0;
}
- /* Next hops (remote VTEPs) for EVPN routes are fully resolved. */
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN_RVTEP))
- return 1;
-
/*
* If the kernel has sent us a route, then
* by golly gee whiz it's a good route.
@@ -459,6 +451,9 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
* Check to see if we should trust the passed in information
* for UNNUMBERED interfaces as that we won't find the GW
* address in the routing table.
+ * This check should suffice to handle IPv4 or IPv6 routes
+ * sourced from EVPN routes which are installed with the
+ * next hop as the remote VTEP IP.
*/
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) {
ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
@@ -2937,6 +2932,10 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
return;
}
+ /* Special handling for IPv4 or IPv6 routes sourced from
+ * EVPN - the nexthop (and associated MAC) need to be
+ * uninstalled if no more refs.
+ */
if (CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE)) {
struct nexthop *tmp_nh;
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 33a7583123..16a47f9c4c 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -767,8 +767,7 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
n->detect_start_time.tv_sec);
char tmp_buf[30];
- memset(tmp_buf, 0, 30);
- strncpy(tmp_buf, buf, strlen(buf) - 1);
+ strlcpy(tmp_buf, buf, sizeof(tmp_buf));
vty_out(vty,
" Duplicate detection started at %s, detection count %u\n",
tmp_buf, n->dad_count);
@@ -1148,7 +1147,7 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
struct vty *vty;
zebra_neigh_t *n = NULL;
struct listnode *node = NULL;
- char buf1[20];
+ char buf1[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
struct zebra_vrf *zvrf;
struct timeval detect_start_time = {0, 0};
@@ -1289,8 +1288,7 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
mac->detect_start_time.tv_sec);
char tmp_buf[30];
- memset(tmp_buf, 0, 30);
- strncpy(tmp_buf, buf, strlen(buf) - 1);
+ strlcpy(tmp_buf, buf, sizeof(tmp_buf));
vty_out(vty,
" Duplicate detection started at %s, detection count %u\n",
tmp_buf, mac->dad_count);
@@ -1323,7 +1321,7 @@ static void zvni_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
struct vty *vty;
json_object *json_mac_hdr = NULL, *json_mac = NULL;
zebra_mac_t *mac;
- char buf1[20];
+ char buf1[ETHER_ADDR_STRLEN];
struct mac_walk_ctx *wctx = ctxt;
vty = wctx->vty;
@@ -1445,7 +1443,7 @@ static void zvni_print_mac_hash_detail(struct hash_bucket *bucket, void *ctxt)
json_object *json_mac_hdr = NULL;
zebra_mac_t *mac;
struct mac_walk_ctx *wctx = ctxt;
- char buf1[20];
+ char buf1[ETHER_ADDR_STRLEN];
vty = wctx->vty;
json_mac_hdr = wctx->json;
@@ -4871,6 +4869,7 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
stream_put(s, &rmac, sizeof(struct ethaddr));
stream_put_in_addr(s, &zl3vni->local_vtep_ip);
stream_put(s, &zl3vni->filter, sizeof(int));
+ stream_putl(s, zl3vni->svi_if->ifindex);
/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
@@ -7086,9 +7085,10 @@ void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
zes.zvrf = zvrf;
/* Display all L2-VNIs */
- hash_iterate(zvrf->vni_table, (void (*)(struct hash_bucket *,
- void *))zvni_print_hash_detail,
- &zes);
+ hash_iterate(
+ zvrf->vni_table,
+ (void (*)(struct hash_bucket *, void *))zvni_print_hash_detail,
+ &zes);
/* Display all L3-VNIs */
hash_iterate(zrouter.l3vni_table,
@@ -7097,8 +7097,9 @@ void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
&zes);
if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
}
}