#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_nexthop.h"
/*
* Definitions and external declarations.
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.
*/
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;
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);
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.
*/
*/
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))
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)) {
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,
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")
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)
}
}
-/* 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)
{
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;
if (addr)
return 1;
+ tmp_tip.addr = nh_addr;
+ tip = hash_lookup(bgp->tip_hash, &tmp_tip);
+ if (tip)
+ return 1;
+
return 0;
}
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);
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 */
/* 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);
}
/* 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);
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);
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;
bgp_scan_finish(bgp);
bgp_address_destroy(bgp);
+ bgp_tip_hash_destroy(bgp);
bgp_evpn_cleanup(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];