summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_evpn.c109
-rw-r--r--bgpd/bgp_evpn.h1
-rw-r--r--bgpd/bgp_memory.c1
-rw-r--r--bgpd/bgp_memory.h1
-rw-r--r--bgpd/bgp_nexthop.c91
-rw-r--r--bgpd/bgp_nexthop.h16
-rw-r--r--bgpd/bgp_route.c2
-rw-r--r--bgpd/bgp_route.h2
-rw-r--r--bgpd/bgp_zebra.c8
-rw-r--r--bgpd/bgpd.c2
-rw-r--r--bgpd/bgpd.h4
11 files changed, 219 insertions, 18 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 109c98f81c..d9735e7ffa 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -46,6 +46,7 @@
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_nexthop.h"
/*
* Definitions and external declarations.
@@ -1200,6 +1201,13 @@ static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
return 0;
}
+ /* Update the tunnel-ip hash */
+ bgp_tip_del(bgp, &vpn->originator_ip);
+ bgp_tip_add(bgp, &originator_ip);
+
+ /* filter routes as martian nexthop db has changed */
+ bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
+
/* Need to withdraw type-3 route as the originator IP is part
* of the key.
*/
@@ -1392,12 +1400,12 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
bgp_evpn_route_type rtype,
int install)
{
- afi_t afi;
- safi_t safi;
- struct bgp_node *rd_rn, *rn;
- struct bgp_table *table;
- struct bgp_info *ri;
- int ret;
+ afi_t afi;
+ safi_t safi;
+ struct bgp_node *rd_rn, *rn;
+ struct bgp_table *table;
+ struct bgp_info *ri;
+ int ret;
afi = AFI_L2VPN;
safi = SAFI_EVPN;
@@ -1432,7 +1440,7 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
if (is_route_matching_for_vni(bgp, vpn, ri)) {
if (install)
ret = install_evpn_route_entry(
- bgp, vpn, evp, ri);
+ bgp, vpn, evp, ri);
else
ret = uninstall_evpn_route_entry(
bgp, vpn, evp, ri);
@@ -2563,6 +2571,79 @@ int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi,
return install_uninstall_evpn_route(bgp, afi, safi, p, ri, 0);
}
+/* filter routes which have martian next hops */
+int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp)
+{
+ afi_t afi;
+ safi_t safi;
+ struct bgp_node *rd_rn, *rn;
+ struct bgp_table *table;
+ struct bgp_info *ri;
+
+ afi = AFI_L2VPN;
+ safi = SAFI_EVPN;
+
+ /* Walk entire global routing table and evaluate routes which could be
+ * imported into this VPN. Note that we cannot just look at the routes
+ * for the VNI's RD -
+ * remote routes applicable for this VNI could have any RD.
+ */
+ /* EVPN routes are a 2-level table. */
+ for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn;
+ rd_rn = bgp_route_next(rd_rn)) {
+ table = (struct bgp_table *)(rd_rn->info);
+ if (!table)
+ continue;
+
+ for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
+
+ for (ri = rn->info; ri; ri = ri->next) {
+
+ /* Consider "valid" remote routes applicable for
+ * this VNI. */
+ if (!(ri->type == ZEBRA_ROUTE_BGP
+ && ri->sub_type == BGP_ROUTE_NORMAL))
+ continue;
+
+ if (bgp_nexthop_self(bgp,
+ ri->attr->nexthop)) {
+
+ char attr_str[BUFSIZ];
+ char pbuf[PREFIX_STRLEN];
+
+ bgp_dump_attr(ri->attr, attr_str,
+ BUFSIZ);
+
+ if (bgp_debug_update(ri->peer, &rn->p,
+ NULL, 1))
+ zlog_debug(
+ "%u: prefix %s with "
+ "attr %s - DENIED"
+ "due to martian or seld"
+ "nexthop",
+ bgp->vrf_id,
+ prefix2str(
+ &rn->p,
+ pbuf,
+ sizeof(pbuf)),
+ attr_str);
+
+ bgp_evpn_unimport_route(bgp, afi, safi,
+ &rn->p, ri);
+
+ bgp_rib_remove(rn, ri, ri->peer,
+ afi, safi);
+
+
+ }
+
+ }
+ }
+ }
+
+ return 0;
+}
+
/*
* Handle del of a local MACIP.
*/
@@ -2658,6 +2739,11 @@ int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni)
*/
delete_routes_for_vni(bgp, vpn);
+ /*
+ * tunnel is no longer active, del tunnel ip address from tip_hash
+ */
+ bgp_tip_del(bgp, &vpn->originator_ip);
+
/* Clear "live" flag and see if hash needs to be freed. */
UNSET_FLAG(vpn->flags, VNI_FLAG_LIVE);
if (!is_vni_configured(vpn))
@@ -2703,15 +2789,22 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
bgp->vrf_id, vni);
return -1;
}
+
}
- /* if the VNI is live already, there is nothibng more to do */
+ /* if the VNI is live already, there is nothing more to do */
if (is_vni_live(vpn))
return 0;
/* Mark as "live" */
SET_FLAG(vpn->flags, VNI_FLAG_LIVE);
+ /* tunnel is now active, add tunnel-ip to db */
+ bgp_tip_add(bgp, &originator_ip);
+
+ /* filter routes as nexthop database has changed */
+ bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
+
/* Create EVPN type-3 route and schedule for processing. */
build_evpn_type3_prefix(&p, vpn->originator_ip);
if (update_evpn_route(bgp, vpn, &p, 0)) {
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index e9b7857212..ef63199395 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -38,6 +38,7 @@ extern int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi,
struct prefix *p, struct bgp_info *ri);
extern int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi,
struct prefix *p, struct bgp_info *ri);
+extern int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp);
extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni,
struct ethaddr *mac, struct ipaddr *ip);
extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c
index 3df40fa87a..37054ce425 100644
--- a/bgpd/bgp_memory.c
+++ b/bgpd/bgp_memory.c
@@ -101,6 +101,7 @@ DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array")
DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp")
DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate")
DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address")
+DEFINE_MTYPE(BGPD, TIP_ADDR, "BGP own tunnel-ip address")
DEFINE_MTYPE(BGPD, BGP_REDIST, "BGP redistribution")
DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information")
diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h
index 152cfaeaf2..35b83a0401 100644
--- a/bgpd/bgp_memory.h
+++ b/bgpd/bgp_memory.h
@@ -97,6 +97,7 @@ DECLARE_MTYPE(BGP_DAMP_ARRAY)
DECLARE_MTYPE(BGP_REGEXP)
DECLARE_MTYPE(BGP_AGGREGATE)
DECLARE_MTYPE(BGP_ADDR)
+DECLARE_MTYPE(TIP_ADDR)
DECLARE_MTYPE(BGP_REDIST)
DECLARE_MTYPE(BGP_FILTER_NAME)
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 63a84684bb..b988fbf738 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -88,11 +88,86 @@ static void bgp_nexthop_cache_reset(struct bgp_table *table)
}
}
-/* BGP own address structure */
-struct bgp_addr {
- struct in_addr addr;
- int refcnt;
-};
+static void *bgp_tip_hash_alloc(void *p)
+{
+ const struct in_addr *val = (const struct in_addr *)p;
+ struct tip_addr *addr;
+
+ addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
+ addr->refcnt = 0;
+ addr->addr.s_addr = val->s_addr;
+
+ return addr;
+}
+
+static void bgp_tip_hash_free(void *addr)
+{
+ XFREE(MTYPE_TIP_ADDR, addr);
+}
+
+static unsigned int bgp_tip_hash_key_make(void *p)
+{
+ const struct tip_addr *addr = p;
+
+ return jhash_1word(addr->addr.s_addr, 0);
+}
+
+static int bgp_tip_hash_cmp(const void *p1, const void *p2)
+{
+ const struct tip_addr *addr1 = p1;
+ const struct tip_addr *addr2 = p2;
+
+ return addr1->addr.s_addr == addr2->addr.s_addr;
+}
+
+void bgp_tip_hash_init(struct bgp *bgp)
+{
+ bgp->tip_hash = hash_create(bgp_tip_hash_key_make,
+ bgp_tip_hash_cmp, NULL);
+}
+
+void bgp_tip_hash_destroy(struct bgp *bgp)
+{
+ if (bgp->tip_hash == NULL)
+ return;
+ hash_clean(bgp->tip_hash, bgp_tip_hash_free);
+ hash_free(bgp->tip_hash);
+ bgp->tip_hash = NULL;
+}
+
+void bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
+{
+ struct tip_addr tmp;
+ struct tip_addr *addr;
+
+ tmp.addr = *tip;
+
+ addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
+ if (!addr)
+ return;
+
+ addr->refcnt++;
+}
+
+void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
+{
+ struct tip_addr tmp;
+ struct tip_addr *addr;
+
+ tmp.addr = *tip;
+
+ addr = hash_lookup(bgp->tip_hash, &tmp);
+ /* may have been deleted earlier by bgp_interface_down() */
+ if (addr == NULL)
+ return;
+
+ addr->refcnt--;
+
+ if (addr->refcnt == 0) {
+ hash_release(bgp->tip_hash, addr);
+ XFREE(MTYPE_TIP_ADDR, addr);
+ }
+}
static void *bgp_address_hash_alloc(void *p)
{
@@ -304,6 +379,7 @@ void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
{
struct bgp_addr tmp, *addr;
+ struct tip_addr tmp_tip, *tip;
tmp.addr = nh_addr;
@@ -311,6 +387,11 @@ int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
if (addr)
return 1;
+ tmp_tip.addr = nh_addr;
+ tip = hash_lookup(bgp->tip_hash, &tmp_tip);
+ if (tip)
+ return 1;
+
return 0;
}
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 37dad577c2..b482778fdf 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -66,6 +66,18 @@ struct bgp_nexthop_cache {
struct bgp *bgp;
};
+/* BGP own address structure */
+struct bgp_addr {
+ struct in_addr addr;
+ int refcnt;
+};
+
+/* Own tunnel-ip address structure */
+struct tip_addr {
+ struct in_addr addr;
+ int refcnt;
+};
+
extern int bgp_nexthop_lookup(afi_t, struct peer *peer, struct bgp_info *,
int *, int *);
extern void bgp_connected_add(struct bgp *bgp, struct connected *c);
@@ -82,5 +94,9 @@ extern void bgp_scan_finish(struct bgp *bgp);
extern void bgp_scan_vty_init(void);
extern void bgp_address_init(struct bgp *bgp);
extern void bgp_address_destroy(struct bgp *bgp);
+extern void bgp_tip_add(struct bgp *bgp, struct in_addr *tip);
+extern void bgp_tip_del(struct bgp *bgp, struct in_addr *tip);
+extern void bgp_tip_hash_init(struct bgp *bgp);
+extern void bgp_tip_hash_destroy(struct bgp *bgp);
#endif /* _QUAGGA_BGP_NEXTHOP_H */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 35f793f861..fc22642833 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2384,7 +2384,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
/* Unconditionally remove the route from the RIB, without taking
* damping into consideration (eg, because the session went down)
*/
-static void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri,
+void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri,
struct peer *peer, afi_t afi, safi_t safi)
{
bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, safi);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 1a1817bad3..93d79e5059 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -293,6 +293,8 @@ static inline int bgp_fibupd_safi(safi_t safi)
}
/* Prototypes. */
+extern void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri,
+ struct peer *peer, afi_t afi, safi_t safi);
extern void bgp_process_queue_init(void);
extern void bgp_route_init(void);
extern void bgp_route_finish(void);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 2fc75ea5a2..ad73f96d55 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -2107,10 +2107,10 @@ static void bgp_zebra_connected(struct zclient *zclient)
static int bgp_zebra_process_local_vni(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
- struct stream *s;
- vni_t vni;
- struct bgp *bgp;
- struct in_addr vtep_ip;
+ struct stream *s;
+ vni_t vni;
+ struct bgp *bgp;
+ struct in_addr vtep_ip;
s = zclient->ibuf;
vni = stream_getl(s);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index d7733fbacd..f48ba6af24 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -2934,6 +2934,7 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
bgp = bgp_create(as, name, inst_type);
bgp_router_id_set(bgp, &bgp->router_id_zebra);
bgp_address_init(bgp);
+ bgp_tip_hash_init(bgp);
bgp_scan_init(bgp);
*bgp_val = bgp;
@@ -3158,6 +3159,7 @@ static void bgp_free(struct bgp *bgp)
bgp_scan_finish(bgp);
bgp_address_destroy(bgp);
+ bgp_tip_hash_destroy(bgp);
bgp_evpn_cleanup(bgp);
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index bfdddc69b1..344b850fb4 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -318,6 +318,10 @@ struct bgp {
struct hash *address_hash;
+ /* DB for all local tunnel-ips - used mainly for martian checks
+ Currently it only has all VxLan tunnel IPs*/
+ struct hash *tip_hash;
+
/* Static route configuration. */
struct bgp_table *route[AFI_MAX][SAFI_MAX];