uint16_t type;
struct rd_as rd_as;
struct rd_ip rd_ip;
- struct prefix_rd prd;
+ struct prefix_rd prd = {0};
mpls_label_t label = {0};
afi_t afi;
safi_t safi;
if (pnt + BGP_ADDPATH_ID_LEN > lim)
return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
- addpath_id = ntohl(*((uint32_t *)pnt));
+ memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
+ addpath_id = ntohl(addpath_id);
pnt += BGP_ADDPATH_ID_LEN;
}
return;
}
- bgp_attr_dup(&static_attr, path_vrf->attr); /* shallow copy */
+ /* shallow copy */
+ static_attr = *path_vrf->attr;
/*
* route map handling
static_attr.nexthop.s_addr = nexthop->u.prefix4.s_addr;
static_attr.mp_nexthop_global_in = nexthop->u.prefix4;
- static_attr.mp_nexthop_len = 4;
+ static_attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
break;
case AF_INET6:
static_attr.mp_nexthop_global = nexthop->u.prefix6;
- static_attr.mp_nexthop_len = 16;
+ static_attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
break;
default:
*/
static_attr.mp_nexthop_global_in =
static_attr.nexthop;
- static_attr.mp_nexthop_len = 4;
+ static_attr.mp_nexthop_len =
+ BGP_ATTR_NHLEN_IPV4;
/*
* XXX Leave static_attr.nexthop
* intact for NHT
&& !BGP_ATTR_NEXTHOP_AFI_IP6(path_vrf->attr)) {
static_attr.mp_nexthop_global_in.s_addr =
static_attr.nexthop.s_addr;
- static_attr.mp_nexthop_len = 4;
+ static_attr.mp_nexthop_len =
+ BGP_ATTR_NHLEN_IPV4;
static_attr.flag |=
ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
}
buf_prefix, bgp_vrf->name_pretty);
}
- bgp_attr_dup(&static_attr, path_vpn->attr); /* shallow copy */
+ /* shallow copy */
+ static_attr = *path_vpn->attr;
/*
* Nexthop: stash and clear
{
const char *export_name;
vpn_policy_direction_t idir, edir;
- char *vname;
- char buf[1000];
+ char *vname, *tmp_name;
+ char buf[RD_ADDRSTRLEN];
struct ecommunity *ecom;
bool first_export = false;
int debug;
+ struct listnode *node;
+ bool is_inst_match = false;
export_name = to_bgp->name ? to_bgp->name : VRF_DEFAULT_NAME;
idir = BGP_VPN_POLICY_DIR_FROMVPN;
vname = (from_bgp->name ? XSTRDUP(MTYPE_TMP, from_bgp->name)
: XSTRDUP(MTYPE_TMP, VRF_DEFAULT_NAME));
- listnode_add(to_bgp->vpn_policy[afi].import_vrf, vname);
+ /* Check the import_vrf list of destination vrf for the source vrf name,
+ * insert otherwise.
+ */
+ for (ALL_LIST_ELEMENTS_RO(to_bgp->vpn_policy[afi].import_vrf,
+ node, tmp_name)) {
+ if (strcmp(vname, tmp_name) == 0) {
+ is_inst_match = true;
+ break;
+ }
+ }
+ if (!is_inst_match)
+ listnode_add(to_bgp->vpn_policy[afi].import_vrf,
+ vname);
- if (!listcount(from_bgp->vpn_policy[afi].export_vrf))
- first_export = true;
+ /* Check if the source vrf already exports to any vrf,
+ * first time export requires to setup auto derived RD/RT values.
+ * Add the destination vrf name to export vrf list if it is
+ * not present.
+ */
+ is_inst_match = false;
vname = XSTRDUP(MTYPE_TMP, export_name);
- listnode_add(from_bgp->vpn_policy[afi].export_vrf, vname);
-
+ if (!listcount(from_bgp->vpn_policy[afi].export_vrf)) {
+ first_export = true;
+ } else {
+ for (ALL_LIST_ELEMENTS_RO(from_bgp->vpn_policy[afi].export_vrf,
+ node, tmp_name)) {
+ if (strcmp(vname, tmp_name) == 0) {
+ is_inst_match = true;
+ break;
+ }
+ }
+ }
+ if (!is_inst_match)
+ listnode_add(from_bgp->vpn_policy[afi].export_vrf,
+ vname);
/* Update import RT for current VRF using export RT of the VRF we're
* importing from. First though, make sure "import_vrf" has that
* set.
const char *export_name, *tmp_name;
vpn_policy_direction_t idir, edir;
char *vname;
- struct ecommunity *ecom;
+ struct ecommunity *ecom = NULL;
struct listnode *node;
int debug;
if (to_bgp->vpn_policy[afi].import_vrf->count == 0) {
UNSET_FLAG(to_bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_IMPORT);
- ecommunity_free(&to_bgp->vpn_policy[afi].rtlist[idir]);
+ if (to_bgp->vpn_policy[afi].rtlist[idir])
+ ecommunity_free(&to_bgp->vpn_policy[afi].rtlist[idir]);
} else {
ecom = from_bgp->vpn_policy[afi].rtlist[edir];
- ecommunity_del_val(to_bgp->vpn_policy[afi].rtlist[idir],
+ if (ecom)
+ ecommunity_del_val(to_bgp->vpn_policy[afi].rtlist[idir],
(struct ecommunity_val *)ecom->val);
vpn_leak_postchange(idir, afi, bgp_get_default(), to_bgp);
}
*
* import_vrf and export_vrf must match in having
* the in/out names as appropriate.
+ * export_vrf list could have been cleaned up
+ * as part of no router bgp source instnace.
*/
- assert(vname);
+ if (!vname)
+ return;
listnode_delete(from_bgp->vpn_policy[afi].export_vrf, vname);
XFREE(MTYPE_TMP, vname);
bgp);
}
}
+
+/* When a bgp vrf instance is unconfigured, remove its routes
+ * from the VPN table and this vrf could be importing routes from other
+ * bgp vrf instnaces, unimport them.
+ * VRF X and VRF Y are exporting routes to each other.
+ * When VRF X is deleted, unimport its routes from all target vrfs,
+ * also VRF Y should unimport its routes from VRF X table.
+ * This will ensure VPN table is cleaned up appropriately.
+ */
+int bgp_vpn_leak_unimport(struct bgp *from_bgp, struct vty *vty)
+{
+ struct bgp *to_bgp;
+ const char *tmp_name;
+ char *vname;
+ struct listnode *node, *next;
+ safi_t safi = SAFI_UNICAST;
+ afi_t afi;
+ bool is_vrf_leak_bind;
+ int debug;
+
+ if (from_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+ return 0;
+
+ debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
+ BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
+
+ tmp_name = from_bgp->name ? from_bgp->name : VRF_DEFAULT_NAME;
+
+ for (afi = 0; afi < AFI_MAX; ++afi) {
+ /* vrf leak is for IPv4 and IPv6 Unicast only */
+ if (afi != AFI_IP && afi != AFI_IP6)
+ continue;
+
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, to_bgp)) {
+ if (from_bgp == to_bgp)
+ continue;
+
+ /* Unimport and remove source vrf from the
+ * other vrfs import list.
+ */
+ struct vpn_policy *to_vpolicy;
+
+ is_vrf_leak_bind = false;
+ to_vpolicy = &(to_bgp->vpn_policy[afi]);
+ for (ALL_LIST_ELEMENTS_RO(to_vpolicy->import_vrf, node,
+ vname)) {
+ if (strcmp(vname, tmp_name) == 0) {
+ is_vrf_leak_bind = true;
+ break;
+ }
+ }
+ /* skip this bgp instance as there is no leak to this
+ * vrf instance.
+ */
+ if (!is_vrf_leak_bind)
+ continue;
+
+ if (debug)
+ zlog_debug("%s: unimport routes from %s to_bgp %s afi %s import vrfs count %u",
+ __func__, from_bgp->name_pretty,
+ to_bgp->name_pretty, afi2str(afi),
+ to_vpolicy->import_vrf->count);
+
+ vrf_unimport_from_vrf(to_bgp, from_bgp, afi, safi);
+
+ /* readd vrf name as unimport removes import vrf name
+ * from the destination vrf's import list where the
+ * `import vrf` configuration still exist.
+ */
+ vname = XSTRDUP(MTYPE_TMP, tmp_name);
+ listnode_add(to_bgp->vpn_policy[afi].import_vrf,
+ vname);
+ SET_FLAG(to_bgp->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT);
+
+ /* If to_bgp exports its routes to the bgp vrf
+ * which is being deleted, un-import the
+ * to_bgp routes from VPN.
+ */
+ for (ALL_LIST_ELEMENTS_RO(to_bgp->vpn_policy[afi]
+ .export_vrf, node,
+ vname)) {
+ if (strcmp(vname, tmp_name) == 0) {
+ vrf_unimport_from_vrf(from_bgp, to_bgp,
+ afi, safi);
+ break;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/* When a router bgp is configured, there could be a bgp vrf
+ * instance importing routes from this newly configured
+ * bgp vrf instance. Export routes from configured
+ * bgp vrf to VPN.
+ * VRF Y has import from bgp vrf x,
+ * when a bgp vrf x instance is created, export its routes
+ * to VRF Y instance.
+ */
+void bgp_vpn_leak_export(struct bgp *from_bgp)
+{
+ afi_t afi;
+ const char *export_name;
+ char *vname;
+ struct listnode *node, *next;
+ struct ecommunity *ecom;
+ vpn_policy_direction_t idir, edir;
+ safi_t safi = SAFI_UNICAST;
+ struct bgp *to_bgp;
+ int debug;
+
+ debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
+ BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
+
+ idir = BGP_VPN_POLICY_DIR_FROMVPN;
+ edir = BGP_VPN_POLICY_DIR_TOVPN;
+
+ export_name = (from_bgp->name ? XSTRDUP(MTYPE_TMP, from_bgp->name)
+ : XSTRDUP(MTYPE_TMP, VRF_DEFAULT_NAME));
+
+ for (afi = 0; afi < AFI_MAX; ++afi) {
+ /* vrf leak is for IPv4 and IPv6 Unicast only */
+ if (afi != AFI_IP && afi != AFI_IP6)
+ continue;
+
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, to_bgp)) {
+ if (from_bgp == to_bgp)
+ continue;
+
+ /* bgp instance has import list, check to see if newly
+ * configured bgp instance is the list.
+ */
+ struct vpn_policy *to_vpolicy;
+
+ to_vpolicy = &(to_bgp->vpn_policy[afi]);
+ for (ALL_LIST_ELEMENTS_RO(to_vpolicy->import_vrf,
+ node, vname)) {
+ if (strcmp(vname, export_name) != 0)
+ continue;
+
+ if (debug)
+ zlog_debug("%s: found from_bgp %s in to_bgp %s import list, import routes.",
+ __func__,
+ export_name, to_bgp->name_pretty);
+
+ ecom = from_bgp->vpn_policy[afi].rtlist[edir];
+ /* remove import rt, it will be readded
+ * as part of import from vrf.
+ */
+ if (ecom)
+ ecommunity_del_val(
+ to_vpolicy->rtlist[idir],
+ (struct ecommunity_val *)
+ ecom->val);
+ vrf_import_from_vrf(to_bgp, from_bgp,
+ afi, safi);
+ break;
+
+ }
+ }
+ }
+}