mirror of
https://git.proxmox.com/git/mirror_frr
synced 2026-02-01 18:56:52 +00:00
Merge branch 'master' into docuser
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
commit
6be1a07b97
@ -166,7 +166,6 @@ zebra_route(int add, int family, const unsigned char *pref, unsigned short plen,
|
||||
api.type = ZEBRA_ROUTE_BABEL;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.prefix = quagga_prefix;
|
||||
|
||||
if(metric >= KERNEL_INFINITY) {
|
||||
@ -175,8 +174,8 @@ zebra_route(int add, int family, const unsigned char *pref, unsigned short plen,
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
api.nexthop_num = 1;
|
||||
api_nh->ifindex = ifindex;
|
||||
|
||||
switch (family) {
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
uchar_to_inaddr(&api_nh->gate.ipv4, gate);
|
||||
if (IPV4_ADDR_SAME (&api_nh->gate.ipv4, &quagga_prefix.u.prefix4) &&
|
||||
|
||||
@ -1876,6 +1876,9 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
|
||||
attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr, &sticky);
|
||||
attr->sticky = sticky;
|
||||
|
||||
/* Check if this is a Gateway MAC-IP advertisement */
|
||||
attr->default_gw = bgp_attr_default_gw(attr);
|
||||
|
||||
/* Extract the Rmac, if any */
|
||||
bgp_attr_rmac(attr, &attr->rmac);
|
||||
|
||||
@ -2698,8 +2701,9 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
|
||||
|
||||
void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
|
||||
struct prefix *p, struct prefix_rd *prd,
|
||||
mpls_label_t *label, int addpath_encode,
|
||||
u_int32_t addpath_tx_id, struct attr *attr)
|
||||
mpls_label_t *label, u_int32_t num_labels,
|
||||
int addpath_encode, u_int32_t addpath_tx_id,
|
||||
struct attr *attr)
|
||||
{
|
||||
if (safi == SAFI_MPLS_VPN) {
|
||||
if (addpath_encode)
|
||||
@ -2711,8 +2715,8 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
|
||||
stream_put(s, &p->u.prefix, PSIZE(p->prefixlen));
|
||||
} else if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
|
||||
/* EVPN prefix - contents depend on type */
|
||||
bgp_evpn_encode_prefix(s, p, prd, label, attr, addpath_encode,
|
||||
addpath_tx_id);
|
||||
bgp_evpn_encode_prefix(s, p, prd, label, num_labels,
|
||||
attr, addpath_encode, addpath_tx_id);
|
||||
} else if (safi == SAFI_LABELED_UNICAST) {
|
||||
/* Prefix write with label. */
|
||||
stream_put_labeled_prefix(s, p, label);
|
||||
@ -2840,8 +2844,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
|
||||
struct bpacket_attr_vec_arr *vecarr,
|
||||
struct prefix *p, afi_t afi, safi_t safi,
|
||||
struct peer *from, struct prefix_rd *prd,
|
||||
mpls_label_t *label, int addpath_encode,
|
||||
u_int32_t addpath_tx_id)
|
||||
mpls_label_t *label, u_int32_t num_labels,
|
||||
int addpath_encode, u_int32_t addpath_tx_id)
|
||||
{
|
||||
size_t cp;
|
||||
size_t aspath_sizep;
|
||||
@ -2863,7 +2867,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
|
||||
|
||||
mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
|
||||
vecarr, attr);
|
||||
bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label,
|
||||
bgp_packet_mpattr_prefix(s, afi, safi, p, prd,
|
||||
label, num_labels,
|
||||
addpath_encode, addpath_tx_id, attr);
|
||||
bgp_packet_mpattr_end(s, mpattrlen_pos);
|
||||
}
|
||||
@ -3295,15 +3300,19 @@ size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, safi_t safi)
|
||||
|
||||
void bgp_packet_mpunreach_prefix(struct stream *s, struct prefix *p, afi_t afi,
|
||||
safi_t safi, struct prefix_rd *prd,
|
||||
mpls_label_t *label, int addpath_encode,
|
||||
u_int32_t addpath_tx_id, struct attr *attr)
|
||||
mpls_label_t *label, u_int32_t num_labels,
|
||||
int addpath_encode, u_int32_t addpath_tx_id,
|
||||
struct attr *attr)
|
||||
{
|
||||
u_char wlabel[3] = {0x80, 0x00, 0x00};
|
||||
|
||||
if (safi == SAFI_LABELED_UNICAST)
|
||||
if (safi == SAFI_LABELED_UNICAST) {
|
||||
label = (mpls_label_t *)wlabel;
|
||||
num_labels = 1;
|
||||
}
|
||||
|
||||
return bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label,
|
||||
return bgp_packet_mpattr_prefix(s, afi, safi, p, prd,
|
||||
label, num_labels,
|
||||
addpath_encode, addpath_tx_id, attr);
|
||||
}
|
||||
|
||||
|
||||
@ -162,6 +162,9 @@ struct attr {
|
||||
/* Static MAC for EVPN */
|
||||
u_char sticky;
|
||||
|
||||
/* Flag for default gateway extended community in EVPN */
|
||||
u_char default_gw;
|
||||
|
||||
/* route tag */
|
||||
route_tag_t tag;
|
||||
|
||||
@ -257,7 +260,8 @@ extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
|
||||
struct bpacket_attr_vec_arr *vecarr,
|
||||
struct prefix *, afi_t, safi_t,
|
||||
struct peer *, struct prefix_rd *,
|
||||
mpls_label_t *, int, u_int32_t);
|
||||
mpls_label_t *, u_int32_t,
|
||||
int, u_int32_t);
|
||||
extern void bgp_dump_routes_attr(struct stream *, struct attr *,
|
||||
struct prefix *);
|
||||
extern int attrhash_cmp(const void *, const void *);
|
||||
@ -305,7 +309,8 @@ extern size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer,
|
||||
struct attr *attr);
|
||||
extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
|
||||
struct prefix *p, struct prefix_rd *prd,
|
||||
mpls_label_t *label, int addpath_encode,
|
||||
mpls_label_t *label, u_int32_t num_labels,
|
||||
int addpath_encode,
|
||||
u_int32_t addpath_tx_id, struct attr *);
|
||||
extern size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
|
||||
struct prefix *p);
|
||||
@ -315,7 +320,8 @@ extern size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi,
|
||||
safi_t safi);
|
||||
extern void bgp_packet_mpunreach_prefix(struct stream *s, struct prefix *p,
|
||||
afi_t afi, safi_t safi,
|
||||
struct prefix_rd *prd, mpls_label_t *,
|
||||
struct prefix_rd *prd,
|
||||
mpls_label_t *, u_int32_t,
|
||||
int, u_int32_t, struct attr *);
|
||||
extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt);
|
||||
|
||||
|
||||
@ -134,6 +134,36 @@ void bgp_attr_rmac(struct attr *attr,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* return true if attr contains default gw extended community
|
||||
*/
|
||||
uint8_t bgp_attr_default_gw(struct attr *attr)
|
||||
{
|
||||
struct ecommunity *ecom;
|
||||
int i;
|
||||
|
||||
ecom = attr->ecommunity;
|
||||
if (!ecom || !ecom->size)
|
||||
return 0;
|
||||
|
||||
/* If there is a default gw extendd community return true otherwise
|
||||
* return 0 */
|
||||
for (i = 0; i < ecom->size; i++) {
|
||||
u_char *pnt;
|
||||
u_char type, sub_type;
|
||||
|
||||
pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
|
||||
type = *pnt++;
|
||||
sub_type = *pnt++;
|
||||
|
||||
if ((type == ECOMMUNITY_ENCODE_OPAQUE
|
||||
&& sub_type == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch and return the sequence number from MAC Mobility extended
|
||||
* community, if present, else 0.
|
||||
|
||||
@ -62,5 +62,6 @@ extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag,
|
||||
extern void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac);
|
||||
extern u_int32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
|
||||
u_char *sticky);
|
||||
extern uint8_t bgp_attr_default_gw(struct attr *attr);
|
||||
|
||||
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */
|
||||
|
||||
@ -385,8 +385,8 @@ int bgp_dump_attr(struct attr *attr, char *buf, size_t size)
|
||||
|
||||
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)))
|
||||
snprintf(buf + strlen(buf), size - strlen(buf),
|
||||
", community %s", community_str(attr->community,
|
||||
false));
|
||||
", community %s",
|
||||
community_str(attr->community, false));
|
||||
|
||||
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)))
|
||||
snprintf(buf + strlen(buf), size - strlen(buf),
|
||||
@ -2017,8 +2017,9 @@ int bgp_debug_zebra(struct prefix *p)
|
||||
const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,
|
||||
struct prefix_rd *prd,
|
||||
union prefixconstptr pu,
|
||||
mpls_label_t *label, int addpath_valid,
|
||||
u_int32_t addpath_id, char *str, int size)
|
||||
mpls_label_t *label, u_int32_t num_labels,
|
||||
int addpath_valid, u_int32_t addpath_id,
|
||||
char *str, int size)
|
||||
{
|
||||
char rd_buf[RD_ADDRSTRLEN];
|
||||
char pfx_buf[PREFIX_STRLEN];
|
||||
@ -2041,11 +2042,19 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,
|
||||
addpath_id);
|
||||
|
||||
tag_buf[0] = '\0';
|
||||
if (bgp_labeled_safi(safi) && label) {
|
||||
u_int32_t label_value;
|
||||
if (bgp_labeled_safi(safi) && num_labels) {
|
||||
|
||||
label_value = decode_label(label);
|
||||
sprintf(tag_buf, " label %u", label_value);
|
||||
if (safi == SAFI_EVPN) {
|
||||
char tag_buf2[20];
|
||||
|
||||
bgp_evpn_label2str(label, num_labels, tag_buf2, 20);
|
||||
sprintf(tag_buf, " label %s", tag_buf2);
|
||||
} else {
|
||||
u_int32_t label_value;
|
||||
|
||||
label_value = decode_label(label);
|
||||
sprintf(tag_buf, " label %u", label_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (prd)
|
||||
|
||||
@ -154,7 +154,8 @@ extern int bgp_debug_zebra(struct prefix *p);
|
||||
extern int bgp_debug_count(void);
|
||||
extern const char *bgp_debug_rdpfxpath2str(afi_t, safi_t, struct prefix_rd *,
|
||||
union prefixconstptr, mpls_label_t *,
|
||||
int, u_int32_t, char *, int);
|
||||
u_int32_t, int, u_int32_t, char *,
|
||||
int);
|
||||
const char *bgp_notify_admin_message(char *buf, size_t bufsz, u_char *data,
|
||||
size_t datalen);
|
||||
|
||||
|
||||
@ -690,6 +690,9 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
|
||||
tunneltype = ntohs(tunneltype);
|
||||
len = sprintf(str_buf + str_pnt, "ET:%d",
|
||||
tunneltype);
|
||||
} else if (*pnt == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW) {
|
||||
len = sprintf(str_buf + str_pnt,
|
||||
"Default Gateway");
|
||||
} else
|
||||
unk_ecom = 1;
|
||||
} else if (type == ECOMMUNITY_ENCODE_EVPN) {
|
||||
|
||||
327
bgpd/bgp_evpn.c
327
bgpd/bgp_evpn.c
@ -484,7 +484,7 @@ static void derive_rd_rt_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
struct prefix_evpn *p,
|
||||
struct in_addr remote_vtep_ip, int add,
|
||||
u_char sticky)
|
||||
u_char flags)
|
||||
{
|
||||
struct stream *s;
|
||||
int ipa_len;
|
||||
@ -519,18 +519,18 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
}
|
||||
stream_put_in_addr(s, &remote_vtep_ip);
|
||||
|
||||
/* TX MAC sticky status */
|
||||
/* TX flags - MAC sticky status and/or gateway mac */
|
||||
if (add)
|
||||
stream_putc(s, sticky);
|
||||
stream_putc(s, flags);
|
||||
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
|
||||
if (bgp_debug_zebra(NULL))
|
||||
zlog_debug("Tx %s MACIP, VNI %u %sMAC %s IP %s remote VTEP %s",
|
||||
zlog_debug("Tx %s MACIP, VNI %u MAC %s IP %s (flags: 0x%x) remote VTEP %s",
|
||||
add ? "ADD" : "DEL", vpn->vni,
|
||||
sticky ? "sticky " : "",
|
||||
prefix_mac2str(&p->prefix.mac, buf1, sizeof(buf1)),
|
||||
ipaddr2str(&p->prefix.ip, buf3, sizeof(buf3)),
|
||||
flags,
|
||||
inet_ntop(AF_INET, &remote_vtep_ip, buf2,
|
||||
sizeof(buf2)));
|
||||
|
||||
@ -640,9 +640,11 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
|
||||
{
|
||||
struct ecommunity ecom_encap;
|
||||
struct ecommunity ecom_sticky;
|
||||
struct ecommunity ecom_default_gw;
|
||||
struct ecommunity ecom_rmac;
|
||||
struct ecommunity_val eval;
|
||||
struct ecommunity_val eval_sticky;
|
||||
struct ecommunity_val eval_default_gw;
|
||||
struct ecommunity_val eval_rmac;
|
||||
bgp_encap_types tnl_type;
|
||||
struct listnode *node, *nnode;
|
||||
@ -697,6 +699,15 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
|
||||
&ecom_rmac);
|
||||
}
|
||||
|
||||
if (attr->default_gw) {
|
||||
memset(&ecom_default_gw, 0, sizeof(ecom_default_gw));
|
||||
encode_default_gw_extcomm(&eval_default_gw);
|
||||
ecom_default_gw.size = 1;
|
||||
ecom_default_gw.val = (uint8_t *)eval_default_gw.val;
|
||||
attr->ecommunity = ecommunity_merge(attr->ecommunity,
|
||||
&ecom_default_gw);
|
||||
}
|
||||
|
||||
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
|
||||
}
|
||||
|
||||
@ -754,13 +765,13 @@ static void add_mac_mobility_to_attr(u_int32_t seq_num, struct attr *attr)
|
||||
/* Install EVPN route into zebra. */
|
||||
static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
struct prefix_evpn *p,
|
||||
struct in_addr remote_vtep_ip, u_char sticky)
|
||||
struct in_addr remote_vtep_ip, u_char flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
|
||||
ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip,
|
||||
1, sticky);
|
||||
1, flags);
|
||||
else
|
||||
ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 1);
|
||||
|
||||
@ -831,6 +842,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
afi_t afi = AFI_L2VPN;
|
||||
safi_t safi = SAFI_EVPN;
|
||||
int ret = 0;
|
||||
u_char flags = 0;
|
||||
|
||||
/* Compute the best path. */
|
||||
bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
|
||||
@ -848,11 +860,16 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
&& !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
|
||||
&& !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED)
|
||||
&& !bgp->addpath_tx_used[afi][safi]) {
|
||||
if (bgp_zebra_has_route_changed(rn, old_select))
|
||||
if (bgp_zebra_has_route_changed(rn, old_select)) {
|
||||
if (old_select->attr->sticky)
|
||||
SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
|
||||
if (old_select->attr->default_gw)
|
||||
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
|
||||
ret = evpn_zebra_install(bgp, vpn,
|
||||
(struct prefix_evpn *)&rn->p,
|
||||
old_select->attr->nexthop,
|
||||
old_select->attr->sticky);
|
||||
flags);
|
||||
}
|
||||
UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG);
|
||||
bgp_zebra_clear_route_change_flags(rn);
|
||||
return ret;
|
||||
@ -877,9 +894,14 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
|
||||
if (new_select && new_select->type == ZEBRA_ROUTE_BGP
|
||||
&& new_select->sub_type == BGP_ROUTE_NORMAL) {
|
||||
flags = 0;
|
||||
if (new_select->attr->sticky)
|
||||
SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
|
||||
if (new_select->attr->default_gw)
|
||||
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
|
||||
ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p,
|
||||
new_select->attr->nexthop,
|
||||
new_select->attr->sticky);
|
||||
flags);
|
||||
/* If an old best existed and it was a "local" route, the only
|
||||
* reason
|
||||
* it would be supplanted is due to MAC mobility procedures. So,
|
||||
@ -909,6 +931,28 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the local ri for this rn is of type gateway mac
|
||||
*/
|
||||
static int evpn_route_is_def_gw(struct bgp *bgp, struct bgp_node *rn)
|
||||
{
|
||||
struct bgp_info *tmp_ri = NULL;
|
||||
struct bgp_info *local_ri = NULL;
|
||||
|
||||
local_ri = NULL;
|
||||
for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) {
|
||||
if (tmp_ri->peer == bgp->peer_self
|
||||
&& tmp_ri->type == ZEBRA_ROUTE_BGP
|
||||
&& tmp_ri->sub_type == BGP_ROUTE_STATIC)
|
||||
local_ri = tmp_ri;
|
||||
}
|
||||
|
||||
if (!local_ri)
|
||||
return 0;
|
||||
|
||||
return local_ri->attr->default_gw;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return true if the local ri for this rn has sticky set
|
||||
@ -968,10 +1012,11 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_def,
|
||||
bgp_def->peer_self, attr_new, rn);
|
||||
SET_FLAG(ri->flags, BGP_INFO_VALID);
|
||||
|
||||
/* L3-VNI goes in the label2 field */
|
||||
/* Type-5 routes advertise the L3-VNI */
|
||||
bgp_info_extra_get(ri);
|
||||
vni2label(bgp_vrf->l3vni, &label);
|
||||
memcpy(&ri->extra->label2, &label, BGP_LABEL_BYTES);
|
||||
memcpy(&ri->extra->label, &label, sizeof(label));
|
||||
ri->extra->num_labels = 1;
|
||||
|
||||
/* add the route entry to route node*/
|
||||
bgp_info_add(rn, ri);
|
||||
@ -1003,7 +1048,8 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_def,
|
||||
|
||||
/* update evpn type-5 route entry */
|
||||
static int update_evpn_type5_route(struct bgp *bgp_vrf,
|
||||
struct prefix_evpn *evp)
|
||||
struct prefix_evpn *evp,
|
||||
struct attr* src_attr)
|
||||
{
|
||||
afi_t afi = AFI_L2VPN;
|
||||
safi_t safi = SAFI_EVPN;
|
||||
@ -1014,11 +1060,18 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf,
|
||||
|
||||
bgp_def = bgp_get_default();
|
||||
if (!bgp_def)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
/* build path attribute for this route */
|
||||
memset(&attr, 0, sizeof(struct attr));
|
||||
bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
|
||||
/* Build path attribute for this route - use the source attr, if
|
||||
* present, else treat as locally originated.
|
||||
*/
|
||||
if (src_attr)
|
||||
bgp_attr_dup(&attr, src_attr);
|
||||
else {
|
||||
memset(&attr, 0, sizeof(struct attr));
|
||||
bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
|
||||
}
|
||||
/* Set nexthop to ourselves and fill in the Router MAC. */
|
||||
attr.nexthop = bgp_vrf->originator_ip;
|
||||
attr.mp_nexthop_global_in = bgp_vrf->originator_ip;
|
||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
@ -1045,7 +1098,8 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf,
|
||||
}
|
||||
|
||||
/* uninten temporary */
|
||||
aspath_unintern(&attr.aspath);
|
||||
if (!src_attr)
|
||||
aspath_unintern(&attr.aspath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1061,11 +1115,15 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
struct bgp_info *tmp_ri;
|
||||
struct bgp_info *local_ri, *remote_ri;
|
||||
struct attr *attr_new;
|
||||
mpls_label_t label = MPLS_INVALID_LABEL;
|
||||
mpls_label_t label[BGP_MAX_LABELS];
|
||||
u_int32_t num_labels = 1;
|
||||
int route_change = 1;
|
||||
u_char sticky = 0;
|
||||
struct prefix_evpn *evp;
|
||||
|
||||
*ri = NULL;
|
||||
evp = (struct prefix_evpn *)&rn->p;
|
||||
memset(&label, 0, sizeof(label));
|
||||
|
||||
/* See if this is an update of an existing route, or a new add. Also,
|
||||
* identify if already known from remote, and if so, the one with the
|
||||
@ -1107,7 +1165,7 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
* SVI) advertised in EVPN.
|
||||
* This will ensure that local routes are preferred for g/w macs
|
||||
*/
|
||||
if (remote_ri && !CHECK_FLAG(flags, ZEBRA_MAC_TYPE_GW)) {
|
||||
if (remote_ri && !CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) {
|
||||
u_int32_t cur_seqnum;
|
||||
|
||||
/* Add MM extended community to route. */
|
||||
@ -1130,9 +1188,20 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
bgp_info_extra_get(tmp_ri);
|
||||
|
||||
/* The VNI goes into the 'label' field of the route */
|
||||
vni2label(vpn->vni, &label);
|
||||
vni2label(vpn->vni, &label[0]);
|
||||
/* Type-2 routes may carry a second VNI - the L3-VNI */
|
||||
if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
|
||||
vni_t l3vni;
|
||||
|
||||
memcpy(&tmp_ri->extra->label, &label, BGP_LABEL_BYTES);
|
||||
l3vni = bgpevpn_get_l3vni(vpn);
|
||||
if (l3vni) {
|
||||
vni2label(l3vni, &label[1]);
|
||||
num_labels++;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&tmp_ri->extra->label, label, sizeof(label));
|
||||
tmp_ri->extra->num_labels = num_labels;
|
||||
bgp_info_add(rn, tmp_ri);
|
||||
} else {
|
||||
tmp_ri = local_ri;
|
||||
@ -1183,8 +1252,9 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
attr.nexthop = vpn->originator_ip;
|
||||
attr.mp_nexthop_global_in = vpn->originator_ip;
|
||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
attr.sticky = CHECK_FLAG(flags, ZEBRA_MAC_TYPE_STICKY) ? 1 : 0;
|
||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
|
||||
attr.sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? 1 : 0;
|
||||
attr.default_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW) ? 1 : 0;
|
||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
|
||||
bgpevpn_get_rmac(vpn, &attr.rmac);
|
||||
vni2label(vpn->vni, &(attr.label));
|
||||
|
||||
@ -1270,7 +1340,7 @@ static int delete_evpn_type5_route(struct bgp *bgp_vrf,
|
||||
|
||||
bgp_def = bgp_get_default();
|
||||
if (!bgp_def)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
/* locate the global route entry for this type-5 prefix */
|
||||
rn = bgp_afi_node_lookup(bgp_def->rib[afi][safi], afi, safi,
|
||||
@ -1372,22 +1442,27 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
struct bgp_info *ri;
|
||||
struct attr attr;
|
||||
struct attr attr_sticky;
|
||||
struct attr attr_def_gw;
|
||||
struct attr attr_ip6;
|
||||
struct attr attr_sticky_ip6;
|
||||
struct attr attr_def_gw_ip6;
|
||||
struct attr *attr_new;
|
||||
|
||||
afi = AFI_L2VPN;
|
||||
safi = SAFI_EVPN;
|
||||
memset(&attr, 0, sizeof(struct attr));
|
||||
memset(&attr_sticky, 0, sizeof(struct attr));
|
||||
memset(&attr_def_gw, 0, sizeof(struct attr));
|
||||
memset(&attr_ip6, 0, sizeof(struct attr));
|
||||
memset(&attr_sticky_ip6, 0, sizeof(struct attr));
|
||||
memset(&attr_def_gw_ip6, 0, sizeof(struct attr));
|
||||
|
||||
/* Build path-attribute - all type-2 routes for this VNI will share the
|
||||
* same path attribute.
|
||||
*/
|
||||
bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
|
||||
bgp_attr_default_set(&attr_sticky, BGP_ORIGIN_IGP);
|
||||
bgp_attr_default_set(&attr_def_gw, BGP_ORIGIN_IGP);
|
||||
attr.nexthop = vpn->originator_ip;
|
||||
attr.mp_nexthop_global_in = vpn->originator_ip;
|
||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
@ -1397,8 +1472,14 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
attr_sticky.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
attr_sticky.sticky = 1;
|
||||
bgpevpn_get_rmac(vpn, &attr_sticky.rmac);
|
||||
attr_def_gw.nexthop = vpn->originator_ip;
|
||||
attr_def_gw.mp_nexthop_global_in = vpn->originator_ip;
|
||||
attr_def_gw.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
attr_def_gw.default_gw = 1;
|
||||
bgpevpn_get_rmac(vpn, &attr_def_gw.rmac);
|
||||
bgp_attr_default_set(&attr_ip6, BGP_ORIGIN_IGP);
|
||||
bgp_attr_default_set(&attr_sticky_ip6, BGP_ORIGIN_IGP);
|
||||
bgp_attr_default_set(&attr_def_gw_ip6, BGP_ORIGIN_IGP);
|
||||
attr_ip6.nexthop = vpn->originator_ip;
|
||||
attr_ip6.mp_nexthop_global_in = vpn->originator_ip;
|
||||
attr_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
@ -1408,12 +1489,19 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
attr_sticky_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
attr_sticky_ip6.sticky = 1;
|
||||
bgpevpn_get_rmac(vpn, &attr_sticky_ip6.rmac);
|
||||
attr_def_gw_ip6.nexthop = vpn->originator_ip;
|
||||
attr_def_gw_ip6.mp_nexthop_global_in = vpn->originator_ip;
|
||||
attr_def_gw_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
attr_def_gw_ip6.default_gw = 1;
|
||||
bgpevpn_get_rmac(vpn, &attr_def_gw_ip6.rmac);
|
||||
|
||||
/* Set up RT, ENCAP and sticky MAC extended community. */
|
||||
build_evpn_route_extcomm(vpn, &attr, AFI_IP);
|
||||
build_evpn_route_extcomm(vpn, &attr_sticky, AFI_IP);
|
||||
build_evpn_route_extcomm(vpn, &attr_def_gw, AFI_IP);
|
||||
build_evpn_route_extcomm(vpn, &attr_ip6, AFI_IP6);
|
||||
build_evpn_route_extcomm(vpn, &attr_sticky_ip6, AFI_IP6);
|
||||
build_evpn_route_extcomm(vpn, &attr_def_gw_ip6, AFI_IP);
|
||||
|
||||
/* Walk this VNI's route table and update local type-2 routes. For any
|
||||
* routes updated, update corresponding entry in the global table too.
|
||||
@ -1432,6 +1520,10 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&attr_sticky, 0, 1,
|
||||
&ri, 0);
|
||||
else if (evpn_route_is_def_gw(bgp, rn))
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&attr_def_gw, 0, 1,
|
||||
&ri, 0);
|
||||
else
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&attr, 0, 1, &ri, 0);
|
||||
@ -1440,6 +1532,10 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&attr_sticky_ip6, 0, 1,
|
||||
&ri, 0);
|
||||
else if (evpn_route_is_def_gw(bgp, rn))
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&attr_def_gw_ip6, 0, 1,
|
||||
&ri, 0);
|
||||
else
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&attr_ip6, 0, 1,
|
||||
@ -1474,7 +1570,11 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
|
||||
/* Unintern temporary. */
|
||||
aspath_unintern(&attr.aspath);
|
||||
aspath_unintern(&attr_ip6.aspath);
|
||||
aspath_unintern(&attr_sticky.aspath);
|
||||
aspath_unintern(&attr_sticky_ip6.aspath);
|
||||
aspath_unintern(&attr_def_gw.aspath);
|
||||
aspath_unintern(&attr_def_gw_ip6.aspath);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1717,9 +1817,11 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
|
||||
SET_FLAG(ri->flags, BGP_INFO_VALID);
|
||||
bgp_info_extra_get(ri);
|
||||
ri->extra->parent = parent_ri;
|
||||
if (parent_ri->extra)
|
||||
if (parent_ri->extra) {
|
||||
memcpy(&ri->extra->label, &parent_ri->extra->label,
|
||||
BGP_LABEL_BYTES);
|
||||
sizeof(ri->extra->label));
|
||||
ri->extra->num_labels = parent_ri->extra->num_labels;
|
||||
}
|
||||
bgp_info_add(rn, ri);
|
||||
} else {
|
||||
if (attrhash_cmp(ri->attr, parent_ri->attr)
|
||||
@ -1783,9 +1885,11 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
SET_FLAG(ri->flags, BGP_INFO_VALID);
|
||||
bgp_info_extra_get(ri);
|
||||
ri->extra->parent = parent_ri;
|
||||
if (parent_ri->extra)
|
||||
if (parent_ri->extra) {
|
||||
memcpy(&ri->extra->label, &parent_ri->extra->label,
|
||||
BGP_LABEL_BYTES);
|
||||
sizeof(ri->extra->label));
|
||||
ri->extra->num_labels = parent_ri->extra->num_labels;
|
||||
}
|
||||
bgp_info_add(rn, ri);
|
||||
} else {
|
||||
if (attrhash_cmp(ri->attr, parent_ri->attr)
|
||||
@ -2675,7 +2779,8 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
|
||||
struct prefix_evpn p;
|
||||
u_char ipaddr_len;
|
||||
u_char macaddr_len;
|
||||
mpls_label_t *label_pnt;
|
||||
mpls_label_t label[BGP_MAX_LABELS]; /* holds the VNI(s) as in packet */
|
||||
u_int32_t num_labels = 0;
|
||||
int ret;
|
||||
|
||||
/* Type-2 route should be either 33, 37 or 49 bytes or an
|
||||
@ -2743,19 +2848,31 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
|
||||
}
|
||||
pfx += ipaddr_len;
|
||||
|
||||
/* Get the VNI (in MPLS label field). */
|
||||
/* Note: We ignore the second VNI, if any. */
|
||||
label_pnt = (mpls_label_t *)pfx;
|
||||
/* Get the VNI(s). Stored as bytes here. */
|
||||
num_labels++;
|
||||
memset(label, 0, sizeof(label));
|
||||
memcpy(&label[0], pfx, BGP_LABEL_BYTES);
|
||||
pfx += BGP_LABEL_BYTES;
|
||||
psize -= (33 + ipaddr_len);
|
||||
/* Do we have a second VNI? */
|
||||
if (psize) {
|
||||
num_labels++;
|
||||
memcpy(&label[1], pfx, BGP_LABEL_BYTES);
|
||||
/*
|
||||
* If in future, we are required to access additional fields,
|
||||
* we MUST increment pfx by BGP_LABEL_BYTES in before reading the next field
|
||||
*/
|
||||
}
|
||||
|
||||
/* Process the route. */
|
||||
if (attr)
|
||||
ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
|
||||
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
|
||||
&prd, label_pnt, 0, NULL);
|
||||
&prd, &label[0], num_labels, 0, NULL);
|
||||
else
|
||||
ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr,
|
||||
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
|
||||
&prd, label_pnt, NULL);
|
||||
&prd, &label[0], num_labels, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2811,11 +2928,11 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
|
||||
if (attr)
|
||||
ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
|
||||
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
|
||||
&prd, NULL, 0, NULL);
|
||||
&prd, NULL, 0, 0, NULL);
|
||||
else
|
||||
ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr,
|
||||
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
|
||||
&prd, NULL, NULL);
|
||||
&prd, NULL, 0, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2831,7 +2948,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
|
||||
struct bgp_route_evpn evpn;
|
||||
u_char ippfx_len;
|
||||
u_int32_t eth_tag;
|
||||
mpls_label_t *label_pnt;
|
||||
mpls_label_t label; /* holds the VNI as in the packet */
|
||||
int ret;
|
||||
|
||||
/* Type-5 route should be 34 or 58 bytes:
|
||||
@ -2897,23 +3014,31 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
|
||||
pfx += 16;
|
||||
}
|
||||
|
||||
label_pnt = (mpls_label_t *)pfx;
|
||||
/* Get the VNI (in MPLS label field). Stored as bytes here. */
|
||||
memset(&label, 0, sizeof(label));
|
||||
memcpy(&label, pfx, BGP_LABEL_BYTES);
|
||||
|
||||
/*
|
||||
* If in future, we are required to access additional fields,
|
||||
* we MUST increment pfx by BGP_LABEL_BYTES in before reading the next field
|
||||
*/
|
||||
|
||||
/* Process the route. */
|
||||
if (!withdraw)
|
||||
ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
|
||||
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
|
||||
&prd, label_pnt, 0, &evpn);
|
||||
&prd, &label, 1, 0, &evpn);
|
||||
else
|
||||
ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr,
|
||||
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
|
||||
&prd, label_pnt, &evpn);
|
||||
&prd, &label, 1, &evpn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void evpn_mpattr_encode_type5(struct stream *s, struct prefix *p,
|
||||
struct prefix_rd *prd, mpls_label_t *label,
|
||||
struct prefix_rd *prd,
|
||||
mpls_label_t *label, u_int32_t num_labels,
|
||||
struct attr *attr)
|
||||
{
|
||||
int len;
|
||||
@ -2958,7 +3083,7 @@ static void evpn_mpattr_encode_type5(struct stream *s, struct prefix *p,
|
||||
stream_put(s, &temp, 16);
|
||||
}
|
||||
|
||||
if (label)
|
||||
if (num_labels)
|
||||
stream_put(s, label, 3);
|
||||
else
|
||||
stream_put3(s, 0);
|
||||
@ -3057,20 +3182,24 @@ static void bgp_evpn_handle_export_rt_change_for_vrf(struct bgp *bgp_vrf)
|
||||
*/
|
||||
|
||||
/* withdraw type-5 route corresponding to ip prefix */
|
||||
void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, struct bgp_node *rn,
|
||||
void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, struct prefix *p,
|
||||
afi_t afi, safi_t safi)
|
||||
{
|
||||
int ret = 0;
|
||||
struct prefix_evpn evp;
|
||||
char buf[PREFIX_STRLEN];
|
||||
|
||||
build_type5_prefix_from_ip_prefix(&evp, &rn->p);
|
||||
/* NOTE: Check needed as this is called per-route also. */
|
||||
if (!advertise_type5_routes(bgp_vrf, afi))
|
||||
return;
|
||||
|
||||
build_type5_prefix_from_ip_prefix(&evp, p);
|
||||
ret = delete_evpn_type5_route(bgp_vrf, &evp);
|
||||
if (ret) {
|
||||
zlog_err(
|
||||
"%u failed to delete type-5 route for prefix %s in vrf %s",
|
||||
bgp_vrf->vrf_id,
|
||||
prefix2str(&rn->p, buf, sizeof(buf)),
|
||||
prefix2str(p, buf, sizeof(buf)),
|
||||
vrf_id_to_name(bgp_vrf->vrf_id));
|
||||
}
|
||||
}
|
||||
@ -3082,54 +3211,77 @@ void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf,
|
||||
struct bgp_table *table = NULL;
|
||||
struct bgp_node *rn = NULL;
|
||||
|
||||
/* Bail out early if we don't have to advertise type-5 routes. */
|
||||
if (!advertise_type5_routes(bgp_vrf, afi))
|
||||
return;
|
||||
|
||||
table = bgp_vrf->rib[afi][safi];
|
||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
|
||||
bgp_evpn_withdraw_type5_route(bgp_vrf, rn, afi, safi);
|
||||
bgp_evpn_withdraw_type5_route(bgp_vrf, &rn->p, afi, safi);
|
||||
|
||||
}
|
||||
|
||||
/* advertise ip prefix as type-5 route*/
|
||||
void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct bgp_node *rn,
|
||||
/*
|
||||
* Advertise IP prefix as type-5 route. The afi/safi and src_attr passed
|
||||
* to this function correspond to those of the source IP prefix (best
|
||||
* path in the case of the attr. In the case of a local prefix (when we
|
||||
* are advertising local subnets), the src_attr will be NULL.
|
||||
*/
|
||||
void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct prefix *p,
|
||||
struct attr *src_attr,
|
||||
afi_t afi, safi_t safi)
|
||||
{
|
||||
int ret = 0;
|
||||
struct prefix_evpn evp;
|
||||
char buf[PREFIX_STRLEN];
|
||||
|
||||
/* NOTE: Check needed as this is called per-route also. */
|
||||
if (!advertise_type5_routes(bgp_vrf, afi))
|
||||
return;
|
||||
|
||||
if (!rn->info)
|
||||
return;
|
||||
|
||||
/* only advertise subnet routes as type-5 */
|
||||
if (is_host_route(&rn->p))
|
||||
if (is_host_route(p))
|
||||
return;
|
||||
|
||||
build_type5_prefix_from_ip_prefix(&evp, &rn->p);
|
||||
ret = update_evpn_type5_route(bgp_vrf, &evp);
|
||||
if (ret) {
|
||||
build_type5_prefix_from_ip_prefix(&evp, p);
|
||||
ret = update_evpn_type5_route(bgp_vrf, &evp, src_attr);
|
||||
if (ret)
|
||||
zlog_err(
|
||||
"%u failed to create type-5 route for prefix %s in vrf %s",
|
||||
"%u: Failed to create type-5 route for prefix %s",
|
||||
bgp_vrf->vrf_id,
|
||||
prefix2str(&rn->p, buf, sizeof(buf)),
|
||||
vrf_id_to_name(bgp_vrf->vrf_id));
|
||||
}
|
||||
prefix2str(p, buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
/* advertise all type-5 routes for an address family */
|
||||
/* Inject all prefixes of a particular address-family (currently, IPv4 or
|
||||
* IPv6 unicast) into EVPN as type-5 routes. This is invoked when the
|
||||
* advertisement is enabled.
|
||||
*/
|
||||
void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf,
|
||||
afi_t afi, safi_t safi)
|
||||
{
|
||||
struct bgp_table *table = NULL;
|
||||
struct bgp_node *rn = NULL;
|
||||
struct bgp_info *ri;
|
||||
|
||||
/* Bail out early if we don't have to advertise type-5 routes. */
|
||||
if (!advertise_type5_routes(bgp_vrf, afi))
|
||||
return;
|
||||
|
||||
table = bgp_vrf->rib[afi][safi];
|
||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
|
||||
bgp_evpn_advertise_type5_route(bgp_vrf, rn, afi, safi);
|
||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
|
||||
/* Need to identify the "selected" route entry to use its
|
||||
* attribute.
|
||||
* TODO: Support for AddPath for EVPN.
|
||||
*/
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) {
|
||||
bgp_evpn_advertise_type5_route(bgp_vrf, &rn->p,
|
||||
ri->attr,
|
||||
afi, safi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void evpn_rt_delete_auto(struct bgp *bgp, vni_t vni,
|
||||
@ -3350,14 +3502,19 @@ int bgp_evpn_uninstall_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to display "tag" in route as a VNI.
|
||||
* TODO: Hardcoded for a maximum of 2 VNIs right now
|
||||
*/
|
||||
char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len)
|
||||
char *bgp_evpn_label2str(mpls_label_t *label, u_int32_t num_labels,
|
||||
char *buf, int len)
|
||||
{
|
||||
vni_t vni;
|
||||
vni_t vni1, vni2;
|
||||
|
||||
vni = label2vni(label);
|
||||
snprintf(buf, len, "%u", vni);
|
||||
vni1 = label2vni(label);
|
||||
if (num_labels == 2) {
|
||||
vni2 = label2vni(label+1);
|
||||
snprintf(buf, len, "%u/%u", vni1, vni2);
|
||||
} else
|
||||
snprintf(buf, len, "%u", vni1);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -3461,7 +3618,7 @@ char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len)
|
||||
PREFIX2STR_BUFFER));
|
||||
}
|
||||
} else if (p->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE) {
|
||||
snprintf(buf, len, "[%d]:[0]:[%d]:[%s]",
|
||||
snprintf(buf, len, "[%d]:[0]:[0]:[%d]:[%s]",
|
||||
p->prefix.route_type,
|
||||
p->prefix.ip_prefix_length,
|
||||
IS_EVPN_PREFIX_IPADDR_V4(p) ?
|
||||
@ -3480,12 +3637,13 @@ char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len)
|
||||
* Encode EVPN prefix in Update (MP_REACH)
|
||||
*/
|
||||
void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
|
||||
struct prefix_rd *prd, mpls_label_t *label,
|
||||
struct prefix_rd *prd,
|
||||
mpls_label_t *label, u_int32_t num_labels,
|
||||
struct attr *attr, int addpath_encode,
|
||||
u_int32_t addpath_tx_id)
|
||||
{
|
||||
struct prefix_evpn *evp = (struct prefix_evpn *)p;
|
||||
int ipa_len = 0;
|
||||
int len, ipa_len = 0;
|
||||
|
||||
if (addpath_encode)
|
||||
stream_putl(s, addpath_tx_id);
|
||||
@ -3499,18 +3657,24 @@ void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
|
||||
ipa_len = IPV4_MAX_BYTELEN;
|
||||
else if (IS_EVPN_PREFIX_IPADDR_V6(evp))
|
||||
ipa_len = IPV6_MAX_BYTELEN;
|
||||
stream_putc(s, 33 + ipa_len); // 1 VNI
|
||||
/* RD, ESI, EthTag, MAC+len, IP len, [IP], 1 VNI */
|
||||
len = 8 + 10 + 4 + 1 + 6 + 1 + ipa_len + 3;
|
||||
if (ipa_len && num_labels > 1) /* There are 2 VNIs */
|
||||
len += 3;
|
||||
stream_putc(s, len);
|
||||
stream_put(s, prd->val, 8); /* RD */
|
||||
stream_put(s, 0, 10); /* ESI */
|
||||
stream_putl(s, 0); /* Ethernet Tag ID */
|
||||
stream_putc(s, 8 * ETH_ALEN); /* Mac Addr Len - bits */
|
||||
stream_put(s, evp->prefix.mac.octet, 6); /* Mac Addr */
|
||||
stream_putc(s, 8 * ipa_len); /* IP address Length */
|
||||
if (ipa_len)
|
||||
stream_put(s, &evp->prefix.ip.ip.addr,
|
||||
ipa_len); /* IP */
|
||||
stream_put(s, label,
|
||||
BGP_LABEL_BYTES); /* VNI is contained in 'tag' */
|
||||
if (ipa_len) /* IP */
|
||||
stream_put(s, &evp->prefix.ip.ip.addr, ipa_len);
|
||||
/* 1st label is the L2 VNI */
|
||||
stream_put(s, label, BGP_LABEL_BYTES);
|
||||
/* Include 2nd label (L3 VNI) if advertising MAC+IP */
|
||||
if (ipa_len && num_labels > 1)
|
||||
stream_put(s, label+1, BGP_LABEL_BYTES);
|
||||
break;
|
||||
|
||||
case BGP_EVPN_IMET_ROUTE:
|
||||
@ -3524,7 +3688,7 @@ void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
|
||||
|
||||
case BGP_EVPN_IP_PREFIX_ROUTE:
|
||||
/* TODO: AddPath support. */
|
||||
evpn_mpattr_encode_type5(s, p, prd, label, attr);
|
||||
evpn_mpattr_encode_type5(s, p, prd, label, num_labels, attr);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -4020,12 +4184,13 @@ int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
|
||||
char buf2[INET6_ADDRSTRLEN];
|
||||
|
||||
zlog_err(
|
||||
"%u:Failed to create Type-2 route, VNI %u %s MAC %s IP %s",
|
||||
"%u:Failed to create Type-2 route, VNI %u %s MAC %s IP %s (flags: 0x%x)",
|
||||
bgp->vrf_id, vpn->vni,
|
||||
CHECK_FLAG(flags, ZEBRA_MAC_TYPE_STICKY) ? "sticky gateway"
|
||||
CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? "sticky gateway"
|
||||
: "",
|
||||
prefix_mac2str(mac, buf, sizeof(buf)),
|
||||
ipaddr2str(ip, buf2, sizeof(buf2)));
|
||||
ipaddr2str(ip, buf2, sizeof(buf2)),
|
||||
flags);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -34,11 +34,33 @@ static inline int is_evpn_enabled(void)
|
||||
return bgp ? bgp->advertise_all_vni : 0;
|
||||
}
|
||||
|
||||
static inline void vni2label(vni_t vni, mpls_label_t *label)
|
||||
{
|
||||
u_char *tag = (u_char *)label;
|
||||
|
||||
tag[0] = (vni >> 16) & 0xFF;
|
||||
tag[1] = (vni >> 8) & 0xFF;
|
||||
tag[2] = vni & 0xFF;
|
||||
}
|
||||
|
||||
static inline vni_t label2vni(mpls_label_t *label)
|
||||
{
|
||||
u_char *tag = (u_char *)label;
|
||||
vni_t vni;
|
||||
|
||||
vni = ((u_int32_t)*tag++ << 16);
|
||||
vni |= (u_int32_t)*tag++ << 8;
|
||||
vni |= (u_int32_t)(*tag & 0xFF);
|
||||
|
||||
return vni;
|
||||
}
|
||||
|
||||
extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf,
|
||||
struct bgp_node *rn,
|
||||
struct prefix *p,
|
||||
struct attr *src_attr,
|
||||
afi_t afi, safi_t safi);
|
||||
extern void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf,
|
||||
struct bgp_node *rn,
|
||||
struct prefix *p,
|
||||
afi_t afi, safi_t safi);
|
||||
extern void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, afi_t afi,
|
||||
safi_t safi);
|
||||
@ -46,11 +68,13 @@ extern void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi,
|
||||
safi_t safi);
|
||||
extern void bgp_evpn_vrf_delete(struct bgp *bgp_vrf);
|
||||
extern void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw);
|
||||
extern char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len);
|
||||
extern char *bgp_evpn_label2str(mpls_label_t *label, u_int32_t num_labels,
|
||||
char *buf, int len);
|
||||
extern char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len);
|
||||
extern void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json);
|
||||
extern void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
|
||||
struct prefix_rd *prd, mpls_label_t *label,
|
||||
struct prefix_rd *prd,
|
||||
mpls_label_t *label, u_int32_t num_labels,
|
||||
struct attr *attr, int addpath_encode,
|
||||
u_int32_t addpath_tx_id);
|
||||
extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
|
||||
|
||||
@ -65,6 +65,9 @@ struct bgpevpn {
|
||||
/* Flag to indicate if we are advertising the g/w mac ip for this VNI*/
|
||||
u_int8_t advertise_gw_macip;
|
||||
|
||||
/* Flag to indicate if we are advertising subnet for this VNI */
|
||||
u_int8_t advertise_subnet;
|
||||
|
||||
/* Id for deriving the RD automatically for this VNI */
|
||||
u_int16_t rd_id;
|
||||
|
||||
@ -228,26 +231,6 @@ static inline int is_vni_param_configured(struct bgpevpn *vpn)
|
||||
|| is_export_rt_configured(vpn));
|
||||
}
|
||||
|
||||
static inline void vni2label(vni_t vni, mpls_label_t *label)
|
||||
{
|
||||
u_char *tag = (u_char *)label;
|
||||
tag[0] = (vni >> 16) & 0xFF;
|
||||
tag[1] = (vni >> 8) & 0xFF;
|
||||
tag[2] = vni & 0xFF;
|
||||
}
|
||||
|
||||
static inline vni_t label2vni(mpls_label_t *label)
|
||||
{
|
||||
u_char *tag = (u_char *)label;
|
||||
vni_t vni;
|
||||
|
||||
vni = ((u_int32_t)*tag++ << 16);
|
||||
vni |= (u_int32_t)*tag++ << 8;
|
||||
vni |= (u_int32_t)(*tag & 0xFF);
|
||||
|
||||
return vni;
|
||||
}
|
||||
|
||||
static inline void encode_rmac_extcomm(struct ecommunity_val *eval,
|
||||
struct ethaddr *rmac)
|
||||
{
|
||||
@ -257,6 +240,13 @@ static inline void encode_rmac_extcomm(struct ecommunity_val *eval,
|
||||
memcpy(&eval->val[2], rmac, ETH_ALEN);
|
||||
}
|
||||
|
||||
static inline void encode_default_gw_extcomm(struct ecommunity_val *eval)
|
||||
{
|
||||
memset(eval, 0, sizeof(*eval));
|
||||
eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE;
|
||||
eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_DEF_GW;
|
||||
}
|
||||
|
||||
static inline void encode_mac_mobility_extcomm(int static_mac, u_int32_t seq,
|
||||
struct ecommunity_val *eval)
|
||||
{
|
||||
|
||||
@ -331,10 +331,88 @@ static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
|
||||
vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
|
||||
vty_out(vty,
|
||||
"EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
|
||||
vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n\n");
|
||||
vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
|
||||
vty_out(vty, "EVPN type-5 prefix: [5]:[ESI]:[EthTag]:[IPlen]:[IP]\n\n");
|
||||
vty_out(vty, "%s", ri_header);
|
||||
}
|
||||
|
||||
static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
|
||||
json_object *json)
|
||||
{
|
||||
char buf1[INET6_ADDRSTRLEN];
|
||||
char *ecom_str;
|
||||
struct listnode *node, *nnode;
|
||||
struct ecommunity *ecom;
|
||||
json_object *json_import_rtl = NULL;
|
||||
json_object *json_export_rtl = NULL;
|
||||
|
||||
json_import_rtl = json_export_rtl = 0;
|
||||
|
||||
if (json) {
|
||||
json_import_rtl = json_object_new_array();
|
||||
json_export_rtl = json_object_new_array();
|
||||
json_object_int_add(json, "vni", bgp_vrf->l3vni);
|
||||
json_object_string_add(json, "type", "L3");
|
||||
json_object_string_add(json, "kernelFlag", "Yes");
|
||||
json_object_string_add(
|
||||
json, "rd",
|
||||
prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
|
||||
json_object_string_add(json, "originatorIp",
|
||||
inet_ntoa(bgp_vrf->originator_ip));
|
||||
json_object_string_add(json, "advertiseGatewayMacip", "n/a");
|
||||
} else {
|
||||
vty_out(vty, "VNI: %d", bgp_vrf->l3vni);
|
||||
vty_out(vty, " (known to the kernel)");
|
||||
vty_out(vty, "\n");
|
||||
|
||||
vty_out(vty, " Type: %s\n", "L3");
|
||||
vty_out(vty, " Tenant VRF: %s\n",
|
||||
vrf_id_to_name(bgp_vrf->vrf_id));
|
||||
vty_out(vty, " RD: %s\n",
|
||||
prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
|
||||
vty_out(vty, " Originator IP: %s\n",
|
||||
inet_ntoa(bgp_vrf->originator_ip));
|
||||
vty_out(vty, " Advertise-gw-macip : %s\n", "n/a");
|
||||
}
|
||||
|
||||
if (!json)
|
||||
vty_out(vty, " Import Route Target:\n");
|
||||
|
||||
for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_import_rtl, node, nnode, ecom)) {
|
||||
ecom_str = ecommunity_ecom2str(ecom,
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
|
||||
if (json)
|
||||
json_object_array_add(json_import_rtl,
|
||||
json_object_new_string(ecom_str));
|
||||
else
|
||||
vty_out(vty, " %s\n", ecom_str);
|
||||
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
}
|
||||
|
||||
if (json)
|
||||
json_object_object_add(json, "importRts", json_import_rtl);
|
||||
else
|
||||
vty_out(vty, " Export Route Target:\n");
|
||||
|
||||
for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_export_rtl, node, nnode, ecom)) {
|
||||
ecom_str = ecommunity_ecom2str(ecom,
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
|
||||
if (json)
|
||||
json_object_array_add(json_export_rtl,
|
||||
json_object_new_string(ecom_str));
|
||||
else
|
||||
vty_out(vty, " %s\n", ecom_str);
|
||||
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
}
|
||||
|
||||
if (json)
|
||||
json_object_object_add(json, "exportRts", json_export_rtl);
|
||||
}
|
||||
|
||||
static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
|
||||
{
|
||||
char buf1[RD_ADDRSTRLEN];
|
||||
@ -348,6 +426,7 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
|
||||
json_import_rtl = json_object_new_array();
|
||||
json_export_rtl = json_object_new_array();
|
||||
json_object_int_add(json, "vni", vpn->vni);
|
||||
json_object_string_add(json, "type", "L2");
|
||||
json_object_string_add(json, "kernelFlag",
|
||||
is_vni_live(vpn) ? "Yes" : "No");
|
||||
json_object_string_add(
|
||||
@ -363,6 +442,7 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
|
||||
vty_out(vty, " (known to the kernel)");
|
||||
vty_out(vty, "\n");
|
||||
|
||||
vty_out(vty, " Type: %s\n", "L2");
|
||||
vty_out(vty, " Tenant-Vrf: %s\n",
|
||||
vrf_id_to_name(vpn->tenant_vrf_id));
|
||||
vty_out(vty, " RD: %s\n",
|
||||
@ -570,6 +650,110 @@ static void show_vni_routes_hash(struct hash_backet *backet, void *arg)
|
||||
json_object_object_add(json, vni_str, json_vni);
|
||||
}
|
||||
|
||||
static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
|
||||
json_object *json)
|
||||
{
|
||||
json_object *json_vni;
|
||||
json_object *json_import_rtl;
|
||||
json_object *json_export_rtl;
|
||||
char buf1[10];
|
||||
char buf2[INET6_ADDRSTRLEN];
|
||||
char rt_buf[25];
|
||||
char *ecom_str;
|
||||
struct listnode *node, *nnode;
|
||||
struct ecommunity *ecom;
|
||||
|
||||
if (!bgp->l3vni)
|
||||
return;
|
||||
|
||||
if (json) {
|
||||
json_vni = json_object_new_object();
|
||||
json_import_rtl = json_object_new_array();
|
||||
json_export_rtl = json_object_new_array();
|
||||
}
|
||||
|
||||
/* if an l3vni is present in bgp it is live */
|
||||
buf1[0] = '\0';
|
||||
sprintf(buf1, "*");
|
||||
|
||||
if (json) {
|
||||
json_object_int_add(json_vni, "vni", bgp->l3vni);
|
||||
json_object_string_add(json_vni, "type", "L3");
|
||||
json_object_string_add(json_vni, "inKernel", "True");
|
||||
json_object_string_add(json_vni, "originatorIp",
|
||||
inet_ntoa(bgp->originator_ip));
|
||||
json_object_string_add(
|
||||
json_vni, "rd",
|
||||
prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
|
||||
} else {
|
||||
vty_out(vty, "%-1s %-10u %-4s %-21s",
|
||||
buf1, bgp->l3vni, "L3",
|
||||
prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, ecom)) {
|
||||
ecom_str = ecommunity_ecom2str(ecom,
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
|
||||
if (json) {
|
||||
json_object_array_add(json_import_rtl,
|
||||
json_object_new_string(ecom_str));
|
||||
} else {
|
||||
if (listcount(bgp->vrf_import_rtl) > 1)
|
||||
sprintf(rt_buf, "%s, ...", ecom_str);
|
||||
else
|
||||
sprintf(rt_buf, "%s", ecom_str);
|
||||
vty_out(vty, " %-25s", rt_buf);
|
||||
}
|
||||
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
|
||||
/* If there are multiple import RTs we break here and show only
|
||||
* one */
|
||||
if (!json)
|
||||
break;
|
||||
}
|
||||
|
||||
if (json)
|
||||
json_object_object_add(json_vni, "importRTs", json_import_rtl);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode, ecom)) {
|
||||
ecom_str = ecommunity_ecom2str(ecom,
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
|
||||
if (json) {
|
||||
json_object_array_add(json_export_rtl,
|
||||
json_object_new_string(ecom_str));
|
||||
} else {
|
||||
if (listcount(bgp->vrf_export_rtl) > 1)
|
||||
sprintf(rt_buf, "%s, ...", ecom_str);
|
||||
else
|
||||
sprintf(rt_buf, "%s", ecom_str);
|
||||
vty_out(vty, " %-25s", rt_buf);
|
||||
}
|
||||
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
|
||||
/* If there are multiple export RTs we break here and show only
|
||||
* one */
|
||||
if (!json)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!json)
|
||||
vty_out(vty, "%-37s", vrf_id_to_name(bgp->vrf_id));
|
||||
|
||||
if (json) {
|
||||
char vni_str[VNI_STR_LEN];
|
||||
|
||||
json_object_object_add(json_vni, "exportRTs", json_export_rtl);
|
||||
snprintf(vni_str, VNI_STR_LEN, "%u", bgp->l3vni);
|
||||
json_object_object_add(json, vni_str, json_vni);
|
||||
} else {
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void show_vni_entry(struct hash_backet *backet, void *args[])
|
||||
{
|
||||
struct vty *vty;
|
||||
@ -600,16 +784,19 @@ static void show_vni_entry(struct hash_backet *backet, void *args[])
|
||||
|
||||
if (json) {
|
||||
json_object_int_add(json_vni, "vni", vpn->vni);
|
||||
json_object_string_add(json_vni, "type", "L2");
|
||||
json_object_string_add(json_vni, "inKernel",
|
||||
is_vni_live(vpn) ? "True" : "False");
|
||||
json_object_string_add(json_vni, "originatorIp",
|
||||
inet_ntoa(vpn->originator_ip));
|
||||
json_object_string_add(json_vni, "originatorIp",
|
||||
inet_ntoa(vpn->originator_ip));
|
||||
json_object_string_add(
|
||||
json_vni, "rd",
|
||||
prefix_rd2str(&vpn->prd, buf2, sizeof(buf2)));
|
||||
} else {
|
||||
vty_out(vty, "%-1s %-10u %-15s %-21s", buf1, vpn->vni,
|
||||
inet_ntoa(vpn->originator_ip),
|
||||
vty_out(vty, "%-1s %-10u %-4s %-21s",
|
||||
buf1, vpn->vni, "L2",
|
||||
prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
|
||||
}
|
||||
|
||||
@ -1982,7 +2169,7 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
|
||||
vty_out(vty,
|
||||
"EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
|
||||
vty_out(vty,
|
||||
"EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
|
||||
"EVPN type-5 prefix: [5]:[ESI]:[EthTag]:[IPlen]:[IP]\n\n");
|
||||
rd_header = 0;
|
||||
}
|
||||
|
||||
@ -2181,10 +2368,26 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
|
||||
static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
|
||||
json_object *json)
|
||||
{
|
||||
u_char found = 0;
|
||||
struct bgpevpn *vpn;
|
||||
|
||||
vpn = bgp_evpn_lookup_vni(bgp, vni);
|
||||
if (!vpn) {
|
||||
if (vpn) {
|
||||
found = 1;
|
||||
display_vni(vty, vpn, json);
|
||||
} else {
|
||||
struct bgp *bgp_temp;
|
||||
struct listnode *node = NULL;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
|
||||
if (bgp_temp->l3vni == vni) {
|
||||
found = 1;
|
||||
display_l3vni(vty, bgp_temp, json);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (json) {
|
||||
vty_out(vty, "{}\n");
|
||||
} else {
|
||||
@ -2192,8 +2395,6 @@ static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
display_vni(vty, vpn, json);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2202,28 +2403,29 @@ static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
|
||||
static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
|
||||
json_object *json)
|
||||
{
|
||||
u_int32_t num_vnis;
|
||||
void *args[2];
|
||||
struct bgp *bgp_temp = NULL;
|
||||
struct listnode *node;
|
||||
|
||||
num_vnis = hashcount(bgp->vnihash);
|
||||
if (!num_vnis)
|
||||
return;
|
||||
|
||||
if (json) {
|
||||
json_object_int_add(json, "numVnis", num_vnis);
|
||||
} else {
|
||||
vty_out(vty, "Number of VNIs: %u\n", num_vnis);
|
||||
if (!json) {
|
||||
vty_out(vty, "Flags: * - Kernel\n");
|
||||
vty_out(vty, " %-10s %-15s %-21s %-25s %-25s %-37s\n", "VNI",
|
||||
"Orig IP", "RD", "Import RT",
|
||||
"Export RT", "Tenant-Vrf");
|
||||
vty_out(vty, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
|
||||
"Type", "RD", "Import RT",
|
||||
"Export RT", "Tenant VRF");
|
||||
}
|
||||
|
||||
/* print all L2 VNIS */
|
||||
args[0] = vty;
|
||||
args[1] = json;
|
||||
hash_iterate(bgp->vnihash,
|
||||
(void (*)(struct hash_backet *, void *))show_vni_entry,
|
||||
args);
|
||||
|
||||
/* print all L3 VNIs */
|
||||
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp))
|
||||
show_l3vni_entry(vty, bgp_temp, json);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2271,6 +2473,32 @@ static void evpn_unset_advertise_default_gw(struct bgp *bgp,
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* evpn - enable advertisement of default g/w
|
||||
*/
|
||||
static void evpn_set_advertise_subnet(struct bgp *bgp,
|
||||
struct bgpevpn *vpn)
|
||||
{
|
||||
if (vpn->advertise_subnet)
|
||||
return;
|
||||
|
||||
vpn->advertise_subnet = 1;
|
||||
bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
|
||||
}
|
||||
|
||||
/*
|
||||
* evpn - disable advertisement of default g/w
|
||||
*/
|
||||
static void evpn_unset_advertise_subnet(struct bgp *bgp,
|
||||
struct bgpevpn *vpn)
|
||||
{
|
||||
if (!vpn->advertise_subnet)
|
||||
return;
|
||||
|
||||
vpn->advertise_subnet = 0;
|
||||
bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
|
||||
}
|
||||
|
||||
/*
|
||||
* EVPN (VNI advertisement) enabled. Register with zebra.
|
||||
*/
|
||||
@ -2330,6 +2558,9 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
|
||||
if (vpn->advertise_gw_macip)
|
||||
vty_out(vty, " advertise-default-gw\n");
|
||||
|
||||
if (vpn->advertise_subnet)
|
||||
vty_out(vty, " advertise-subnet\n");
|
||||
|
||||
vty_out(vty, " exit-vni\n");
|
||||
}
|
||||
}
|
||||
@ -2440,6 +2671,56 @@ DEFUN (no_bgp_evpn_advertise_all_vni,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (bgp_evpn_advertise_vni_subnet,
|
||||
bgp_evpn_advertise_vni_subnet_cmd,
|
||||
"advertise-subnet",
|
||||
"Advertise the subnet corresponding to VNI\n")
|
||||
{
|
||||
struct bgp *bgp_vrf = NULL;
|
||||
struct bgp *bgp = VTY_GET_CONTEXT(bgp);
|
||||
VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
|
||||
|
||||
if (!bgp)
|
||||
return CMD_WARNING;
|
||||
|
||||
if (!vpn)
|
||||
return CMD_WARNING;
|
||||
|
||||
bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
|
||||
if (!bgp_vrf)
|
||||
return CMD_WARNING;
|
||||
|
||||
if (!(advertise_type5_routes(bgp_vrf, AFI_IP) ||
|
||||
advertise_type5_routes(bgp_vrf, AFI_IP6))) {
|
||||
vty_out(vty,
|
||||
"%%Please enable ip prefix advertisement under l2vpn evpn in %s",
|
||||
vrf_id_to_name(bgp_vrf->vrf_id));
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
evpn_set_advertise_subnet(bgp, vpn);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_bgp_evpn_advertise_vni_subnet,
|
||||
no_bgp_evpn_advertise_vni_subnet_cmd,
|
||||
"no advertise-subnet",
|
||||
NO_STR
|
||||
"Advertise All local VNIs\n")
|
||||
{
|
||||
struct bgp *bgp = VTY_GET_CONTEXT(bgp);
|
||||
VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
|
||||
|
||||
if (!bgp)
|
||||
return CMD_WARNING;
|
||||
|
||||
if (!vpn)
|
||||
return CMD_WARNING;
|
||||
|
||||
evpn_unset_advertise_subnet(bgp, vpn);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (bgp_evpn_advertise_type5,
|
||||
bgp_evpn_advertise_type5_cmd,
|
||||
"advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR,
|
||||
@ -2563,16 +2844,21 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
|
||||
"VNI number\n"
|
||||
JSON_STR)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
struct bgp *bgp_def;
|
||||
vni_t vni;
|
||||
int idx = 0;
|
||||
u_char uj = 0;
|
||||
json_object *json = NULL;
|
||||
u_int32_t num_l2vnis = 0;
|
||||
u_int32_t num_l3vnis = 0;
|
||||
uint32_t num_vnis = 0;
|
||||
struct listnode *node = NULL;
|
||||
struct bgp *bgp_temp = NULL;
|
||||
|
||||
uj = use_json(argc, argv);
|
||||
|
||||
bgp = bgp_get_default();
|
||||
if (!bgp)
|
||||
bgp_def = bgp_get_default();
|
||||
if (!bgp_def)
|
||||
return CMD_WARNING;
|
||||
|
||||
if (!argv_find(argv, argc, "evpn", &idx))
|
||||
@ -2582,26 +2868,36 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
|
||||
json = json_object_new_object();
|
||||
|
||||
if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
|
||||
|
||||
num_l2vnis = hashcount(bgp_def->vnihash);
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
|
||||
if (bgp_temp->l3vni)
|
||||
num_l3vnis++;
|
||||
}
|
||||
num_vnis = num_l2vnis + num_l3vnis;
|
||||
if (uj) {
|
||||
json_object_string_add(json, "advertiseGatewayMacip",
|
||||
bgp->advertise_gw_macip
|
||||
bgp_def->advertise_gw_macip
|
||||
? "Enabled"
|
||||
: "Disabled");
|
||||
json_object_string_add(json, "advertiseAllVnis",
|
||||
is_evpn_enabled()
|
||||
? "Enabled"
|
||||
: "Disabled");
|
||||
json_object_int_add(json, "numVnis", num_vnis);
|
||||
json_object_int_add(json, "numL2Vnis", num_l2vnis);
|
||||
json_object_int_add(json, "numL3Vnis", num_l3vnis);
|
||||
} else {
|
||||
vty_out(vty, "Advertise Gateway Macip: %s\n",
|
||||
bgp->advertise_gw_macip ? "Enabled"
|
||||
bgp_def->advertise_gw_macip ? "Enabled"
|
||||
: "Disabled");
|
||||
|
||||
/* Display all VNIs */
|
||||
vty_out(vty, "Advertise All VNI flag: %s\n",
|
||||
is_evpn_enabled() ? "Enabled" : "Disabled");
|
||||
vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
|
||||
vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
|
||||
}
|
||||
|
||||
evpn_show_all_vnis(vty, bgp, json);
|
||||
evpn_show_all_vnis(vty, bgp_def, json);
|
||||
} else {
|
||||
int vni_idx = 0;
|
||||
|
||||
@ -2610,7 +2906,7 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
|
||||
|
||||
/* Display specific VNI */
|
||||
vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
|
||||
evpn_show_vni(vty, bgp, vni, json);
|
||||
evpn_show_vni(vty, bgp_def, vni, json);
|
||||
}
|
||||
|
||||
if (uj) {
|
||||
@ -2644,7 +2940,7 @@ DEFUN(show_bgp_l2vpn_evpn_summary,
|
||||
*/
|
||||
DEFUN(show_bgp_l2vpn_evpn_route,
|
||||
show_bgp_l2vpn_evpn_route_cmd,
|
||||
"show bgp l2vpn evpn route [type <macip|multicast>] [json]",
|
||||
"show bgp l2vpn evpn route [type <macip|multicast|prefix>] [json]",
|
||||
SHOW_STR
|
||||
BGP_STR
|
||||
L2VPN_HELP_STR
|
||||
@ -2653,6 +2949,7 @@ DEFUN(show_bgp_l2vpn_evpn_route,
|
||||
"Specify Route type\n"
|
||||
"MAC-IP (Type-2) route\n"
|
||||
"Multicast (Type-3) route\n"
|
||||
"Prefix route\n"
|
||||
JSON_STR)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
@ -2677,6 +2974,8 @@ DEFUN(show_bgp_l2vpn_evpn_route,
|
||||
type = BGP_EVPN_MAC_IP_ROUTE;
|
||||
else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
|
||||
type = BGP_EVPN_IMET_ROUTE;
|
||||
else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
|
||||
type = BGP_EVPN_IP_PREFIX_ROUTE;
|
||||
else
|
||||
return CMD_WARNING;
|
||||
}
|
||||
@ -2688,7 +2987,6 @@ DEFUN(show_bgp_l2vpn_evpn_route,
|
||||
json, JSON_C_TO_STRING_PRETTY));
|
||||
json_object_free(json);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2697,7 +2995,7 @@ DEFUN(show_bgp_l2vpn_evpn_route,
|
||||
*/
|
||||
DEFUN(show_bgp_l2vpn_evpn_route_rd,
|
||||
show_bgp_l2vpn_evpn_route_rd_cmd,
|
||||
"show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>] [json]",
|
||||
"show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|prefix>] [json]",
|
||||
SHOW_STR
|
||||
BGP_STR
|
||||
L2VPN_HELP_STR
|
||||
@ -2708,6 +3006,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd,
|
||||
"Specify Route type\n"
|
||||
"MAC-IP (Type-2) route\n"
|
||||
"Multicast (Type-3) route\n"
|
||||
"Prefix route\n"
|
||||
JSON_STR)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
@ -2745,6 +3044,8 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd,
|
||||
type = BGP_EVPN_MAC_IP_ROUTE;
|
||||
else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
|
||||
type = BGP_EVPN_IMET_ROUTE;
|
||||
else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
|
||||
type = BGP_EVPN_IP_PREFIX_ROUTE;
|
||||
else
|
||||
return CMD_WARNING;
|
||||
}
|
||||
@ -3544,13 +3845,12 @@ static int bgp_evpn_rt_matches_existing(struct list *rtl,
|
||||
/* display L3VNI related info for a VRF instance */
|
||||
DEFUN (show_bgp_vrf_l3vni_info,
|
||||
show_bgp_vrf_l3vni_info_cmd,
|
||||
"show bgp vrf VRFNAME l3vni info [json]",
|
||||
"show bgp vrf VRFNAME vni [json]",
|
||||
SHOW_STR
|
||||
BGP_STR
|
||||
"show bgp vrf\n"
|
||||
"VRF Name\n"
|
||||
"L3-VNI\n"
|
||||
"L3-VNI info\n"
|
||||
JSON_STR)
|
||||
{
|
||||
char buf[ETHER_ADDR_STRLEN];
|
||||
@ -4118,5 +4418,8 @@ void bgp_ethernetvpn_init(void)
|
||||
&bgp_evpn_advertise_default_gw_vni_cmd);
|
||||
install_element(BGP_EVPN_VNI_NODE,
|
||||
&no_bgp_evpn_advertise_default_gw_vni_cmd);
|
||||
install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
|
||||
install_element(BGP_EVPN_VNI_NODE,
|
||||
&no_bgp_evpn_advertise_vni_subnet_cmd);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri,
|
||||
if (!rn || !ri || !to)
|
||||
return MPLS_INVALID_LABEL;
|
||||
|
||||
remote_label = ri->extra ? ri->extra->label : MPLS_INVALID_LABEL;
|
||||
remote_label = ri->extra ? ri->extra->label[0] : MPLS_INVALID_LABEL;
|
||||
from = ri->peer;
|
||||
reflect =
|
||||
((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));
|
||||
@ -325,11 +325,11 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
|
||||
if (attr) {
|
||||
bgp_update(peer, &p, addpath_id, attr, packet->afi,
|
||||
SAFI_UNICAST, ZEBRA_ROUTE_BGP,
|
||||
BGP_ROUTE_NORMAL, NULL, &label, 0, NULL);
|
||||
BGP_ROUTE_NORMAL, NULL, &label, 1, 0, NULL);
|
||||
} else {
|
||||
bgp_withdraw(peer, &p, addpath_id, attr, packet->afi,
|
||||
SAFI_UNICAST, ZEBRA_ROUTE_BGP,
|
||||
BGP_ROUTE_NORMAL, NULL, &label, NULL);
|
||||
BGP_ROUTE_NORMAL, NULL, &label, 1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -214,11 +214,11 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
|
||||
if (attr) {
|
||||
bgp_update(peer, &p, addpath_id, attr, packet->afi,
|
||||
SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP,
|
||||
BGP_ROUTE_NORMAL, &prd, &label, 0, NULL);
|
||||
BGP_ROUTE_NORMAL, &prd, &label, 1, 0, NULL);
|
||||
} else {
|
||||
bgp_withdraw(peer, &p, addpath_id, attr, packet->afi,
|
||||
SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP,
|
||||
BGP_ROUTE_NORMAL, &prd, &label, NULL);
|
||||
BGP_ROUTE_NORMAL, &prd, &label, 1, NULL);
|
||||
}
|
||||
}
|
||||
/* Packet length consistency check. */
|
||||
@ -366,8 +366,8 @@ int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
|
||||
return CMD_WARNING;
|
||||
}
|
||||
table = bgp->rib[afi][SAFI_MPLS_VPN];
|
||||
return bgp_show_table_rd(vty, bgp, SAFI_MPLS_VPN,
|
||||
table, prd, type, output_arg, use_json);
|
||||
return bgp_show_table_rd(vty, bgp, SAFI_MPLS_VPN, table, prd, type,
|
||||
output_arg, use_json);
|
||||
}
|
||||
|
||||
DEFUN (show_bgp_ip_vpn_all_rd,
|
||||
@ -389,7 +389,7 @@ DEFUN (show_bgp_ip_vpn_all_rd,
|
||||
|
||||
if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
|
||||
if (argv_find(argv, argc, "rd", &idx)) {
|
||||
ret = str2prefix_rd(argv[idx+1]->arg, &prd);
|
||||
ret = str2prefix_rd(argv[idx + 1]->arg, &prd);
|
||||
if (!ret) {
|
||||
vty_out(vty,
|
||||
"%% Malformed Route Distinguisher\n");
|
||||
|
||||
@ -24,30 +24,6 @@
|
||||
#include "bgpd/bgp_route.h"
|
||||
#include "bgpd/bgp_rd.h"
|
||||
|
||||
#ifdef MPLS_LABEL_MAX
|
||||
#undef MPLS_LABEL_MAX
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
MPLS_LABEL_IPV4_EXPLICIT_NULL = 0, /* [RFC3032] */
|
||||
MPLS_LABEL_ROUTER_ALERT = 1, /* [RFC3032] */
|
||||
MPLS_LABEL_IPV6_EXPLICIT_NULL = 2, /* [RFC3032] */
|
||||
MPLS_LABEL_IMPLICIT_NULL = 3, /* [RFC3032] */
|
||||
MPLS_LABEL_UNASSIGNED4 = 4,
|
||||
MPLS_LABEL_UNASSIGNED5 = 5,
|
||||
MPLS_LABEL_UNASSIGNED6 = 6,
|
||||
MPLS_LABEL_ELI = 7, /* Entropy Indicator [RFC6790] */
|
||||
MPLS_LABEL_UNASSIGNED8 = 8,
|
||||
MPLS_LABEL_UNASSIGNED9 = 9,
|
||||
MPLS_LABEL_UNASSIGNED10 = 10,
|
||||
MPLS_LABEL_UNASSIGNED11 = 11,
|
||||
MPLS_LABEL_GAL = 13, /* [RFC5586] */
|
||||
MPLS_LABEL_OAM_ALERT = 14, /* [RFC3429] */
|
||||
MPLS_LABEL_EXTENSION = 15, /* [RFC7274] */
|
||||
MPLS_LABEL_MAX = 1048575,
|
||||
MPLS_LABEL_ILLEGAL = 0xFFFFFFFF /* for internal use only */
|
||||
} mpls_special_label_t;
|
||||
|
||||
#define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION)
|
||||
#define MPLS_LABEL_IS_NULL(label) \
|
||||
((label) == MPLS_LABEL_IPV4_EXPLICIT_NULL \
|
||||
|
||||
560
bgpd/bgp_route.c
560
bgpd/bgp_route.c
File diff suppressed because it is too large
Load Diff
@ -59,6 +59,11 @@ enum bgp_show_type {
|
||||
#define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"
|
||||
#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path\n"
|
||||
|
||||
/* Maximum number of labels we can process or send with a prefix. We
|
||||
* really do only 1 for MPLS (BGP-LU) but we can do 2 for EVPN-VxLAN.
|
||||
*/
|
||||
#define BGP_MAX_LABELS 2
|
||||
|
||||
/* Ancillary information to struct bgp_info,
|
||||
* used for uncommonly used data (aggregation, MPLS, etc.)
|
||||
* and lazily allocated to save memory.
|
||||
@ -73,11 +78,9 @@ struct bgp_info_extra {
|
||||
/* Nexthop reachability check. */
|
||||
u_int32_t igpmetric;
|
||||
|
||||
/* MPLS label - L2VNI */
|
||||
mpls_label_t label;
|
||||
|
||||
/* MPLS label - L3-VNI */
|
||||
mpls_label_t label2;
|
||||
/* MPLS label(s) - VNI(s) for EVPN-VxLAN */
|
||||
mpls_label_t label[BGP_MAX_LABELS];
|
||||
u_int32_t num_labels;
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
union {
|
||||
@ -360,10 +363,10 @@ extern int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *,
|
||||
/* this is primarily for MPLS-VPN */
|
||||
extern int bgp_update(struct peer *, struct prefix *, u_int32_t, struct attr *,
|
||||
afi_t, safi_t, int, int, struct prefix_rd *,
|
||||
mpls_label_t *, int, struct bgp_route_evpn *);
|
||||
mpls_label_t *, u_int32_t, int, struct bgp_route_evpn *);
|
||||
extern int bgp_withdraw(struct peer *, struct prefix *, u_int32_t,
|
||||
struct attr *, afi_t, safi_t, int, int,
|
||||
struct prefix_rd *, mpls_label_t *,
|
||||
struct prefix_rd *, mpls_label_t *, u_int32_t,
|
||||
struct bgp_route_evpn *);
|
||||
|
||||
/* for bgp_nexthop and bgp_damp */
|
||||
|
||||
@ -618,8 +618,7 @@ static route_map_result_t route_match_mac_address(void *rule,
|
||||
p.prefixlen = ETH_ALEN * 8;
|
||||
p.u.prefix_eth = prefix->u.prefix_evpn.mac;
|
||||
|
||||
return (access_list_apply(alist, &p)
|
||||
== FILTER_DENY
|
||||
return (access_list_apply(alist, &p) == FILTER_DENY
|
||||
? RMAP_NOMATCH
|
||||
: RMAP_MATCH);
|
||||
}
|
||||
@ -659,7 +658,7 @@ static route_map_result_t route_match_vni(void *rule, struct prefix *prefix,
|
||||
vni = *((vni_t *)rule);
|
||||
bgp_info = (struct bgp_info *)object;
|
||||
|
||||
if (vni == label2vni(&bgp_info->extra->label))
|
||||
if (vni == label2vni(&bgp_info->extra->label[0]))
|
||||
return RMAP_MATCH;
|
||||
}
|
||||
|
||||
@ -696,6 +695,56 @@ struct route_map_rule_cmd route_match_evpn_vni_cmd = {
|
||||
"evpn vni", route_match_vni, route_match_vni_compile,
|
||||
route_match_vni_free};
|
||||
|
||||
/* `match evpn route-type' */
|
||||
|
||||
/* Match function should return 1 if match is success else return
|
||||
zero. */
|
||||
static route_map_result_t route_match_evpn_route_type(void *rule,
|
||||
struct prefix *prefix,
|
||||
route_map_object_t type,
|
||||
void *object)
|
||||
{
|
||||
u_char route_type = 0;
|
||||
|
||||
if (type == RMAP_BGP) {
|
||||
route_type = *((u_char *)rule);
|
||||
|
||||
if (route_type == prefix->u.prefix_evpn.route_type)
|
||||
return RMAP_MATCH;
|
||||
}
|
||||
|
||||
return RMAP_NOMATCH;
|
||||
}
|
||||
|
||||
/* Route map `route-type' match statement. */
|
||||
static void *route_match_evpn_route_type_compile(const char *arg)
|
||||
{
|
||||
u_char *route_type = NULL;
|
||||
|
||||
route_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_char));
|
||||
|
||||
if (strncmp(arg, "ma", 2) == 0)
|
||||
*route_type = BGP_EVPN_MAC_IP_ROUTE;
|
||||
else if (strncmp(arg, "mu", 2) == 0)
|
||||
*route_type = BGP_EVPN_IMET_ROUTE;
|
||||
else
|
||||
*route_type = BGP_EVPN_IP_PREFIX_ROUTE;
|
||||
|
||||
return route_type;
|
||||
}
|
||||
|
||||
/* Free route map's compiled `route-type' value. */
|
||||
static void route_match_evpn_route_type_free(void *rule)
|
||||
{
|
||||
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||
}
|
||||
|
||||
/* Route map commands for evpn route-type matching. */
|
||||
struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
|
||||
"evpn route-type", route_match_evpn_route_type,
|
||||
route_match_evpn_route_type_compile,
|
||||
route_match_evpn_route_type_free};
|
||||
|
||||
/* `match local-preference LOCAL-PREF' */
|
||||
|
||||
/* Match function return 1 if match is success else return zero. */
|
||||
@ -3132,6 +3181,36 @@ DEFUN (no_match_mac_address,
|
||||
RMAP_EVENT_FILTER_DELETED);
|
||||
}
|
||||
|
||||
DEFUN (match_evpn_route_type,
|
||||
match_evpn_route_type_cmd,
|
||||
"match evpn route-type <macip | multicast | prefix>",
|
||||
MATCH_STR
|
||||
EVPN_HELP_STR
|
||||
"Match route-type\n"
|
||||
"mac-ip route\n"
|
||||
"IMET route\n"
|
||||
"prefix route\n")
|
||||
{
|
||||
return bgp_route_match_add(vty, "evpn route-type", argv[3]->arg,
|
||||
RMAP_EVENT_MATCH_ADDED);
|
||||
}
|
||||
|
||||
DEFUN (no_match_evpn_route_type,
|
||||
no_match_evpn_route_type_cmd,
|
||||
"no match evpn route-type <macip | multicast | prefix>",
|
||||
NO_STR
|
||||
MATCH_STR
|
||||
EVPN_HELP_STR
|
||||
"Match route-type\n"
|
||||
"mac-ip route\n"
|
||||
"IMET route\n"
|
||||
"prefix route\n")
|
||||
{
|
||||
return bgp_route_match_delete(vty, "evpn route-type", argv[4]->arg,
|
||||
RMAP_EVENT_MATCH_DELETED);
|
||||
}
|
||||
|
||||
|
||||
DEFUN (match_evpn_vni,
|
||||
match_evpn_vni_cmd,
|
||||
"match evpn vni (1-16777215)",
|
||||
@ -3519,9 +3598,9 @@ DEFUN (set_ip_nexthop_peer,
|
||||
"Use peer address (for BGP only)\n")
|
||||
{
|
||||
int (*func)(struct vty *, struct route_map_index *, const char *,
|
||||
const char *) = strmatch(argv[0]->text, "no")
|
||||
? generic_set_delete
|
||||
: generic_set_add;
|
||||
const char *) = strmatch(argv[0]->text, "no")
|
||||
? generic_set_delete
|
||||
: generic_set_add;
|
||||
|
||||
return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
|
||||
"peer-address");
|
||||
@ -3537,9 +3616,9 @@ DEFUN (set_ip_nexthop_unchanged,
|
||||
"Don't modify existing Next hop address\n")
|
||||
{
|
||||
int (*func)(struct vty *, struct route_map_index *, const char *,
|
||||
const char *) = strmatch(argv[0]->text, "no")
|
||||
? generic_set_delete
|
||||
: generic_set_add;
|
||||
const char *) = strmatch(argv[0]->text, "no")
|
||||
? generic_set_delete
|
||||
: generic_set_add;
|
||||
|
||||
return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
|
||||
"unchanged");
|
||||
@ -3780,7 +3859,8 @@ DEFUN (set_community,
|
||||
buffer_putstr(b, "no-export");
|
||||
continue;
|
||||
}
|
||||
if (strncmp(argv[i]->arg, "graceful-shutdown", strlen(argv[i]->arg))
|
||||
if (strncmp(argv[i]->arg, "graceful-shutdown",
|
||||
strlen(argv[i]->arg))
|
||||
== 0) {
|
||||
buffer_putstr(b, "graceful-shutdown");
|
||||
continue;
|
||||
@ -4534,6 +4614,7 @@ void bgp_route_map_init(void)
|
||||
route_map_install_match(&route_match_tag_cmd);
|
||||
route_map_install_match(&route_match_mac_address_cmd);
|
||||
route_map_install_match(&route_match_evpn_vni_cmd);
|
||||
route_map_install_match(&route_match_evpn_route_type_cmd);
|
||||
|
||||
route_map_install_set(&route_set_ip_nexthop_cmd);
|
||||
route_map_install_set(&route_set_local_pref_cmd);
|
||||
@ -4568,6 +4649,8 @@ void bgp_route_map_init(void)
|
||||
install_element(RMAP_NODE, &no_match_mac_address_cmd);
|
||||
install_element(RMAP_NODE, &match_evpn_vni_cmd);
|
||||
install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
|
||||
install_element(RMAP_NODE, &match_evpn_route_type_cmd);
|
||||
install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
|
||||
|
||||
install_element(RMAP_NODE, &match_aspath_cmd);
|
||||
install_element(RMAP_NODE, &no_match_aspath_cmd);
|
||||
|
||||
@ -701,7 +701,8 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
int addpath_overhead = 0;
|
||||
u_int32_t addpath_tx_id = 0;
|
||||
struct prefix_rd *prd = NULL;
|
||||
mpls_label_t label = MPLS_INVALID_LABEL;
|
||||
mpls_label_t label = MPLS_INVALID_LABEL, *label_pnt = NULL;
|
||||
u_int32_t num_labels = 0;
|
||||
|
||||
if (!subgrp)
|
||||
return NULL;
|
||||
@ -772,7 +773,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
* attr. */
|
||||
total_attr_len = bgp_packet_attribute(
|
||||
NULL, peer, s, adv->baa->attr, &vecarr, NULL,
|
||||
afi, safi, from, NULL, NULL, 0, 0);
|
||||
afi, safi, from, NULL, NULL, 0, 0, 0);
|
||||
|
||||
space_remaining =
|
||||
STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s))
|
||||
@ -815,11 +816,15 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
if (rn->prn)
|
||||
prd = (struct prefix_rd *)&rn->prn->p;
|
||||
|
||||
if (safi == SAFI_LABELED_UNICAST)
|
||||
if (safi == SAFI_LABELED_UNICAST) {
|
||||
label = bgp_adv_label(rn, binfo, peer, afi,
|
||||
safi);
|
||||
else if (binfo && binfo->extra)
|
||||
label = binfo->extra->label;
|
||||
label_pnt = &label;
|
||||
num_labels = 1;
|
||||
} else if (binfo && binfo->extra) {
|
||||
label_pnt = &binfo->extra->label[0];
|
||||
num_labels = binfo->extra->num_labels;
|
||||
}
|
||||
|
||||
if (stream_empty(snlri))
|
||||
mpattrlen_pos = bgp_packet_mpattr_start(
|
||||
@ -827,8 +832,9 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
adv->baa->attr);
|
||||
|
||||
bgp_packet_mpattr_prefix(snlri, afi, safi, &rn->p, prd,
|
||||
&label, addpath_encode,
|
||||
addpath_tx_id, adv->baa->attr);
|
||||
label_pnt, num_labels,
|
||||
addpath_encode, addpath_tx_id,
|
||||
adv->baa->attr);
|
||||
}
|
||||
|
||||
num_pfx++;
|
||||
@ -857,7 +863,8 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
send_attr_printed = 1;
|
||||
}
|
||||
|
||||
bgp_debug_rdpfxpath2str(afi, safi, prd, &rn->p, &label,
|
||||
bgp_debug_rdpfxpath2str(afi, safi, prd, &rn->p,
|
||||
label_pnt, num_labels,
|
||||
addpath_encode, addpath_tx_id,
|
||||
pfx_buf, sizeof(pfx_buf));
|
||||
zlog_debug("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s",
|
||||
@ -1009,7 +1016,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp)
|
||||
}
|
||||
|
||||
bgp_packet_mpunreach_prefix(s, &rn->p, afi, safi, prd,
|
||||
NULL, addpath_encode,
|
||||
NULL, 0, addpath_encode,
|
||||
addpath_tx_id, NULL);
|
||||
}
|
||||
|
||||
@ -1018,7 +1025,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp)
|
||||
if (bgp_debug_update(NULL, &rn->p, subgrp->update_group, 0)) {
|
||||
char pfx_buf[BGP_PRD_PATH_STRLEN];
|
||||
|
||||
bgp_debug_rdpfxpath2str(afi, safi, prd, &rn->p, NULL,
|
||||
bgp_debug_rdpfxpath2str(afi, safi, prd, &rn->p, NULL, 0,
|
||||
addpath_encode, addpath_tx_id,
|
||||
pfx_buf, sizeof(pfx_buf));
|
||||
zlog_debug("u%" PRIu64 ":s%" PRIu64
|
||||
@ -1132,7 +1139,7 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp,
|
||||
stream_putw(s, 0);
|
||||
total_attr_len = bgp_packet_attribute(
|
||||
NULL, peer, s, attr, &vecarr, &p, afi, safi, from, NULL, NULL,
|
||||
addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
|
||||
0, addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
|
||||
|
||||
/* Set Total Path Attribute Length. */
|
||||
stream_putw_at(s, pos, total_attr_len);
|
||||
@ -1227,7 +1234,7 @@ void subgroup_default_withdraw_packet(struct update_subgroup *subgrp)
|
||||
mp_start = stream_get_endp(s);
|
||||
mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
|
||||
bgp_packet_mpunreach_prefix(
|
||||
s, &p, afi, safi, NULL, NULL, addpath_encode,
|
||||
s, &p, afi, safi, NULL, NULL, 0, addpath_encode,
|
||||
BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, NULL);
|
||||
|
||||
/* Set the mp_unreach attr's length */
|
||||
|
||||
188
bgpd/bgp_vty.c
188
bgpd/bgp_vty.c
@ -1540,7 +1540,8 @@ DEFUN (no_bgp_maxpaths,
|
||||
}
|
||||
|
||||
ALIAS_HIDDEN(no_bgp_maxpaths, no_bgp_maxpaths_hidden_cmd,
|
||||
"no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM) "]", NO_STR
|
||||
"no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM) "]",
|
||||
NO_STR
|
||||
"Forward packets over multiple paths\n"
|
||||
"Number of paths\n")
|
||||
|
||||
@ -1868,14 +1869,14 @@ static void bgp_redistribute_redo(struct bgp *bgp)
|
||||
struct listnode *node;
|
||||
struct bgp_redist *red;
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
|
||||
red_list = bgp->redist[afi][i];
|
||||
if (!red_list)
|
||||
continue;
|
||||
red_list = bgp->redist[afi][i];
|
||||
if (!red_list)
|
||||
continue;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
|
||||
for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
|
||||
bgp_redistribute_resend(bgp, afi, i,
|
||||
red->instance);
|
||||
}
|
||||
@ -4363,23 +4364,23 @@ DEFUN (neighbor_attr_unchanged,
|
||||
SET_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED);
|
||||
SET_FLAG(flags, PEER_FLAG_MED_UNCHANGED);
|
||||
} else {
|
||||
if (!CHECK_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED) &&
|
||||
peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_AS_PATH_UNCHANGED)) {
|
||||
if (!CHECK_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED)
|
||||
&& peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_AS_PATH_UNCHANGED)) {
|
||||
peer_af_flag_unset_vty(vty, peer_str, afi, safi,
|
||||
PEER_FLAG_AS_PATH_UNCHANGED);
|
||||
}
|
||||
|
||||
if (!CHECK_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED) &&
|
||||
peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_NEXTHOP_UNCHANGED)) {
|
||||
if (!CHECK_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED)
|
||||
&& peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_NEXTHOP_UNCHANGED)) {
|
||||
peer_af_flag_unset_vty(vty, peer_str, afi, safi,
|
||||
PEER_FLAG_NEXTHOP_UNCHANGED);
|
||||
}
|
||||
|
||||
if (!CHECK_FLAG(flags, PEER_FLAG_MED_UNCHANGED) &&
|
||||
peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_MED_UNCHANGED)) {
|
||||
if (!CHECK_FLAG(flags, PEER_FLAG_MED_UNCHANGED)
|
||||
&& peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_MED_UNCHANGED)) {
|
||||
peer_af_flag_unset_vty(vty, peer_str, afi, safi,
|
||||
PEER_FLAG_MED_UNCHANGED);
|
||||
}
|
||||
@ -6125,9 +6126,11 @@ DEFUN_NOSH (address_family_ipv4_safi,
|
||||
if (argc == 3) {
|
||||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||
safi_t safi = bgp_vty_safi_from_str(argv[2]->text);
|
||||
if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT &&
|
||||
safi != SAFI_UNICAST && safi != SAFI_MULTICAST) {
|
||||
vty_out(vty, "Only Unicast and Multicast SAFIs supported in non-core instances.\n");
|
||||
if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT
|
||||
&& safi != SAFI_UNICAST && safi != SAFI_MULTICAST
|
||||
&& safi != SAFI_EVPN) {
|
||||
vty_out(vty,
|
||||
"Only Unicast/Multicast/EVPN SAFIs supported in non-core instances.\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
vty->node = bgp_node_type(AFI_IP, safi);
|
||||
@ -6147,9 +6150,11 @@ DEFUN_NOSH (address_family_ipv6_safi,
|
||||
if (argc == 3) {
|
||||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||
safi_t safi = bgp_vty_safi_from_str(argv[2]->text);
|
||||
if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT &&
|
||||
safi != SAFI_UNICAST && safi != SAFI_MULTICAST) {
|
||||
vty_out(vty, "Only Unicast and Multicast SAFIs supported in non-core instances.\n");
|
||||
if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT
|
||||
&& safi != SAFI_UNICAST && safi != SAFI_MULTICAST
|
||||
&& safi != SAFI_EVPN) {
|
||||
vty_out(vty,
|
||||
"Only Unicast/Multicast/EVPN SAFIs supported in non-core instances.\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
vty->node = bgp_node_type(AFI_IP6, safi);
|
||||
@ -6191,10 +6196,6 @@ DEFUN_NOSH (address_family_evpn,
|
||||
"Address Family modifier\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||
if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
|
||||
vty_out(vty, "Only Unicast and Multicast SAFIs supported in non-core instances.\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
vty->node = BGP_EVPN_NODE;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -6511,8 +6512,8 @@ DEFUN (show_bgp_vrfs,
|
||||
if (!uj && count == 1)
|
||||
vty_out(vty,
|
||||
"%4s %-5s %-16s %9s %10s %-37s %-10s %-15s\n",
|
||||
"Type", "Id", "routerId", "#PeersVfg",
|
||||
"#PeersEstb", "Name", "L3-VNI", "Rmac");
|
||||
"Type", "Id", "routerId", "#PeersVfg",
|
||||
"#PeersEstb", "Name", "L3-VNI", "Rmac");
|
||||
|
||||
peers_cfg = peers_estb = 0;
|
||||
if (uj)
|
||||
@ -6537,8 +6538,9 @@ DEFUN (show_bgp_vrfs,
|
||||
|
||||
|
||||
if (uj) {
|
||||
int64_t vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN) ? -1 :
|
||||
(int64_t)bgp->vrf_id;
|
||||
int64_t vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN)
|
||||
? -1
|
||||
: (int64_t)bgp->vrf_id;
|
||||
json_object_string_add(json_vrf, "type", type);
|
||||
json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
|
||||
json_object_string_add(json_vrf, "routerId",
|
||||
@ -6549,17 +6551,18 @@ DEFUN (show_bgp_vrfs,
|
||||
peers_estb);
|
||||
|
||||
json_object_int_add(json_vrf, "l3vni", bgp->l3vni);
|
||||
json_object_string_add(json_vrf, "rmac",
|
||||
prefix_mac2str(&bgp->rmac, buf,
|
||||
sizeof(buf)));
|
||||
json_object_string_add(
|
||||
json_vrf, "rmac",
|
||||
prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
|
||||
json_object_object_add(json_vrfs, name, json_vrf);
|
||||
} else
|
||||
vty_out(vty,
|
||||
"%4s %-5d %-16s %9u %10u %-37s %-10u %-15s\n",
|
||||
type, bgp->vrf_id == VRF_UNKNOWN ?
|
||||
-1 : (int)bgp->vrf_id,
|
||||
inet_ntoa(bgp->router_id),
|
||||
peers_cfg, peers_estb, name, bgp->l3vni,
|
||||
type,
|
||||
bgp->vrf_id == VRF_UNKNOWN ? -1
|
||||
: (int)bgp->vrf_id,
|
||||
inet_ntoa(bgp->router_id), peers_cfg,
|
||||
peers_estb, name, bgp->l3vni,
|
||||
prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
@ -6568,8 +6571,9 @@ DEFUN (show_bgp_vrfs,
|
||||
|
||||
json_object_int_add(json, "totalVrfs", count);
|
||||
|
||||
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);
|
||||
} else {
|
||||
if (count)
|
||||
@ -6718,17 +6722,20 @@ DEFUN (show_bgp_memory,
|
||||
/* Other attributes */
|
||||
if ((count = community_count()))
|
||||
vty_out(vty, "%ld BGP community entries, using %s of memory\n",
|
||||
count, mtype_memstr(memstrbuf, sizeof(memstrbuf),
|
||||
count * sizeof(struct community)));
|
||||
count,
|
||||
mtype_memstr(memstrbuf, sizeof(memstrbuf),
|
||||
count * sizeof(struct community)));
|
||||
if ((count = mtype_stats_alloc(MTYPE_ECOMMUNITY)))
|
||||
vty_out(vty, "%ld BGP community entries, using %s of memory\n",
|
||||
count, mtype_memstr(memstrbuf, sizeof(memstrbuf),
|
||||
count * sizeof(struct ecommunity)));
|
||||
count,
|
||||
mtype_memstr(memstrbuf, sizeof(memstrbuf),
|
||||
count * sizeof(struct ecommunity)));
|
||||
if ((count = mtype_stats_alloc(MTYPE_LCOMMUNITY)))
|
||||
vty_out(vty,
|
||||
"%ld BGP large-community entries, using %s of memory\n",
|
||||
count, mtype_memstr(memstrbuf, sizeof(memstrbuf),
|
||||
count * sizeof(struct lcommunity)));
|
||||
count,
|
||||
mtype_memstr(memstrbuf, sizeof(memstrbuf),
|
||||
count * sizeof(struct lcommunity)));
|
||||
|
||||
if ((count = mtype_stats_alloc(MTYPE_CLUSTER)))
|
||||
vty_out(vty, "%ld Cluster lists, using %s of memory\n", count,
|
||||
@ -6757,8 +6764,9 @@ DEFUN (show_bgp_memory,
|
||||
count * sizeof(struct hash_backet)));
|
||||
if ((count = mtype_stats_alloc(MTYPE_BGP_REGEXP)))
|
||||
vty_out(vty, "%ld compiled regexes, using %s of memory\n",
|
||||
count, mtype_memstr(memstrbuf, sizeof(memstrbuf),
|
||||
count * sizeof(regex_t)));
|
||||
count,
|
||||
mtype_memstr(memstrbuf, sizeof(memstrbuf),
|
||||
count * sizeof(regex_t)));
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -6773,27 +6781,21 @@ static void bgp_show_bestpath_json(struct bgp *bgp, json_object *json)
|
||||
json_object_string_add(bestpath, "asPath", "confed");
|
||||
|
||||
if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
|
||||
if (bgp_flag_check(bgp,
|
||||
BGP_FLAG_MULTIPATH_RELAX_AS_SET))
|
||||
json_object_string_add(bestpath,
|
||||
"multiPathRelax",
|
||||
if (bgp_flag_check(bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET))
|
||||
json_object_string_add(bestpath, "multiPathRelax",
|
||||
"as-set");
|
||||
else
|
||||
json_object_string_add(bestpath,
|
||||
"multiPathRelax",
|
||||
json_object_string_add(bestpath, "multiPathRelax",
|
||||
"true");
|
||||
} else
|
||||
json_object_string_add(bestpath,
|
||||
"multiPathRelax",
|
||||
"false");
|
||||
json_object_string_add(bestpath, "multiPathRelax", "false");
|
||||
|
||||
if (bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID))
|
||||
json_object_string_add(bestpath, "compareRouterId", "true");
|
||||
if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED)
|
||||
|| bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST)) {
|
||||
if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED))
|
||||
json_object_string_add(bestpath, "med",
|
||||
"confed");
|
||||
json_object_string_add(bestpath, "med", "confed");
|
||||
if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
|
||||
json_object_string_add(bestpath, "med",
|
||||
"missing-as-worst");
|
||||
@ -6884,9 +6886,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
||||
char memstrbuf[MTYPE_MEMSTR_LEN];
|
||||
int64_t vrf_id_ui;
|
||||
|
||||
vrf_id_ui =
|
||||
(bgp->vrf_id == VRF_UNKNOWN) ? -1 :
|
||||
(int64_t)bgp->vrf_id;
|
||||
vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN)
|
||||
? -1
|
||||
: (int64_t)bgp->vrf_id;
|
||||
|
||||
/* Usage summary and header */
|
||||
if (use_json) {
|
||||
@ -6905,8 +6907,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
||||
vty_out(vty,
|
||||
"BGP router identifier %s, local AS number %u vrf-id %d",
|
||||
inet_ntoa(bgp->router_id), bgp->as,
|
||||
bgp->vrf_id == VRF_UNKNOWN ? -1 :
|
||||
(int)bgp->vrf_id);
|
||||
bgp->vrf_id == VRF_UNKNOWN
|
||||
? -1
|
||||
: (int)bgp->vrf_id);
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
@ -7015,8 +7018,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
||||
json, "peerGroupCount", ents);
|
||||
json_object_int_add(
|
||||
json, "peerGroupMemory",
|
||||
ents * sizeof(struct
|
||||
peer_group));
|
||||
ents
|
||||
* sizeof(struct
|
||||
peer_group));
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
@ -7039,10 +7043,11 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
||||
vty_out(vty,
|
||||
"RIB entries %ld, using %s of memory\n",
|
||||
ents,
|
||||
mtype_memstr(memstrbuf,
|
||||
sizeof(memstrbuf),
|
||||
ents * sizeof(struct
|
||||
bgp_node)));
|
||||
mtype_memstr(
|
||||
memstrbuf, sizeof(memstrbuf),
|
||||
ents
|
||||
* sizeof(struct
|
||||
bgp_node)));
|
||||
|
||||
/* Peer related usage */
|
||||
ents = listcount(bgp->peer);
|
||||
@ -7059,8 +7064,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
||||
mtype_memstr(
|
||||
memstrbuf,
|
||||
sizeof(memstrbuf),
|
||||
ents * sizeof(struct
|
||||
peer_group)));
|
||||
ents
|
||||
* sizeof(struct
|
||||
peer_group)));
|
||||
|
||||
if (CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_CONFIG_DAMPENING))
|
||||
@ -7165,7 +7171,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
||||
if (peer->status == Established)
|
||||
if (peer->afc_recv[afi][pfx_rcd_safi])
|
||||
vty_out(vty, " %12ld",
|
||||
peer->pcount[afi][pfx_rcd_safi]);
|
||||
peer->pcount[afi]
|
||||
[pfx_rcd_safi]);
|
||||
else
|
||||
vty_out(vty, " NoNeg");
|
||||
else {
|
||||
@ -7192,8 +7199,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
||||
|
||||
bgp_show_bestpath_json(bgp, 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);
|
||||
} else {
|
||||
if (count)
|
||||
@ -7829,8 +7837,9 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
|
||||
|
||||
paf = peer_af_find(p, afi, safi);
|
||||
if (paf && PAF_SUBGRP(paf)) {
|
||||
vty_out(vty, " Update group %" PRIu64
|
||||
", subgroup %" PRIu64 "\n",
|
||||
vty_out(vty,
|
||||
" Update group %" PRIu64 ", subgroup %" PRIu64
|
||||
"\n",
|
||||
PAF_UPDGRP(paf)->id, PAF_SUBGRP(paf)->id);
|
||||
vty_out(vty, " Packet Queue length %d\n",
|
||||
bpacket_queue_virtual_length(paf));
|
||||
@ -8300,7 +8309,8 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json,
|
||||
epoch_tbuf = time(NULL) - uptime;
|
||||
|
||||
#if CONFDATE > 20200101
|
||||
CPP_NOTICE("bgpTimerUp should be deprecated and can be removed now");
|
||||
CPP_NOTICE(
|
||||
"bgpTimerUp should be deprecated and can be removed now");
|
||||
#endif
|
||||
/*
|
||||
* bgpTimerUp was miliseconds that was accurate
|
||||
@ -8376,8 +8386,8 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json,
|
||||
"bgpTimerConfiguredKeepAliveIntervalMsecs",
|
||||
p->keepalive * 1000);
|
||||
} else if ((bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
|
||||
|| (bgp->default_keepalive !=
|
||||
BGP_DEFAULT_KEEPALIVE)) {
|
||||
|| (bgp->default_keepalive
|
||||
!= BGP_DEFAULT_KEEPALIVE)) {
|
||||
json_object_int_add(json_neigh,
|
||||
"bgpTimerConfiguredHoldTimeMsecs",
|
||||
bgp->default_holdtime);
|
||||
@ -8437,8 +8447,8 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json,
|
||||
vty_out(vty, ", keepalive interval is %d seconds\n",
|
||||
p->keepalive);
|
||||
} else if ((bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
|
||||
|| (bgp->default_keepalive !=
|
||||
BGP_DEFAULT_KEEPALIVE)) {
|
||||
|| (bgp->default_keepalive
|
||||
!= BGP_DEFAULT_KEEPALIVE)) {
|
||||
vty_out(vty, " Configured hold time is %d",
|
||||
bgp->default_holdtime);
|
||||
vty_out(vty, ", keepalive interval is %d seconds\n",
|
||||
@ -9629,8 +9639,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json,
|
||||
} else
|
||||
vty_out(vty,
|
||||
" Reduce the no. of prefix from %s, will restart in %ld seconds\n",
|
||||
p->host, thread_timer_remain_second(
|
||||
p->t_pmax_restart));
|
||||
p->host,
|
||||
thread_timer_remain_second(
|
||||
p->t_pmax_restart));
|
||||
} else {
|
||||
if (use_json)
|
||||
json_object_boolean_true_add(
|
||||
@ -9874,8 +9885,9 @@ static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp,
|
||||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
vty_out(vty, "\n");
|
||||
@ -9910,7 +9922,8 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty,
|
||||
|
||||
json_object_int_add(json, "vrfId",
|
||||
(bgp->vrf_id == VRF_UNKNOWN)
|
||||
? -1 : (int64_t) bgp->vrf_id);
|
||||
? -1
|
||||
: (int64_t)bgp->vrf_id);
|
||||
json_object_string_add(
|
||||
json, "vrfName",
|
||||
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
|
||||
@ -10645,7 +10658,8 @@ DEFUN (show_ip_bgp_peer_groups,
|
||||
vrf = pg = NULL;
|
||||
int idx = 0;
|
||||
|
||||
vrf = argv_find(argv, argc, "VIEWVRFNAME", &idx) ? argv[idx]->arg : NULL;
|
||||
vrf = argv_find(argv, argc, "VIEWVRFNAME", &idx) ? argv[idx]->arg
|
||||
: NULL;
|
||||
pg = argv_find(argv, argc, "PGNAME", &idx) ? argv[idx]->arg : NULL;
|
||||
|
||||
return bgp_show_peer_group_vty(vty, vrf, pg);
|
||||
|
||||
102
bgpd/bgp_zebra.c
102
bgpd/bgp_zebra.c
@ -570,8 +570,8 @@ static int zebra_read_route(int command, struct zclient *zclient,
|
||||
|
||||
/* Now perform the add/update. */
|
||||
bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex,
|
||||
nhtype, api.metric, api.type,
|
||||
api.instance, api.tag);
|
||||
nhtype, api.metric, api.type, api.instance,
|
||||
api.tag);
|
||||
} else {
|
||||
bgp_redistribute_delete(bgp, &api.prefix, api.type,
|
||||
api.instance);
|
||||
@ -1001,7 +1001,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
memset(&api, 0, sizeof(api));
|
||||
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
|
||||
api.vrf_id = bgp->vrf_id;
|
||||
api.nh_vrf_id = bgp->vrf_id;
|
||||
api.type = ZEBRA_ROUTE_BGP;
|
||||
api.safi = safi;
|
||||
api.prefix = *p;
|
||||
@ -1081,7 +1080,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
|
||||
api_nh = &api.nexthops[valid_nh_count];
|
||||
api_nh->gate.ipv4 = *nexthop;
|
||||
|
||||
api_nh->vrf_id = bgp->vrf_id;
|
||||
/* EVPN type-2 routes are
|
||||
programmed as onlink on l3-vni SVI
|
||||
*/
|
||||
@ -1142,10 +1141,11 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
}
|
||||
|
||||
if (mpinfo->extra && bgp_is_valid_label(&mpinfo->extra->label)
|
||||
if (mpinfo->extra
|
||||
&& bgp_is_valid_label(&mpinfo->extra->label[0])
|
||||
&& !CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) {
|
||||
has_valid_label = 1;
|
||||
label = label_pton(&mpinfo->extra->label);
|
||||
label = label_pton(&mpinfo->extra->label[0]);
|
||||
|
||||
api_nh->label_num = 1;
|
||||
api_nh->labels[0] = label;
|
||||
@ -1154,8 +1154,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
}
|
||||
|
||||
/* if this is a evpn route we don't have to include the label */
|
||||
if (has_valid_label &&
|
||||
!(CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)))
|
||||
if (has_valid_label && !(CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)))
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
|
||||
|
||||
if (info->sub_type != BGP_ROUTE_AGGREGATE)
|
||||
@ -1197,8 +1196,8 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
sizeof(nh_buf));
|
||||
|
||||
label_buf[0] = '\0';
|
||||
if (has_valid_label &&
|
||||
!CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE))
|
||||
if (has_valid_label
|
||||
&& !CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE))
|
||||
sprintf(label_buf, "label %u",
|
||||
api_nh->labels[0]);
|
||||
zlog_debug(" nhop [%d]: %s %s", i + 1, nh_buf,
|
||||
@ -1254,7 +1253,6 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
|
||||
memset(&api, 0, sizeof(api));
|
||||
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
|
||||
api.vrf_id = peer->bgp->vrf_id;
|
||||
api.nh_vrf_id = peer->bgp->vrf_id;
|
||||
api.type = ZEBRA_ROUTE_BGP;
|
||||
api.safi = safi;
|
||||
api.prefix = *p;
|
||||
@ -1578,8 +1576,7 @@ void bgp_zebra_instance_register(struct bgp *bgp)
|
||||
|
||||
/* For default instance, register to learn about VNIs, if appropriate.
|
||||
*/
|
||||
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
|
||||
&& is_evpn_enabled())
|
||||
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT && is_evpn_enabled())
|
||||
bgp_zebra_advertise_all_vni(bgp, 1);
|
||||
}
|
||||
|
||||
@ -1597,8 +1594,7 @@ void bgp_zebra_instance_deregister(struct bgp *bgp)
|
||||
|
||||
/* For default instance, unregister learning about VNIs, if appropriate.
|
||||
*/
|
||||
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
|
||||
&& is_evpn_enabled())
|
||||
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT && is_evpn_enabled())
|
||||
bgp_zebra_advertise_all_vni(bgp, 0);
|
||||
|
||||
/* Deregister for router-id, interfaces, redistributed routes. */
|
||||
@ -1634,6 +1630,29 @@ void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer)
|
||||
zclient_send_interface_radv_req(zclient, bgp->vrf_id, peer->ifp, 0, 0);
|
||||
}
|
||||
|
||||
int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise, vni_t vni)
|
||||
{
|
||||
struct stream *s = NULL;
|
||||
|
||||
/* Check socket. */
|
||||
if (!zclient || zclient->sock < 0)
|
||||
return 0;
|
||||
|
||||
/* Don't try to register if Zebra doesn't know of this instance. */
|
||||
if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
|
||||
return 0;
|
||||
|
||||
s = zclient->obuf;
|
||||
stream_reset(s);
|
||||
|
||||
zclient_create_header(s, ZEBRA_ADVERTISE_SUBNET, bgp->vrf_id);
|
||||
stream_putc(s, advertise);
|
||||
stream_put3(s, vni);
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
|
||||
return zclient_send_message(zclient);
|
||||
}
|
||||
|
||||
int bgp_zebra_advertise_gw_macip(struct bgp *bgp, int advertise, vni_t vni)
|
||||
{
|
||||
struct stream *s = NULL;
|
||||
@ -1725,8 +1744,7 @@ static int bgp_zebra_process_local_l3vni(int cmd, struct zclient *zclient,
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_debug("Rx L3-VNI %s VRF %s VNI %u RMAC %s",
|
||||
(cmd == ZEBRA_L3VNI_ADD) ? "add" : "del",
|
||||
vrf_id_to_name(vrf_id),
|
||||
l3vni,
|
||||
vrf_id_to_name(vrf_id), l3vni,
|
||||
prefix_mac2str(&rmac, buf, sizeof(buf)));
|
||||
|
||||
if (cmd == ZEBRA_L3VNI_ADD)
|
||||
@ -1743,7 +1761,7 @@ static int bgp_zebra_process_local_vni(int command, struct zclient *zclient,
|
||||
struct stream *s;
|
||||
vni_t vni;
|
||||
struct bgp *bgp;
|
||||
struct in_addr vtep_ip = { INADDR_ANY };
|
||||
struct in_addr vtep_ip = {INADDR_ANY};
|
||||
vrf_id_t tenant_vrf_id = VRF_DEFAULT;
|
||||
|
||||
s = zclient->ibuf;
|
||||
@ -1760,8 +1778,8 @@ static int bgp_zebra_process_local_vni(int command, struct zclient *zclient,
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_debug("Rx VNI %s VRF %s VNI %u tenant-vrf %s",
|
||||
(command == ZEBRA_VNI_ADD) ? "add" : "del",
|
||||
vrf_id_to_name(vrf_id),
|
||||
vni, vrf_id_to_name(tenant_vrf_id));
|
||||
vrf_id_to_name(vrf_id), vni,
|
||||
vrf_id_to_name(tenant_vrf_id));
|
||||
|
||||
if (command == ZEBRA_VNI_ADD)
|
||||
return bgp_evpn_local_vni_add(
|
||||
@ -1820,6 +1838,48 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient,
|
||||
return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip);
|
||||
}
|
||||
|
||||
static void bgp_zebra_process_local_ip_prefix(int cmd, struct zclient *zclient,
|
||||
zebra_size_t length,
|
||||
vrf_id_t vrf_id)
|
||||
{
|
||||
struct stream *s = NULL;
|
||||
struct bgp *bgp_vrf = NULL;
|
||||
struct prefix p;
|
||||
char buf[PREFIX_STRLEN];
|
||||
|
||||
memset(&p, 0, sizeof(struct prefix));
|
||||
s = zclient->ibuf;
|
||||
stream_get(&p, s, sizeof(struct prefix));
|
||||
|
||||
bgp_vrf = bgp_lookup_by_vrf_id(vrf_id);
|
||||
if (!bgp_vrf)
|
||||
return;
|
||||
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_debug("Recv prefix %s %s on vrf %s",
|
||||
prefix2str(&p, buf, sizeof(buf)),
|
||||
(cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) ? "ADD" : "DEL",
|
||||
vrf_id_to_name(vrf_id));
|
||||
|
||||
if (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) {
|
||||
|
||||
if (p.family == AF_INET)
|
||||
return bgp_evpn_advertise_type5_route(
|
||||
bgp_vrf, &p, NULL, AFI_IP, SAFI_UNICAST);
|
||||
else
|
||||
return bgp_evpn_advertise_type5_route(
|
||||
bgp_vrf, &p, NULL, AFI_IP6, SAFI_UNICAST);
|
||||
|
||||
} else {
|
||||
if (p.family == AF_INET)
|
||||
return bgp_evpn_withdraw_type5_route(
|
||||
bgp_vrf, &p, AFI_IP, SAFI_UNICAST);
|
||||
else
|
||||
return bgp_evpn_withdraw_type5_route(
|
||||
bgp_vrf, &p, AFI_IP6, SAFI_UNICAST);
|
||||
}
|
||||
}
|
||||
|
||||
extern struct zebra_privs_t bgpd_privs;
|
||||
|
||||
void bgp_zebra_init(struct thread_master *master)
|
||||
@ -1852,6 +1912,8 @@ void bgp_zebra_init(struct thread_master *master)
|
||||
zclient->local_macip_del = bgp_zebra_process_local_macip;
|
||||
zclient->local_l3vni_add = bgp_zebra_process_local_l3vni;
|
||||
zclient->local_l3vni_del = bgp_zebra_process_local_l3vni;
|
||||
zclient->local_ip_prefix_add = bgp_zebra_process_local_ip_prefix;
|
||||
zclient->local_ip_prefix_del = bgp_zebra_process_local_ip_prefix;
|
||||
}
|
||||
|
||||
void bgp_zebra_destroy(void)
|
||||
|
||||
@ -58,7 +58,8 @@ extern struct interface *if_lookup_by_ipv6(struct in6_addr *, ifindex_t,
|
||||
vrf_id_t);
|
||||
extern struct interface *if_lookup_by_ipv6_exact(struct in6_addr *, ifindex_t,
|
||||
vrf_id_t);
|
||||
|
||||
extern int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise,
|
||||
vni_t vni);
|
||||
extern int bgp_zebra_advertise_gw_macip(struct bgp *, int, vni_t);
|
||||
extern int bgp_zebra_advertise_all_vni(struct bgp *, int);
|
||||
|
||||
|
||||
89
bgpd/bgpd.c
89
bgpd/bgpd.c
@ -1403,16 +1403,12 @@ static void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi,
|
||||
if (rn->info != NULL) {
|
||||
/* Special handling for 2-level routing
|
||||
* tables. */
|
||||
if (safi == SAFI_MPLS_VPN
|
||||
|| safi == SAFI_ENCAP
|
||||
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
|
||||
|| safi == SAFI_EVPN) {
|
||||
for (nrn = bgp_table_top((
|
||||
struct bgp_table
|
||||
*)(rn->info));
|
||||
nrn;
|
||||
nrn = bgp_route_next(nrn))
|
||||
bgp_process(bgp, nrn,
|
||||
afi, safi);
|
||||
for (nrn = bgp_table_top(
|
||||
(struct bgp_table *)(rn->info));
|
||||
nrn; nrn = bgp_route_next(nrn))
|
||||
bgp_process(bgp, nrn, afi, safi);
|
||||
} else
|
||||
bgp_process(bgp, rn, afi, safi);
|
||||
}
|
||||
@ -1864,8 +1860,7 @@ static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi)
|
||||
peer->afc[afi][safi] = 1;
|
||||
|
||||
if (peer->group)
|
||||
peer_group2peer_config_copy_af(peer->group, peer,
|
||||
afi, safi);
|
||||
peer_group2peer_config_copy_af(peer->group, peer, afi, safi);
|
||||
|
||||
if (!active && peer_active(peer)) {
|
||||
bgp_timer_set(peer);
|
||||
@ -1933,12 +1928,14 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi)
|
||||
ret |= peer_activate_af(peer, afi, safi);
|
||||
}
|
||||
|
||||
/* If this is the first peer to be activated for this afi/labeled-unicast
|
||||
* recalc bestpaths to trigger label allocation */
|
||||
if (safi == SAFI_LABELED_UNICAST && !bgp->allocate_mpls_labels[afi][SAFI_UNICAST]) {
|
||||
/* If this is the first peer to be activated for this
|
||||
* afi/labeled-unicast recalc bestpaths to trigger label allocation */
|
||||
if (safi == SAFI_LABELED_UNICAST
|
||||
&& !bgp->allocate_mpls_labels[afi][SAFI_UNICAST]) {
|
||||
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_info("peer(s) are now active for labeled-unicast, allocate MPLS labels");
|
||||
zlog_info(
|
||||
"peer(s) are now active for labeled-unicast, allocate MPLS labels");
|
||||
|
||||
bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 1;
|
||||
bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST);
|
||||
@ -2027,14 +2024,15 @@ int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi)
|
||||
|
||||
bgp = peer->bgp;
|
||||
|
||||
/* If this is the last peer to be deactivated for this afi/labeled-unicast
|
||||
* recalc bestpaths to trigger label deallocation */
|
||||
if (safi == SAFI_LABELED_UNICAST &&
|
||||
bgp->allocate_mpls_labels[afi][SAFI_UNICAST] &&
|
||||
!bgp_afi_safi_peer_exists(bgp, afi, safi)) {
|
||||
/* If this is the last peer to be deactivated for this
|
||||
* afi/labeled-unicast recalc bestpaths to trigger label deallocation */
|
||||
if (safi == SAFI_LABELED_UNICAST
|
||||
&& bgp->allocate_mpls_labels[afi][SAFI_UNICAST]
|
||||
&& !bgp_afi_safi_peer_exists(bgp, afi, safi)) {
|
||||
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_info("peer(s) are no longer active for labeled-unicast, deallocate MPLS labels");
|
||||
zlog_info(
|
||||
"peer(s) are no longer active for labeled-unicast, deallocate MPLS labels");
|
||||
|
||||
bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 0;
|
||||
bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST);
|
||||
@ -2654,7 +2652,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
|
||||
}
|
||||
} else if (peer->afc[afi][safi])
|
||||
peer_deactivate(peer, afi, safi);
|
||||
}
|
||||
}
|
||||
|
||||
if (peer->group) {
|
||||
assert(group && peer->group == group);
|
||||
@ -2856,8 +2854,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
|
||||
XSTRDUP(MTYPE_BGP_PEER_HOST, cmd_domainname_get());
|
||||
bgp->peer = list_new();
|
||||
bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
|
||||
bgp->peerhash = hash_create(peer_hash_key_make,
|
||||
peer_hash_same,
|
||||
bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same,
|
||||
"BGP Peer Hash");
|
||||
bgp->peerhash->max_size = BGP_PEER_MAX_HASH_SIZE;
|
||||
|
||||
@ -3988,8 +3985,9 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
|
||||
}
|
||||
|
||||
/* Track if addpath TX is in use */
|
||||
if (flag & (PEER_FLAG_ADDPATH_TX_ALL_PATHS
|
||||
| PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
|
||||
if (flag
|
||||
& (PEER_FLAG_ADDPATH_TX_ALL_PATHS
|
||||
| PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
|
||||
bgp = peer->bgp;
|
||||
addpath_tx_used = 0;
|
||||
|
||||
@ -6802,8 +6800,9 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
} else {
|
||||
if (!peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_SEND_COMMUNITY)
|
||||
&& (!g_peer || peer_af_flag_check(g_peer, afi, safi,
|
||||
PEER_FLAG_SEND_COMMUNITY))
|
||||
&& (!g_peer
|
||||
|| peer_af_flag_check(g_peer, afi, safi,
|
||||
PEER_FLAG_SEND_COMMUNITY))
|
||||
&& !peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_SEND_EXT_COMMUNITY)
|
||||
&& (!g_peer
|
||||
@ -6811,9 +6810,10 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
PEER_FLAG_SEND_EXT_COMMUNITY))
|
||||
&& !peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_SEND_LARGE_COMMUNITY)
|
||||
&& (!g_peer || peer_af_flag_check(
|
||||
g_peer, afi, safi,
|
||||
PEER_FLAG_SEND_LARGE_COMMUNITY))) {
|
||||
&& (!g_peer
|
||||
|| peer_af_flag_check(
|
||||
g_peer, afi, safi,
|
||||
PEER_FLAG_SEND_LARGE_COMMUNITY))) {
|
||||
vty_out(vty, " no neighbor %s send-community all\n",
|
||||
addr);
|
||||
} else {
|
||||
@ -6841,9 +6841,10 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
|
||||
if (!peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_SEND_COMMUNITY)
|
||||
&& (!g_peer || peer_af_flag_check(
|
||||
g_peer, afi, safi,
|
||||
PEER_FLAG_SEND_COMMUNITY))) {
|
||||
&& (!g_peer
|
||||
|| peer_af_flag_check(
|
||||
g_peer, afi, safi,
|
||||
PEER_FLAG_SEND_COMMUNITY))) {
|
||||
vty_out(vty,
|
||||
" no neighbor %s send-community\n",
|
||||
addr);
|
||||
@ -6954,17 +6955,17 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
bgp_config_write_filter(vty, peer, afi, safi);
|
||||
|
||||
/* atribute-unchanged. */
|
||||
if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ||
|
||||
peer_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ||
|
||||
peer_af_flag_check(peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) {
|
||||
if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED)
|
||||
|| peer_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED)
|
||||
|| peer_af_flag_check(peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) {
|
||||
|
||||
if (!peer_group_active(peer) ||
|
||||
peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_AS_PATH_UNCHANGED) ||
|
||||
peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_NEXTHOP_UNCHANGED) ||
|
||||
peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_MED_UNCHANGED)) {
|
||||
if (!peer_group_active(peer)
|
||||
|| peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_AS_PATH_UNCHANGED)
|
||||
|| peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_NEXTHOP_UNCHANGED)
|
||||
|| peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_MED_UNCHANGED)) {
|
||||
|
||||
vty_out(vty,
|
||||
" neighbor %s attribute-unchanged%s%s%s\n",
|
||||
|
||||
54
bgpd/bgpd.h
54
bgpd/bgpd.h
@ -262,13 +262,14 @@ struct bgp {
|
||||
/* $FRR indent$ */
|
||||
/* clang-format off */
|
||||
#define BGP_MAXMED_ADMIN_UNCONFIGURED 0 /* Off by default */
|
||||
u_int32_t
|
||||
maxmed_admin_value; /* Max-med value when administrative in on
|
||||
u_int32_t maxmed_admin_value; /* Max-med value when administrative in on
|
||||
*/
|
||||
/* $FRR indent$ */
|
||||
/* clang-format off */
|
||||
#define BGP_MAXMED_VALUE_DEFAULT 4294967294 /* Maximum by default */
|
||||
|
||||
u_char maxmed_active; /* 1/0 if max-med is active or not */
|
||||
u_int32_t maxmed_value; /* Max-med value when its active */
|
||||
u_char maxmed_active; /* 1/0 if max-med is active or not */
|
||||
u_int32_t maxmed_value; /* Max-med value when its active */
|
||||
|
||||
/* BGP update delay on startup */
|
||||
struct thread *t_update_delay;
|
||||
@ -828,8 +829,8 @@ struct peer {
|
||||
#define PEER_CONFIG_ROUTEADV (1 << 2) /* route advertise */
|
||||
#define PEER_GROUP_CONFIG_TIMER (1 << 3) /* timers from peer-group */
|
||||
|
||||
#define PEER_OR_GROUP_TIMER_SET(peer) \
|
||||
(CHECK_FLAG(peer->config, PEER_CONFIG_TIMER) \
|
||||
#define PEER_OR_GROUP_TIMER_SET(peer) \
|
||||
(CHECK_FLAG(peer->config, PEER_CONFIG_TIMER) \
|
||||
|| CHECK_FLAG(peer->config, PEER_GROUP_CONFIG_TIMER))
|
||||
|
||||
_Atomic uint32_t holdtime;
|
||||
@ -869,21 +870,29 @@ struct peer {
|
||||
/* workqueues */
|
||||
struct work_queue *clear_node_queue;
|
||||
|
||||
#define PEER_TOTAL_RX(peer) \
|
||||
atomic_load_explicit(&peer->open_in, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->update_in, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->notify_in, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->refresh_in, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->keepalive_in, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->dynamic_cap_in, memory_order_relaxed)
|
||||
#define PEER_TOTAL_RX(peer) \
|
||||
atomic_load_explicit(&peer->open_in, memory_order_relaxed) \
|
||||
+ atomic_load_explicit(&peer->update_in, memory_order_relaxed) \
|
||||
+ atomic_load_explicit(&peer->notify_in, memory_order_relaxed) \
|
||||
+ atomic_load_explicit(&peer->refresh_in, \
|
||||
memory_order_relaxed) \
|
||||
+ atomic_load_explicit(&peer->keepalive_in, \
|
||||
memory_order_relaxed) \
|
||||
+ atomic_load_explicit(&peer->dynamic_cap_in, \
|
||||
memory_order_relaxed)
|
||||
|
||||
#define PEER_TOTAL_TX(peer) \
|
||||
atomic_load_explicit(&peer->open_out, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->update_out, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->notify_out, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->refresh_out, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->keepalive_out, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->dynamic_cap_out, memory_order_relaxed)
|
||||
#define PEER_TOTAL_TX(peer) \
|
||||
atomic_load_explicit(&peer->open_out, memory_order_relaxed) \
|
||||
+ atomic_load_explicit(&peer->update_out, \
|
||||
memory_order_relaxed) \
|
||||
+ atomic_load_explicit(&peer->notify_out, \
|
||||
memory_order_relaxed) \
|
||||
+ atomic_load_explicit(&peer->refresh_out, \
|
||||
memory_order_relaxed) \
|
||||
+ atomic_load_explicit(&peer->keepalive_out, \
|
||||
memory_order_relaxed) \
|
||||
+ atomic_load_explicit(&peer->dynamic_cap_out, \
|
||||
memory_order_relaxed)
|
||||
|
||||
/* Statistics field */
|
||||
_Atomic uint32_t open_in; /* Open message input count */
|
||||
@ -898,7 +907,7 @@ struct peer {
|
||||
_Atomic uint32_t refresh_in; /* Route Refresh input count */
|
||||
_Atomic uint32_t refresh_out; /* Route Refresh output count */
|
||||
_Atomic uint32_t dynamic_cap_in; /* Dynamic Capability input count. */
|
||||
_Atomic uint32_t dynamic_cap_out; /* Dynamic Capability output count. */
|
||||
_Atomic uint32_t dynamic_cap_out; /* Dynamic Capability output count. */
|
||||
|
||||
/* BGP state count */
|
||||
u_int32_t established; /* Established */
|
||||
@ -1480,7 +1489,8 @@ extern int peer_cmp(struct peer *p1, struct peer *p2);
|
||||
extern int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, iana_safi_t pkt_safi,
|
||||
afi_t *afi, safi_t *safi);
|
||||
extern int bgp_map_afi_safi_int2iana(afi_t afi, safi_t safi,
|
||||
iana_afi_t *pkt_afi, iana_safi_t *pkt_safi);
|
||||
iana_afi_t *pkt_afi,
|
||||
iana_safi_t *pkt_safi);
|
||||
|
||||
extern struct peer_af *peer_af_create(struct peer *, afi_t, safi_t);
|
||||
extern struct peer_af *peer_af_find(struct peer *, afi_t, safi_t);
|
||||
|
||||
@ -260,20 +260,21 @@ int bgp_rfapi_is_vnc_configured(struct bgp *bgp)
|
||||
/***********************************************************************
|
||||
* VNC Configuration/CLI
|
||||
***********************************************************************/
|
||||
#define VNC_VTY_CONFIG_CHECK(bgp) \
|
||||
{ \
|
||||
switch (bgp_rfapi_is_vnc_configured(bgp)) { \
|
||||
case EPERM: \
|
||||
vty_out(vty, "VNC operations only permitted on default BGP instance.\n"); \
|
||||
return CMD_WARNING_CONFIG_FAILED; \
|
||||
break; \
|
||||
case ENXIO: \
|
||||
vty_out(vty, "VNC not configured.\n"); \
|
||||
return CMD_WARNING_CONFIG_FAILED; \
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
#define VNC_VTY_CONFIG_CHECK(bgp) \
|
||||
{ \
|
||||
switch (bgp_rfapi_is_vnc_configured(bgp)) { \
|
||||
case EPERM: \
|
||||
vty_out(vty, \
|
||||
"VNC operations only permitted on default BGP instance.\n"); \
|
||||
return CMD_WARNING_CONFIG_FAILED; \
|
||||
break; \
|
||||
case ENXIO: \
|
||||
vty_out(vty, "VNC not configured.\n"); \
|
||||
return CMD_WARNING_CONFIG_FAILED; \
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
DEFUN (vnc_advertise_un_method,
|
||||
@ -509,9 +510,8 @@ DEFUN (vnc_defaults_responselifetime,
|
||||
} else {
|
||||
rspint = strtoul(argv[1]->arg, NULL, 10);
|
||||
if (rspint > INT32_MAX)
|
||||
rspint =
|
||||
INT32_MAX; /* is really an int, not an unsigned
|
||||
int */
|
||||
rspint = INT32_MAX; /* is really an int, not an unsigned
|
||||
int */
|
||||
}
|
||||
|
||||
bgp->rfapi_cfg->default_response_lifetime = rspint;
|
||||
@ -554,7 +554,7 @@ rfapi_group_new(struct bgp *bgp, rfapi_group_cfg_type_t type, const char *name)
|
||||
/* add to tail of list */
|
||||
listnode_add(bgp->rfapi_cfg->nve_groups_sequential, rfg);
|
||||
}
|
||||
rfg->label = MPLS_LABEL_ILLEGAL;
|
||||
rfg->label = MPLS_LABEL_NONE;
|
||||
QOBJ_REG(rfg, rfapi_nve_group_cfg);
|
||||
|
||||
return rfg;
|
||||
@ -1631,14 +1631,14 @@ DEFUN (vnc_nve_group_export_no_prefixlist,
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (argv[idx-1]->text[0] == 'z')
|
||||
if (argv[idx - 1]->text[0] == 'z')
|
||||
is_bgp = 0;
|
||||
idx += 2; /* skip afi and keyword */
|
||||
idx += 2; /* skip afi and keyword */
|
||||
|
||||
if (is_bgp) {
|
||||
if (idx == argc ||
|
||||
strmatch(argv[idx]->arg,
|
||||
rfg->plist_export_bgp_name[afi])) {
|
||||
if (idx == argc
|
||||
|| strmatch(argv[idx]->arg,
|
||||
rfg->plist_export_bgp_name[afi])) {
|
||||
if (rfg->plist_export_bgp_name[afi])
|
||||
free(rfg->plist_export_bgp_name[afi]);
|
||||
rfg->plist_export_bgp_name[afi] = NULL;
|
||||
@ -1647,9 +1647,9 @@ DEFUN (vnc_nve_group_export_no_prefixlist,
|
||||
vnc_direct_bgp_reexport_group_afi(bgp, rfg, afi);
|
||||
}
|
||||
} else {
|
||||
if (idx == argc ||
|
||||
strmatch(argv[idx]->arg,
|
||||
rfg->plist_export_zebra_name[afi])) {
|
||||
if (idx == argc
|
||||
|| strmatch(argv[idx]->arg,
|
||||
rfg->plist_export_zebra_name[afi])) {
|
||||
if (rfg->plist_export_zebra_name[afi])
|
||||
free(rfg->plist_export_zebra_name[afi]);
|
||||
rfg->plist_export_zebra_name[afi] = NULL;
|
||||
@ -1700,7 +1700,7 @@ DEFUN (vnc_nve_group_export_prefixlist,
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (argv[idx-1]->text[0] == 'z')
|
||||
if (argv[idx - 1]->text[0] == 'z')
|
||||
is_bgp = 0;
|
||||
idx = argc - 1;
|
||||
|
||||
@ -1758,18 +1758,19 @@ DEFUN (vnc_nve_group_export_no_routemap,
|
||||
switch (argv[idx]->text[0]) {
|
||||
case 'z':
|
||||
is_bgp = 0;
|
||||
/* fall thru */
|
||||
/* fall thru */
|
||||
case 'b':
|
||||
idx += 2;
|
||||
break;
|
||||
default: /* route-map */
|
||||
default: /* route-map */
|
||||
idx++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_bgp) {
|
||||
if (idx == argc ||
|
||||
strmatch(argv[idx]->arg, rfg->routemap_export_bgp_name)) {
|
||||
if (idx == argc
|
||||
|| strmatch(argv[idx]->arg,
|
||||
rfg->routemap_export_bgp_name)) {
|
||||
if (rfg->routemap_export_bgp_name)
|
||||
free(rfg->routemap_export_bgp_name);
|
||||
rfg->routemap_export_bgp_name = NULL;
|
||||
@ -1779,9 +1780,9 @@ DEFUN (vnc_nve_group_export_no_routemap,
|
||||
vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP6);
|
||||
}
|
||||
} else {
|
||||
if (idx == argc ||
|
||||
strmatch(argv[idx]->arg,
|
||||
rfg->routemap_export_zebra_name)) {
|
||||
if (idx == argc
|
||||
|| strmatch(argv[idx]->arg,
|
||||
rfg->routemap_export_zebra_name)) {
|
||||
if (rfg->routemap_export_zebra_name)
|
||||
free(rfg->routemap_export_zebra_name);
|
||||
rfg->routemap_export_zebra_name = NULL;
|
||||
@ -2466,8 +2467,7 @@ bgp_rfapi_delete_named_nve_group(struct vty *vty, /* NULL = no output */
|
||||
if (rfg->rfd)
|
||||
clear_vnc_vrf_closer(rfg);
|
||||
bgp_rfapi_delete_nve_group(vty, bgp, rfg);
|
||||
}
|
||||
else /* must be delete all */
|
||||
} else /* must be delete all */
|
||||
for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->nve_groups_sequential,
|
||||
node, nnode, rfg)) {
|
||||
if (rfg->rfd)
|
||||
@ -3063,7 +3063,7 @@ DEFUN (vnc_vrf_policy_no_label,
|
||||
vnc_redistribute_prechange(bgp);
|
||||
}
|
||||
|
||||
rfg->label = MPLS_LABEL_ILLEGAL;
|
||||
rfg->label = MPLS_LABEL_NONE;
|
||||
|
||||
if (bgp->rfapi_cfg->rfg_redist == rfg) {
|
||||
vnc_redistribute_postchange(bgp);
|
||||
@ -3950,7 +3950,9 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
|
||||
if (rfg->plist_export_bgp_name[afi]) {
|
||||
vty_out(vty,
|
||||
" export %s%s prefix-list %s\n",
|
||||
(rfg->type == RFAPI_GROUP_CFG_VRF ? "" : "bgp "),
|
||||
(rfg->type == RFAPI_GROUP_CFG_VRF
|
||||
? ""
|
||||
: "bgp "),
|
||||
afistr,
|
||||
rfg->plist_export_bgp_name
|
||||
[afi]);
|
||||
@ -3958,7 +3960,9 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
|
||||
if (rfg->plist_export_zebra_name[afi]) {
|
||||
vty_out(vty,
|
||||
" export %s%s prefix-list %s\n",
|
||||
(rfg->type == RFAPI_GROUP_CFG_VRF ? "" : "zebra "),
|
||||
(rfg->type == RFAPI_GROUP_CFG_VRF
|
||||
? ""
|
||||
: "zebra "),
|
||||
afistr,
|
||||
rfg->plist_export_zebra_name
|
||||
[afi]);
|
||||
@ -3993,12 +3997,16 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
|
||||
|
||||
if (rfg->routemap_export_bgp_name) {
|
||||
vty_out(vty, " export %sroute-map %s\n",
|
||||
(rfg->type == RFAPI_GROUP_CFG_VRF ? "" : "bgp "),
|
||||
(rfg->type == RFAPI_GROUP_CFG_VRF
|
||||
? ""
|
||||
: "bgp "),
|
||||
rfg->routemap_export_bgp_name);
|
||||
}
|
||||
if (rfg->routemap_export_zebra_name) {
|
||||
vty_out(vty, " export %sroute-map %s\n",
|
||||
(rfg->type == RFAPI_GROUP_CFG_VRF ? "" : "zebra "),
|
||||
(rfg->type == RFAPI_GROUP_CFG_VRF
|
||||
? ""
|
||||
: "zebra "),
|
||||
rfg->routemap_export_zebra_name);
|
||||
}
|
||||
if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]) {
|
||||
@ -4098,7 +4106,8 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
|
||||
}
|
||||
|
||||
if (hc->default_rd.prefixlen
|
||||
|| hc->default_response_lifetime != BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT
|
||||
|| hc->default_response_lifetime
|
||||
!= BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT
|
||||
|| hc->default_rt_import_list || hc->default_rt_export_list
|
||||
|| hc->nve_groups_sequential->count) {
|
||||
|
||||
@ -4184,8 +4193,8 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
|
||||
|
||||
prefix2str(&rfg->vn_prefix, buf,
|
||||
sizeof(buf));
|
||||
vty_out(vty, " prefix %s %s\n",
|
||||
"vn", buf);
|
||||
vty_out(vty, " prefix %s %s\n", "vn",
|
||||
buf);
|
||||
}
|
||||
|
||||
if (rfg->un_prefix.family && rfg->un_node) {
|
||||
@ -4193,8 +4202,8 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
|
||||
|
||||
prefix2str(&rfg->un_prefix, buf,
|
||||
sizeof(buf));
|
||||
vty_out(vty, " prefix %s %s\n",
|
||||
"un", buf);
|
||||
vty_out(vty, " prefix %s %s\n", "un",
|
||||
buf);
|
||||
}
|
||||
|
||||
|
||||
@ -4215,11 +4224,10 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
|
||||
value);
|
||||
|
||||
} else
|
||||
vty_out(vty,
|
||||
" rd %s\n",
|
||||
prefix_rd2str(&rfg->rd,
|
||||
buf,
|
||||
sizeof(buf)));
|
||||
vty_out(vty, " rd %s\n",
|
||||
prefix_rd2str(
|
||||
&rfg->rd, buf,
|
||||
sizeof(buf)));
|
||||
}
|
||||
if (rfg->flags & RFAPI_RFG_RESPONSE_LIFETIME) {
|
||||
vty_out(vty, " response-lifetime ");
|
||||
|
||||
@ -1083,7 +1083,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
|
||||
/* save backref to rfapi handle */
|
||||
assert(bgp_info_extra_get(new));
|
||||
new->extra->vnc.export.rfapi_handle = (void *)rfd;
|
||||
encode_label(label_val, &new->extra->label);
|
||||
encode_label(label_val, &new->extra->label[0]);
|
||||
|
||||
/* debug */
|
||||
|
||||
|
||||
@ -521,7 +521,7 @@ static struct bgp_info *rfapiBgpInfoCreate(struct attr *attr, struct peer *peer,
|
||||
rfapi_time(&new->extra->vnc.import.create_time);
|
||||
}
|
||||
if (label)
|
||||
encode_label(*label, &new->extra->label);
|
||||
encode_label(*label, &new->extra->label[0]);
|
||||
new->type = type;
|
||||
new->sub_type = sub_type;
|
||||
new->peer = peer;
|
||||
@ -1338,7 +1338,7 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix,
|
||||
vo->v.l2addr.local_nve_id = bi->extra->vnc.import.rd.val[1];
|
||||
|
||||
/* label comes from MP_REACH_NLRI label */
|
||||
vo->v.l2addr.label = decode_label(&bi->extra->label);
|
||||
vo->v.l2addr.label = decode_label(&bi->extra->label[0]);
|
||||
|
||||
new->vn_options = vo;
|
||||
|
||||
@ -4242,7 +4242,7 @@ static void rfapiBgpTableFilteredImport(struct bgp *bgp,
|
||||
|
||||
if (bi->extra)
|
||||
label = decode_label(
|
||||
&bi->extra->label);
|
||||
&bi->extra->label[0]);
|
||||
(*rfapiBgpInfoFilteredImportFunction(
|
||||
safi))(
|
||||
it, /* which import table */
|
||||
|
||||
@ -697,7 +697,7 @@ static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri,
|
||||
vo->v.l2addr.local_nve_id = bi->extra->vnc.import.rd.val[1];
|
||||
|
||||
/* label comes from MP_REACH_NLRI label */
|
||||
vo->v.l2addr.label = decode_label(&bi->extra->label);
|
||||
vo->v.l2addr.label = decode_label(&bi->extra->label[0]);
|
||||
|
||||
rfapi_vn_options_free(
|
||||
ri->vn_options); /* maybe free old version */
|
||||
|
||||
@ -432,7 +432,7 @@ void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p,
|
||||
}
|
||||
|
||||
if (bi->extra != NULL)
|
||||
vty_out(vty, " label=%u", decode_label(&bi->extra->label));
|
||||
vty_out(vty, " label=%u", decode_label(&bi->extra->label[0]));
|
||||
|
||||
if (!rfapiGetVncLifetime(bi->attr, &lifetime)) {
|
||||
vty_out(vty, " life=%d", lifetime);
|
||||
@ -1068,7 +1068,7 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
|
||||
inet_ntop(pfx_vn.family, &pfx_vn.u.prefix, buf_ntop,
|
||||
BUFSIZ));
|
||||
if (bi->extra) {
|
||||
u_int32_t l = decode_label(&bi->extra->label);
|
||||
u_int32_t l = decode_label(&bi->extra->label[0]);
|
||||
snprintf(buf_vn, BUFSIZ, "Label: %d", l);
|
||||
} else /* should never happen */
|
||||
{
|
||||
@ -1181,7 +1181,7 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
|
||||
}
|
||||
}
|
||||
if (tun_type != BGP_ENCAP_TYPE_MPLS && bi->extra) {
|
||||
u_int32_t l = decode_label(&bi->extra->label);
|
||||
u_int32_t l = decode_label(&bi->extra->label[0]);
|
||||
if (!MPLS_LABEL_IS_NULL(l)) {
|
||||
fp(out, " Label: %d", l);
|
||||
if (nlines == 1)
|
||||
|
||||
@ -317,7 +317,7 @@ void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct route_node *rn,
|
||||
iattr, /* bgp_update copies this attr */
|
||||
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
|
||||
BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
|
||||
NULL, /* tag not used for unicast */
|
||||
NULL, 0, /* tag not used for unicast */
|
||||
0, NULL); /* EVPN not used */
|
||||
bgp_attr_unintern(&iattr);
|
||||
}
|
||||
@ -398,7 +398,7 @@ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct route_node *rn,
|
||||
NULL, /* attr, ignored */
|
||||
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
|
||||
BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
|
||||
NULL, NULL); /* tag not used for unicast */
|
||||
NULL, 0, NULL); /* tag not used for unicast */
|
||||
}
|
||||
|
||||
static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi)
|
||||
@ -498,7 +498,7 @@ static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi)
|
||||
ZEBRA_ROUTE_VNC_DIRECT,
|
||||
BGP_ROUTE_REDISTRIBUTE,
|
||||
NULL, /* RD not used for unicast */
|
||||
NULL,
|
||||
NULL, 0,
|
||||
NULL); /* tag not used for unicast */
|
||||
}
|
||||
}
|
||||
@ -880,7 +880,7 @@ void vnc_direct_bgp_del_prefix(struct bgp *bgp,
|
||||
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
|
||||
BGP_ROUTE_REDISTRIBUTE,
|
||||
NULL, /* RD not used for unicast */
|
||||
NULL, NULL); /* tag not used for unicast */
|
||||
NULL, 0, NULL); /* tag not used for unicast */
|
||||
/*
|
||||
* yuck!
|
||||
* - but consistent with rest of function
|
||||
@ -909,7 +909,7 @@ void vnc_direct_bgp_del_prefix(struct bgp *bgp,
|
||||
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
|
||||
BGP_ROUTE_REDISTRIBUTE,
|
||||
NULL, /* RD not used for unicast */
|
||||
NULL, NULL); /* tag not used for unicast */
|
||||
NULL, 0, NULL); /* tag not used for unicast */
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1048,7 +1048,7 @@ void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
|
||||
unicast */
|
||||
NULL, /* tag not used for
|
||||
unicast */
|
||||
0, NULL); /* EVPN not used */
|
||||
0, 0, NULL); /* EVPN not used */
|
||||
|
||||
bgp_attr_unintern(&iattr);
|
||||
}
|
||||
@ -1142,7 +1142,7 @@ void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
|
||||
BGP_ROUTE_REDISTRIBUTE,
|
||||
NULL, /* RD not used for
|
||||
unicast */
|
||||
NULL, NULL); /* tag not
|
||||
NULL, 0, NULL); /* tag not
|
||||
used for
|
||||
unicast */
|
||||
}
|
||||
@ -1260,7 +1260,7 @@ static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
|
||||
BGP_ROUTE_REDISTRIBUTE,
|
||||
NULL, /* RD not used for unicast */
|
||||
NULL, /* tag not used for unicast */
|
||||
0, NULL); /* EVPN not used */
|
||||
0, 0, NULL); /* EVPN not used */
|
||||
|
||||
bgp_attr_unintern(&iattr);
|
||||
|
||||
@ -1374,7 +1374,7 @@ static void vnc_direct_del_rn_group_rd(struct bgp *bgp,
|
||||
ZEBRA_ROUTE_VNC_DIRECT,
|
||||
BGP_ROUTE_REDISTRIBUTE,
|
||||
NULL, /* RD not used for unicast */
|
||||
NULL,
|
||||
NULL, 0,
|
||||
NULL); /* tag not used for unicast */
|
||||
return;
|
||||
}
|
||||
@ -1496,7 +1496,7 @@ static void vnc_direct_bgp_unexport_table(afi_t afi, struct route_table *rt,
|
||||
BGP_ROUTE_REDISTRIBUTE,
|
||||
NULL, /* RD not used for
|
||||
unicast */
|
||||
NULL, NULL); /* tag not
|
||||
NULL, 0, NULL); /* tag not
|
||||
used for
|
||||
unicast,
|
||||
EVPN
|
||||
@ -1719,7 +1719,7 @@ void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi,
|
||||
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT_RH,
|
||||
BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
|
||||
NULL, /* tag not used for unicast, EVPN neither */
|
||||
0, NULL); /* EVPN not used */
|
||||
0, 0, NULL); /* EVPN not used */
|
||||
bgp_attr_unintern(&iattr);
|
||||
}
|
||||
|
||||
@ -1734,7 +1734,7 @@ static int vncExportWithdrawTimer(struct thread *t)
|
||||
NULL, /* attr, ignored */
|
||||
family2afi(eti->node->p.family), SAFI_UNICAST, eti->type,
|
||||
eti->subtype, NULL, /* RD not used for unicast */
|
||||
NULL, NULL); /* tag not used for unicast, EVPN neither */
|
||||
NULL, 0, NULL); /* tag not used for unicast, EVPN neither */
|
||||
|
||||
/*
|
||||
* Free the eti
|
||||
@ -1965,7 +1965,7 @@ void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi)
|
||||
NULL, /* tag not used for
|
||||
unicast, EVPN
|
||||
neither */
|
||||
0, NULL); /* EVPN not used */
|
||||
0, 0, NULL); /* EVPN not used */
|
||||
bgp_attr_unintern(&iattr);
|
||||
}
|
||||
}
|
||||
@ -2026,7 +2026,7 @@ void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi)
|
||||
ZEBRA_ROUTE_VNC_DIRECT_RH,
|
||||
BGP_ROUTE_REDISTRIBUTE,
|
||||
NULL, /* RD not used for unicast */
|
||||
NULL, NULL); /* tag not used for
|
||||
NULL, 0, NULL); /* tag not used for
|
||||
unicast, EVPN
|
||||
neither */
|
||||
}
|
||||
|
||||
@ -495,7 +495,7 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
|
||||
ecommunity_merge(new_ecom, bi->attr->ecommunity);
|
||||
|
||||
if (bi->extra)
|
||||
label = decode_label(&bi->extra->label);
|
||||
label = decode_label(&bi->extra->label[0]);
|
||||
|
||||
add_vnc_route(&vncHDResolveNve, bgp, SAFI_MPLS_VPN,
|
||||
prefix, /* unicast route prefix */
|
||||
@ -1783,7 +1783,7 @@ static void vnc_import_bgp_exterior_add_route_it(
|
||||
prd = &bi_interior->extra->vnc.import
|
||||
.rd;
|
||||
label = decode_label(
|
||||
&bi_interior->extra->label);
|
||||
&bi_interior->extra->label[0]);
|
||||
} else
|
||||
prd = NULL;
|
||||
|
||||
@ -1958,7 +1958,7 @@ void vnc_import_bgp_exterior_del_route(
|
||||
prd = &bi_interior->extra->vnc.import
|
||||
.rd;
|
||||
label = decode_label(
|
||||
&bi_interior->extra->label);
|
||||
&bi_interior->extra->label[0]);
|
||||
} else
|
||||
prd = NULL;
|
||||
|
||||
@ -2113,7 +2113,7 @@ void vnc_import_bgp_exterior_add_route_interior(
|
||||
if (bi_interior->extra) {
|
||||
prd = &bi_interior->extra->vnc.import.rd;
|
||||
label = decode_label(
|
||||
&bi_interior->extra->label);
|
||||
&bi_interior->extra->label[0]);
|
||||
} else
|
||||
prd = NULL;
|
||||
|
||||
@ -2226,7 +2226,7 @@ void vnc_import_bgp_exterior_add_route_interior(
|
||||
if (bi->extra) {
|
||||
prd = &bi->extra->vnc.import.rd;
|
||||
label = decode_label(
|
||||
&bi->extra->label);
|
||||
&bi->extra->label[0]);
|
||||
} else
|
||||
prd = NULL;
|
||||
|
||||
@ -2248,7 +2248,7 @@ void vnc_import_bgp_exterior_add_route_interior(
|
||||
prd = &bi_interior->extra->vnc.import
|
||||
.rd;
|
||||
label = decode_label(
|
||||
&bi_interior->extra->label);
|
||||
&bi_interior->extra->label[0]);
|
||||
} else
|
||||
prd = NULL;
|
||||
|
||||
@ -2369,7 +2369,7 @@ void vnc_import_bgp_exterior_add_route_interior(
|
||||
if (bi_interior->extra) {
|
||||
prd = &bi_interior->extra->vnc.import.rd;
|
||||
label = decode_label(
|
||||
&bi_interior->extra->label);
|
||||
&bi_interior->extra->label[0]);
|
||||
} else
|
||||
prd = NULL;
|
||||
|
||||
@ -2480,7 +2480,7 @@ void vnc_import_bgp_exterior_del_route_interior(
|
||||
|
||||
if (bi_interior->extra) {
|
||||
prd = &bi_interior->extra->vnc.import.rd;
|
||||
label = decode_label(&bi_interior->extra->label);
|
||||
label = decode_label(&bi_interior->extra->label[0]);
|
||||
} else
|
||||
prd = NULL;
|
||||
|
||||
@ -2556,7 +2556,8 @@ void vnc_import_bgp_exterior_del_route_interior(
|
||||
|
||||
if (bi->extra) {
|
||||
prd = &bi->extra->vnc.import.rd;
|
||||
label = decode_label(&bi->extra->label);
|
||||
label = decode_label(
|
||||
&bi->extra->label[0]);
|
||||
} else
|
||||
prd = NULL;
|
||||
|
||||
|
||||
@ -396,7 +396,6 @@ static void vnc_zebra_route_msg(struct prefix *p, unsigned int nhp_count,
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_VNC;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = *p;
|
||||
@ -407,6 +406,7 @@ static void vnc_zebra_route_msg(struct prefix *p, unsigned int nhp_count,
|
||||
for (i = 0; i < api.nexthop_num; i++) {
|
||||
|
||||
api_nh = &api.nexthops[i];
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
switch (p->family) {
|
||||
case AF_INET:
|
||||
memcpy(&api_nh->gate.ipv4, nhp_ary4[i],
|
||||
|
||||
1
debianpkg/.gitignore
vendored
Normal file
1
debianpkg/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
changelog
|
||||
@ -13,7 +13,7 @@ Package: frr
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, logrotate (>= 3.2-11), ${misc:Depends}
|
||||
Pre-Depends: adduser
|
||||
Conflicts: zebra, zebra-pj
|
||||
Conflicts: zebra, zebra-pj, quagga
|
||||
Replaces: zebra, zebra-pj
|
||||
Suggests: snmpd
|
||||
Description: BGP/OSPF/RIP/RIPng/ISIS/PIM/LDP routing daemon forked from Quagga
|
||||
|
||||
@ -13,7 +13,7 @@ Package: frr
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, logrotate (>= 3.2-11), ${misc:Depends}
|
||||
Pre-Depends: adduser
|
||||
Conflicts: zebra, zebra-pj
|
||||
Conflicts: zebra, zebra-pj, quagga
|
||||
Replaces: zebra, zebra-pj
|
||||
Suggests: snmpd
|
||||
Description: BGP/OSPF/RIP/RIPng/ISIS/PIM/LDP routing daemon forked from Quagga
|
||||
|
||||
@ -25,7 +25,7 @@ Add frr groups and user
|
||||
|
||||
sudo addgroup --system --gid 92 frr
|
||||
sudo addgroup --system --gid 85 frrvty
|
||||
sudo adduser --system --ingroup frr --home /var/run/frr/ \
|
||||
sudo adduser --system --ingroup frr --home /var/opt/frr/ \
|
||||
--gecos "FRR suite" --shell /bin/false frr
|
||||
sudo usermod -a -G frrvty frr
|
||||
|
||||
@ -43,7 +43,7 @@ an example.)
|
||||
./bootstrap.sh
|
||||
./configure \
|
||||
--enable-exampledir=/usr/share/doc/frr/examples/ \
|
||||
--localstatedir=/var/run/frr \
|
||||
--localstatedir=/var/opt/frr \
|
||||
--sbindir=/usr/lib/frr \
|
||||
--sysconfdir=/etc/frr \
|
||||
--enable-vtysh \
|
||||
@ -73,6 +73,7 @@ Create empty FRR configuration files
|
||||
::
|
||||
|
||||
sudo install -m 755 -o frr -g frr -d /var/log/frr
|
||||
sudo install -m 755 -o frr -g frr -d /var/opt/frr
|
||||
sudo install -m 775 -o frr -g frrvty -d /etc/frr
|
||||
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
|
||||
sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
|
||||
@ -106,32 +107,18 @@ other settings)
|
||||
system
|
||||
|
||||
Troubleshooting
|
||||
~~~~~~~~~~~~~~~
|
||||
---------------
|
||||
|
||||
**Local state directory**
|
||||
|
||||
The local state directory must exist and have the correct permissions
|
||||
applied for the frrouting daemons to start. In the above ./configure
|
||||
example the local state directory is set to /var/run/frr
|
||||
(--localstatedir=/var/run/frr) Debian considers /var/run/frr to be
|
||||
temporary and this is removed after a reboot.
|
||||
|
||||
When using a different local state directory you need to create the new
|
||||
directory and change the ownership to the frr user, for example:
|
||||
|
||||
::
|
||||
|
||||
mkdir /var/opt/frr
|
||||
chown frr /var/opt/frr
|
||||
|
||||
**Shared library error**
|
||||
Shared library error
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you try and start any of the frrouting daemons you may see the below
|
||||
error due to the frrouting shared library directory not being found:
|
||||
|
||||
::
|
||||
|
||||
./zebra: error while loading shared libraries: libfrr.so.0: cannot open shared object file: No such file or directory
|
||||
./zebra: error while loading shared libraries: libfrr.so.0: cannot open
|
||||
shared object file: No such file or directory
|
||||
|
||||
The fix is to add the following line to /etc/ld.so.conf which will
|
||||
continue to reference the library directory after the system reboots. To
|
||||
@ -140,5 +127,5 @@ after adding the line to the file eg:
|
||||
|
||||
::
|
||||
|
||||
echo include /usr/local/lib >> /etc/ld.so.conf
|
||||
ldconfig
|
||||
echo include /usr/local/lib >> /etc/ld.so.conf
|
||||
ldconfig
|
||||
|
||||
@ -366,7 +366,6 @@ void eigrp_zebra_route_add(struct prefix *p, struct list *successors)
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_EIGRP;
|
||||
api.safi = SAFI_UNICAST;
|
||||
memcpy(&api.prefix, p, sizeof(*p));
|
||||
@ -378,6 +377,7 @@ void eigrp_zebra_route_add(struct prefix *p, struct list *successors)
|
||||
if (count >= MULTIPATH_NUM)
|
||||
break;
|
||||
api_nh = &api.nexthops[count];
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
if (te->adv_router->src.s_addr) {
|
||||
api_nh->gate.ipv4 = te->adv_router->src;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
@ -408,7 +408,6 @@ void eigrp_zebra_route_delete(struct prefix *p)
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_EIGRP;
|
||||
api.safi = SAFI_UNICAST;
|
||||
memcpy(&api.prefix, p, sizeof(*p));
|
||||
|
||||
@ -6,7 +6,7 @@ import sys, re, subprocess, os
|
||||
|
||||
# find all DEFUNs
|
||||
defun_re = re.compile(
|
||||
r'^(DEF(UN(_NOSH|_HIDDEN)?|PY)\s*\(.*?)^(?=\s*\{)',
|
||||
r'^((DEF(UN(_NOSH|_HIDDEN)?|PY)|ALIAS)\s*\(.*?)^(?=\s*\{)',
|
||||
re.M | re.S)
|
||||
define_re = re.compile(
|
||||
r'((^#\s*define[^\n]+[^\\]\n)+)',
|
||||
|
||||
@ -293,6 +293,7 @@ void isis_circuit_del_addr(struct isis_circuit *circuit,
|
||||
|
||||
if (ip) {
|
||||
listnode_delete(circuit->ip_addrs, ip);
|
||||
prefix_ipv4_free(ip);
|
||||
if (circuit->area)
|
||||
lsp_regenerate_schedule(circuit->area,
|
||||
circuit->is_type, 0);
|
||||
@ -328,6 +329,7 @@ void isis_circuit_del_addr(struct isis_circuit *circuit,
|
||||
}
|
||||
if (ip6) {
|
||||
listnode_delete(circuit->ipv6_link, ip6);
|
||||
prefix_ipv6_free(ip6);
|
||||
found = 1;
|
||||
}
|
||||
} else {
|
||||
@ -339,6 +341,7 @@ void isis_circuit_del_addr(struct isis_circuit *circuit,
|
||||
}
|
||||
if (ip6) {
|
||||
listnode_delete(circuit->ipv6_non_link, ip6);
|
||||
prefix_ipv6_free(ip6);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
@ -554,7 +557,7 @@ void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream)
|
||||
|
||||
void isis_circuit_prepare(struct isis_circuit *circuit)
|
||||
{
|
||||
#ifdef GNU_LINUX
|
||||
#if ISIS_METHOD != ISIS_METHOD_DLPI
|
||||
thread_add_read(master, isis_receive, circuit, circuit->fd,
|
||||
&circuit->t_read);
|
||||
#else
|
||||
|
||||
@ -261,7 +261,6 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_ISIS;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = *prefix;
|
||||
@ -281,6 +280,7 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
|
||||
if (count >= MULTIPATH_NUM)
|
||||
break;
|
||||
api_nh = &api.nexthops[count];
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
/* FIXME: can it be ? */
|
||||
if (nexthop->ip.s_addr != INADDR_ANY) {
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
@ -303,6 +303,7 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
|
||||
}
|
||||
|
||||
api_nh = &api.nexthops[count];
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
api_nh->gate.ipv6 = nexthop6->ip6;
|
||||
api_nh->ifindex = nexthop6->ifindex;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
@ -330,7 +331,6 @@ static void isis_zebra_route_del_route(struct prefix *prefix,
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_ISIS;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = *prefix;
|
||||
|
||||
@ -320,9 +320,9 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
|
||||
/* do not accept invalid labels */
|
||||
if (label > MPLS_LABEL_MAX ||
|
||||
(label <= MPLS_LABEL_RESERVED_MAX &&
|
||||
label != MPLS_LABEL_IPV4NULL &&
|
||||
label != MPLS_LABEL_IPV6NULL &&
|
||||
label != MPLS_LABEL_IMPLNULL)) {
|
||||
label != MPLS_LABEL_IPV4_EXPLICIT_NULL &&
|
||||
label != MPLS_LABEL_IPV6_EXPLICIT_NULL &&
|
||||
label != MPLS_LABEL_IMPLICIT_NULL)) {
|
||||
session_shutdown(nbr, S_BAD_TLV_VAL,
|
||||
msg.id, msg.type);
|
||||
goto err;
|
||||
@ -396,7 +396,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
|
||||
case MAP_TYPE_PREFIX:
|
||||
switch (me->map.fec.prefix.af) {
|
||||
case AF_INET:
|
||||
if (label == MPLS_LABEL_IPV6NULL) {
|
||||
if (label == MPLS_LABEL_IPV6_EXPLICIT_NULL) {
|
||||
session_shutdown(nbr, S_BAD_TLV_VAL,
|
||||
msg.id, msg.type);
|
||||
goto err;
|
||||
@ -405,7 +405,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
|
||||
goto next;
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (label == MPLS_LABEL_IPV4NULL) {
|
||||
if (label == MPLS_LABEL_IPV4_EXPLICIT_NULL) {
|
||||
session_shutdown(nbr, S_BAD_TLV_VAL,
|
||||
msg.id, msg.type);
|
||||
goto err;
|
||||
|
||||
22
ldpd/lde.c
22
ldpd/lde.c
@ -702,20 +702,20 @@ lde_update_label(struct fec_node *fn)
|
||||
switch (fn->fec.type) {
|
||||
case FEC_TYPE_IPV4:
|
||||
if (!(ldeconf->ipv4.flags & F_LDPD_AF_EXPNULL))
|
||||
return (MPLS_LABEL_IMPLNULL);
|
||||
return (MPLS_LABEL_IMPLICIT_NULL);
|
||||
if (lde_acl_check(ldeconf->ipv4.acl_label_expnull_for,
|
||||
AF_INET, (union ldpd_addr *)&fn->fec.u.ipv4.prefix,
|
||||
fn->fec.u.ipv4.prefixlen) != FILTER_PERMIT)
|
||||
return (MPLS_LABEL_IMPLNULL);
|
||||
return (MPLS_LABEL_IPV4NULL);
|
||||
return (MPLS_LABEL_IMPLICIT_NULL);
|
||||
return MPLS_LABEL_IPV4_EXPLICIT_NULL;
|
||||
case FEC_TYPE_IPV6:
|
||||
if (!(ldeconf->ipv6.flags & F_LDPD_AF_EXPNULL))
|
||||
return (MPLS_LABEL_IMPLNULL);
|
||||
return (MPLS_LABEL_IMPLICIT_NULL);
|
||||
if (lde_acl_check(ldeconf->ipv6.acl_label_expnull_for,
|
||||
AF_INET6, (union ldpd_addr *)&fn->fec.u.ipv6.prefix,
|
||||
fn->fec.u.ipv6.prefixlen) != FILTER_PERMIT)
|
||||
return (MPLS_LABEL_IMPLNULL);
|
||||
return (MPLS_LABEL_IPV6NULL);
|
||||
return (MPLS_LABEL_IMPLICIT_NULL);
|
||||
return MPLS_LABEL_IPV6_EXPLICIT_NULL;
|
||||
default:
|
||||
fatalx("lde_update_label: unexpected fec type");
|
||||
break;
|
||||
@ -1522,11 +1522,15 @@ lde_change_egress_label(int af)
|
||||
|
||||
/* explicitly withdraw all null labels */
|
||||
RB_FOREACH(ln, nbr_tree, &lde_nbrs) {
|
||||
lde_send_labelwithdraw_wcard(ln, MPLS_LABEL_IMPLNULL);
|
||||
lde_send_labelwithdraw_wcard(ln, MPLS_LABEL_IMPLICIT_NULL);
|
||||
if (ln->v4_enabled)
|
||||
lde_send_labelwithdraw_wcard(ln, MPLS_LABEL_IPV4NULL);
|
||||
lde_send_labelwithdraw_wcard(
|
||||
ln,
|
||||
MPLS_LABEL_IPV4_EXPLICIT_NULL);
|
||||
if (ln->v6_enabled)
|
||||
lde_send_labelwithdraw_wcard(ln, MPLS_LABEL_IPV6NULL);
|
||||
lde_send_labelwithdraw_wcard(
|
||||
ln,
|
||||
MPLS_LABEL_IPV6_EXPLICIT_NULL);
|
||||
}
|
||||
|
||||
/* update label of connected routes */
|
||||
|
||||
@ -115,11 +115,11 @@ log_label(uint32_t label)
|
||||
case NO_LABEL:
|
||||
snprintf(buf, TF_LEN, "-");
|
||||
break;
|
||||
case MPLS_LABEL_IMPLNULL:
|
||||
case MPLS_LABEL_IMPLICIT_NULL:
|
||||
snprintf(buf, TF_LEN, "imp-null");
|
||||
break;
|
||||
case MPLS_LABEL_IPV4NULL:
|
||||
case MPLS_LABEL_IPV6NULL:
|
||||
case MPLS_LABEL_IPV4_EXPLICIT_NULL:
|
||||
case MPLS_LABEL_IPV6_EXPLICIT_NULL:
|
||||
snprintf(buf, TF_LEN, "exp-null");
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -929,6 +929,7 @@ static const struct zebra_desc_table command_types[] = {
|
||||
DESC_ENTRY(ZEBRA_VRF_UNREGISTER),
|
||||
DESC_ENTRY(ZEBRA_VRF_ADD),
|
||||
DESC_ENTRY(ZEBRA_VRF_DELETE),
|
||||
DESC_ENTRY(ZEBRA_VRF_LABEL),
|
||||
DESC_ENTRY(ZEBRA_INTERFACE_VRF_UPDATE),
|
||||
DESC_ENTRY(ZEBRA_BFD_CLIENT_REGISTER),
|
||||
DESC_ENTRY(ZEBRA_INTERFACE_ENABLE_RADV),
|
||||
@ -943,6 +944,7 @@ static const struct zebra_desc_table command_types[] = {
|
||||
DESC_ENTRY(ZEBRA_RELEASE_LABEL_CHUNK),
|
||||
DESC_ENTRY(ZEBRA_ADVERTISE_ALL_VNI),
|
||||
DESC_ENTRY(ZEBRA_ADVERTISE_DEFAULT_GW),
|
||||
DESC_ENTRY(ZEBRA_ADVERTISE_SUBNET),
|
||||
DESC_ENTRY(ZEBRA_VNI_ADD),
|
||||
DESC_ENTRY(ZEBRA_VNI_DEL),
|
||||
DESC_ENTRY(ZEBRA_L3VNI_ADD),
|
||||
@ -951,6 +953,8 @@ static const struct zebra_desc_table command_types[] = {
|
||||
DESC_ENTRY(ZEBRA_REMOTE_VTEP_DEL),
|
||||
DESC_ENTRY(ZEBRA_MACIP_ADD),
|
||||
DESC_ENTRY(ZEBRA_MACIP_DEL),
|
||||
DESC_ENTRY(ZEBRA_IP_PREFIX_ROUTE_ADD),
|
||||
DESC_ENTRY(ZEBRA_IP_PREFIX_ROUTE_DEL),
|
||||
DESC_ENTRY(ZEBRA_REMOTE_MACIP_ADD),
|
||||
DESC_ENTRY(ZEBRA_REMOTE_MACIP_DEL),
|
||||
DESC_ENTRY(ZEBRA_PW_ADD),
|
||||
|
||||
63
lib/mpls.h
63
lib/mpls.h
@ -24,21 +24,27 @@
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#ifdef MPLS_LABEL_MAX
|
||||
#undef MPLS_LABEL_MAX
|
||||
#endif
|
||||
|
||||
/* Well-known MPLS label values (RFC 3032 etc). */
|
||||
#define MPLS_V4_EXP_NULL_LABEL 0
|
||||
#define MPLS_RA_LABEL 1
|
||||
#define MPLS_V6_EXP_NULL_LABEL 2
|
||||
#define MPLS_IMP_NULL_LABEL 3
|
||||
#define MPLS_ENTROPY_LABEL_INDICATOR 7
|
||||
#define MPLS_GAL_LABEL 13
|
||||
#define MPLS_OAM_ALERT_LABEL 14
|
||||
#define MPLS_EXTENSION_LABEL 15
|
||||
#define MPLS_LABEL_IPV4_EXPLICIT_NULL 0 /* [RFC3032] */
|
||||
#define MPLS_LABEL_ROUTER_ALERT 1 /* [RFC3032] */
|
||||
#define MPLS_LABEL_IPV6_EXPLICIT_NULL 2 /* [RFC3032] */
|
||||
#define MPLS_LABEL_IMPLICIT_NULL 3 /* [RFC3032] */
|
||||
#define MPLS_LABEL_ELI 7 /* [RFC6790] */
|
||||
#define MPLS_LABEL_GAL 13 /* [RFC5586] */
|
||||
#define MPLS_LABEL_OAM_ALERT 14 /* [RFC3429] */
|
||||
#define MPLS_LABEL_EXTENSION 15 /* [RFC7274] */
|
||||
#define MPLS_LABEL_MAX 1048575
|
||||
#define MPLS_LABEL_NONE 0xFFFFFFFF /* for internal use only */
|
||||
|
||||
/* Minimum and maximum label values */
|
||||
#define MPLS_MIN_RESERVED_LABEL 0
|
||||
#define MPLS_MAX_RESERVED_LABEL 15
|
||||
#define MPLS_MIN_UNRESERVED_LABEL 16
|
||||
#define MPLS_MAX_UNRESERVED_LABEL 1048575
|
||||
#define MPLS_LABEL_RESERVED_MIN 0
|
||||
#define MPLS_LABEL_RESERVED_MAX 15
|
||||
#define MPLS_LABEL_UNRESERVED_MIN 16
|
||||
#define MPLS_LABEL_UNRESERVED_MAX 1048575
|
||||
|
||||
/* Default min and max SRGB label range */
|
||||
/* Even if the SRGB allows to manage different Label space between routers,
|
||||
@ -56,11 +62,11 @@
|
||||
#define MPLS_MAX_LABELS 16
|
||||
|
||||
#define IS_MPLS_RESERVED_LABEL(label) \
|
||||
(label >= MPLS_MIN_RESERVED_LABEL && label <= MPLS_MAX_RESERVED_LABEL)
|
||||
(label >= MPLS_LABEL_RESERVED_MIN && label <= MPLS_LABEL_RESERVED_MAX)
|
||||
|
||||
#define IS_MPLS_UNRESERVED_LABEL(label) \
|
||||
(label >= MPLS_MIN_UNRESERVED_LABEL \
|
||||
&& label <= MPLS_MAX_UNRESERVED_LABEL)
|
||||
(label >= MPLS_LABEL_UNRESERVED_MIN \
|
||||
&& label <= MPLS_LABEL_UNRESERVED_MAX)
|
||||
|
||||
/* Definitions for a MPLS label stack entry (RFC 3032). This encodes the
|
||||
* label, EXP, BOS and TTL fields.
|
||||
@ -109,7 +115,8 @@ enum lsp_types_t {
|
||||
ZEBRA_LSP_STATIC = 1, /* Static LSP. */
|
||||
ZEBRA_LSP_LDP = 2, /* LDP LSP. */
|
||||
ZEBRA_LSP_BGP = 3, /* BGP LSP. */
|
||||
ZEBRA_LSP_SR = 4 /* Segment Routing LSP. */
|
||||
ZEBRA_LSP_SR = 4, /* Segment Routing LSP. */
|
||||
ZEBRA_LSP_SHARP = 5, /* Identifier for test protocol */
|
||||
};
|
||||
|
||||
/* Functions for basic label operations. */
|
||||
@ -153,28 +160,28 @@ static inline void mpls_lse_decode(mpls_lse_t lse, mpls_label_t *label,
|
||||
static inline char *label2str(mpls_label_t label, char *buf, size_t len)
|
||||
{
|
||||
switch (label) {
|
||||
case MPLS_V4_EXP_NULL_LABEL:
|
||||
case MPLS_LABEL_IPV4_EXPLICIT_NULL:
|
||||
strlcpy(buf, "IPv4 Explicit Null", len);
|
||||
return (buf);
|
||||
case MPLS_RA_LABEL:
|
||||
case MPLS_LABEL_ROUTER_ALERT:
|
||||
strlcpy(buf, "Router Alert", len);
|
||||
return (buf);
|
||||
case MPLS_V6_EXP_NULL_LABEL:
|
||||
case MPLS_LABEL_IPV6_EXPLICIT_NULL:
|
||||
strlcpy(buf, "IPv6 Explict Null", len);
|
||||
return (buf);
|
||||
case MPLS_IMP_NULL_LABEL:
|
||||
case MPLS_LABEL_IMPLICIT_NULL:
|
||||
strlcpy(buf, "implicit-null", len);
|
||||
return (buf);
|
||||
case MPLS_ENTROPY_LABEL_INDICATOR:
|
||||
case MPLS_LABEL_ELI:
|
||||
strlcpy(buf, "Entropy Label Indicator", len);
|
||||
return (buf);
|
||||
case MPLS_GAL_LABEL:
|
||||
case MPLS_LABEL_GAL:
|
||||
strlcpy(buf, "Generic Associated Channel", len);
|
||||
return (buf);
|
||||
case MPLS_OAM_ALERT_LABEL:
|
||||
case MPLS_LABEL_OAM_ALERT:
|
||||
strlcpy(buf, "OAM Alert", len);
|
||||
return (buf);
|
||||
case MPLS_EXTENSION_LABEL:
|
||||
case MPLS_LABEL_EXTENSION:
|
||||
strlcpy(buf, "Extension", len);
|
||||
return (buf);
|
||||
default:
|
||||
@ -186,13 +193,5 @@ static inline char *label2str(mpls_label_t label, char *buf, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
/* constants used by ldpd */
|
||||
#define MPLS_LABEL_IPV4NULL 0 /* IPv4 Explicit NULL Label */
|
||||
#define MPLS_LABEL_RTALERT 1 /* Router Alert Label */
|
||||
#define MPLS_LABEL_IPV6NULL 2 /* IPv6 Explicit NULL Label */
|
||||
#define MPLS_LABEL_IMPLNULL 3 /* Implicit NULL Label */
|
||||
/* MPLS_LABEL_RESERVED 4-15 */ /* Values 4-15 are reserved */
|
||||
#define MPLS_LABEL_RESERVED_MAX 15
|
||||
#define MPLS_LABEL_MAX ((1 << 20) - 1)
|
||||
|
||||
#endif
|
||||
|
||||
@ -167,6 +167,7 @@ void copy_nexthops(struct nexthop **tnh, struct nexthop *nh,
|
||||
|
||||
for (nh1 = nh; nh1; nh1 = nh1->next) {
|
||||
nexthop = nexthop_new();
|
||||
nexthop->vrf_id = nh1->vrf_id;
|
||||
nexthop->ifindex = nh1->ifindex;
|
||||
nexthop->type = nh1->type;
|
||||
nexthop->flags = nh1->flags;
|
||||
|
||||
@ -60,6 +60,11 @@ struct nexthop {
|
||||
struct nexthop *next;
|
||||
struct nexthop *prev;
|
||||
|
||||
/*
|
||||
* What vrf is this nexthop associated with?
|
||||
*/
|
||||
vrf_id_t vrf_id;
|
||||
|
||||
/* Interface index. */
|
||||
ifindex_t ifindex;
|
||||
|
||||
@ -116,18 +121,6 @@ struct nexthop {
|
||||
(nexthop); \
|
||||
(nexthop) = nexthop_next(nexthop)
|
||||
|
||||
extern int zebra_rnh_ip_default_route;
|
||||
extern int zebra_rnh_ipv6_default_route;
|
||||
|
||||
static inline int nh_resolve_via_default(int family)
|
||||
{
|
||||
if (((family == AF_INET) && zebra_rnh_ip_default_route)
|
||||
|| ((family == AF_INET6) && zebra_rnh_ipv6_default_route))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nexthop *nexthop_new(void);
|
||||
void nexthop_add(struct nexthop **target, struct nexthop *nexthop);
|
||||
|
||||
|
||||
41
lib/vrf.c
41
lib/vrf.c
@ -141,7 +141,9 @@ struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
|
||||
return vrf;
|
||||
}
|
||||
|
||||
/* Delete a VRF. This is called in vrf_terminate(). */
|
||||
/* Delete a VRF. This is called when the underlying VRF goes away, a
|
||||
* pre-configured VRF is deleted or when shutting down (vrf_terminate()).
|
||||
*/
|
||||
void vrf_delete(struct vrf *vrf)
|
||||
{
|
||||
if (debug_vrf)
|
||||
@ -150,6 +152,23 @@ void vrf_delete(struct vrf *vrf)
|
||||
if (vrf_is_enabled(vrf))
|
||||
vrf_disable(vrf);
|
||||
|
||||
/* If the VRF is user configured, it'll stick around, just remove
|
||||
* the ID mapping. Interfaces assigned to this VRF should've been
|
||||
* removed already as part of the VRF going down.
|
||||
*/
|
||||
if (vrf_is_user_cfged(vrf)) {
|
||||
if (vrf->vrf_id != VRF_UNKNOWN) {
|
||||
/* Delete any VRF interfaces - should be only
|
||||
* the VRF itself, other interfaces should've
|
||||
* been moved out of the VRF.
|
||||
*/
|
||||
if_terminate(vrf);
|
||||
RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
|
||||
vrf->vrf_id = VRF_UNKNOWN;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (vrf_master.vrf_delete_hook)
|
||||
(*vrf_master.vrf_delete_hook)(vrf);
|
||||
|
||||
@ -172,14 +191,6 @@ struct vrf *vrf_lookup_by_id(vrf_id_t vrf_id)
|
||||
return (RB_FIND(vrf_id_head, &vrfs_by_id, &vrf));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the VRF is enabled.
|
||||
*/
|
||||
static int vrf_is_enabled(struct vrf *vrf)
|
||||
{
|
||||
return vrf && CHECK_FLAG(vrf->status, VRF_ACTIVE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable a VRF - that is, let the VRF be ready to use.
|
||||
* The VRF_ENABLE_HOOK callback will be called to inform
|
||||
@ -408,10 +419,16 @@ void vrf_terminate(void)
|
||||
zlog_debug("%s: Shutting down vrf subsystem",
|
||||
__PRETTY_FUNCTION__);
|
||||
|
||||
while ((vrf = RB_ROOT(vrf_id_head, &vrfs_by_id)) != NULL)
|
||||
while ((vrf = RB_ROOT(vrf_id_head, &vrfs_by_id)) != NULL) {
|
||||
/* Clear configured flag and invoke delete. */
|
||||
UNSET_FLAG(vrf->status, VRF_CONFIGURED);
|
||||
vrf_delete(vrf);
|
||||
while ((vrf = RB_ROOT(vrf_name_head, &vrfs_by_name)) != NULL)
|
||||
}
|
||||
while ((vrf = RB_ROOT(vrf_name_head, &vrfs_by_name)) != NULL) {
|
||||
/* Clear configured flag and invoke delete. */
|
||||
UNSET_FLAG(vrf->status, VRF_CONFIGURED);
|
||||
vrf_delete(vrf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a socket for the VRF. */
|
||||
@ -473,6 +490,8 @@ DEFUN_NOSH (no_vrf,
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* Clear configured flag and invoke delete. */
|
||||
UNSET_FLAG(vrfp->status, VRF_CONFIGURED);
|
||||
vrf_delete(vrfp);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
||||
29
lib/vrf.h
29
lib/vrf.h
@ -75,7 +75,8 @@ struct vrf {
|
||||
|
||||
/* Zebra internal VRF status */
|
||||
u_char status;
|
||||
#define VRF_ACTIVE (1 << 0)
|
||||
#define VRF_ACTIVE (1 << 0) /* VRF is up in kernel */
|
||||
#define VRF_CONFIGURED (1 << 1) /* VRF has some FRR configuration */
|
||||
|
||||
/* Interfaces belonging to this VRF */
|
||||
struct if_name_head ifaces_by_name;
|
||||
@ -119,6 +120,32 @@ extern vrf_id_t vrf_name_to_id(const char *);
|
||||
(V) = vrf->vrf_id; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Check whether the VRF is enabled.
|
||||
*/
|
||||
static inline int vrf_is_enabled(struct vrf *vrf)
|
||||
{
|
||||
return vrf && CHECK_FLAG(vrf->status, VRF_ACTIVE);
|
||||
}
|
||||
|
||||
/* check if the vrf is user configured */
|
||||
static inline int vrf_is_user_cfged(struct vrf *vrf)
|
||||
{
|
||||
return vrf && CHECK_FLAG(vrf->status, VRF_CONFIGURED);
|
||||
}
|
||||
|
||||
/* Mark that VRF has user configuration */
|
||||
static inline void vrf_set_user_cfged(struct vrf *vrf)
|
||||
{
|
||||
SET_FLAG(vrf->status, VRF_CONFIGURED);
|
||||
}
|
||||
|
||||
/* Mark that VRF no longer has any user configuration */
|
||||
static inline void vrf_reset_user_cfged(struct vrf *vrf)
|
||||
{
|
||||
UNSET_FLAG(vrf->status, VRF_CONFIGURED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Utilities to obtain the user data
|
||||
*/
|
||||
|
||||
@ -363,6 +363,21 @@ static int zebra_hello_send(struct zclient *zclient)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id,
|
||||
mpls_label_t label, enum lsp_types_t ltype)
|
||||
{
|
||||
struct stream *s;
|
||||
|
||||
s = zclient->obuf;
|
||||
stream_reset(s);
|
||||
|
||||
zclient_create_header(s, ZEBRA_VRF_LABEL, vrf_id);
|
||||
stream_putl(s, label);
|
||||
stream_putc(s, ltype);
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
zclient_send_message(zclient);
|
||||
}
|
||||
|
||||
/* Send register requests to zebra daemon for the information in a VRF. */
|
||||
void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
|
||||
{
|
||||
@ -975,12 +990,11 @@ int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api)
|
||||
}
|
||||
|
||||
stream_putw(s, api->nexthop_num);
|
||||
if (api->nexthop_num)
|
||||
stream_putl(s, api->nh_vrf_id);
|
||||
|
||||
for (i = 0; i < api->nexthop_num; i++) {
|
||||
api_nh = &api->nexthops[i];
|
||||
|
||||
stream_putl(s, api_nh->vrf_id);
|
||||
stream_putc(s, api_nh->type);
|
||||
switch (api_nh->type) {
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
@ -1126,12 +1140,10 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (api->nexthop_num)
|
||||
STREAM_GETL(s, api->nh_vrf_id);
|
||||
|
||||
for (i = 0; i < api->nexthop_num; i++) {
|
||||
api_nh = &api->nexthops[i];
|
||||
|
||||
STREAM_GETL(s, api_nh->vrf_id);
|
||||
STREAM_GETC(s, api_nh->type);
|
||||
switch (api_nh->type) {
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
@ -1217,6 +1229,7 @@ struct nexthop *nexthop_from_zapi_nexthop(struct zapi_nexthop *znh)
|
||||
struct nexthop *n = nexthop_new();
|
||||
|
||||
n->type = znh->type;
|
||||
n->vrf_id = znh->vrf_id;
|
||||
n->ifindex = znh->ifindex;
|
||||
n->gate = znh->gate;
|
||||
|
||||
@ -1979,8 +1992,8 @@ int lm_get_label_chunk(struct zclient *zclient, u_char keep,
|
||||
__func__, *start, *end, keep, response_keep);
|
||||
}
|
||||
/* sanity */
|
||||
if (*start > *end || *start < MPLS_MIN_UNRESERVED_LABEL
|
||||
|| *end > MPLS_MAX_UNRESERVED_LABEL) {
|
||||
if (*start > *end || *start < MPLS_LABEL_UNRESERVED_MIN
|
||||
|| *end > MPLS_LABEL_UNRESERVED_MAX) {
|
||||
zlog_err("%s: Invalid Label chunk: %u - %u", __func__, *start,
|
||||
*end);
|
||||
return -1;
|
||||
@ -2333,6 +2346,16 @@ static int zclient_read(struct thread *thread)
|
||||
(*zclient->local_macip_del)(command, zclient, length,
|
||||
vrf_id);
|
||||
break;
|
||||
case ZEBRA_IP_PREFIX_ROUTE_ADD:
|
||||
if (zclient->local_ip_prefix_add)
|
||||
(*zclient->local_ip_prefix_add)(command, zclient,
|
||||
length, vrf_id);
|
||||
break;
|
||||
case ZEBRA_IP_PREFIX_ROUTE_DEL:
|
||||
if (zclient->local_ip_prefix_del)
|
||||
(*zclient->local_ip_prefix_del)(command, zclient,
|
||||
length, vrf_id);
|
||||
break;
|
||||
case ZEBRA_PW_STATUS_UPDATE:
|
||||
if (zclient->pw_status_update)
|
||||
(*zclient->pw_status_update)(command, zclient, length,
|
||||
|
||||
@ -93,6 +93,7 @@ typedef enum {
|
||||
ZEBRA_VRF_UNREGISTER,
|
||||
ZEBRA_VRF_ADD,
|
||||
ZEBRA_VRF_DELETE,
|
||||
ZEBRA_VRF_LABEL,
|
||||
ZEBRA_INTERFACE_VRF_UPDATE,
|
||||
ZEBRA_BFD_CLIENT_REGISTER,
|
||||
ZEBRA_INTERFACE_ENABLE_RADV,
|
||||
@ -109,6 +110,7 @@ typedef enum {
|
||||
ZEBRA_FEC_UNREGISTER,
|
||||
ZEBRA_FEC_UPDATE,
|
||||
ZEBRA_ADVERTISE_DEFAULT_GW,
|
||||
ZEBRA_ADVERTISE_SUBNET,
|
||||
ZEBRA_ADVERTISE_ALL_VNI,
|
||||
ZEBRA_VNI_ADD,
|
||||
ZEBRA_VNI_DEL,
|
||||
@ -118,6 +120,8 @@ typedef enum {
|
||||
ZEBRA_REMOTE_VTEP_DEL,
|
||||
ZEBRA_MACIP_ADD,
|
||||
ZEBRA_MACIP_DEL,
|
||||
ZEBRA_IP_PREFIX_ROUTE_ADD,
|
||||
ZEBRA_IP_PREFIX_ROUTE_DEL,
|
||||
ZEBRA_REMOTE_MACIP_ADD,
|
||||
ZEBRA_REMOTE_MACIP_DEL,
|
||||
ZEBRA_PW_ADD,
|
||||
@ -204,6 +208,8 @@ struct zclient {
|
||||
int (*local_vni_del)(int, struct zclient *, uint16_t, vrf_id_t);
|
||||
int (*local_l3vni_add)(int, struct zclient *, uint16_t, vrf_id_t);
|
||||
int (*local_l3vni_del)(int, struct zclient *, uint16_t, vrf_id_t);
|
||||
void (*local_ip_prefix_add)(int, struct zclient *, uint16_t, vrf_id_t);
|
||||
void (*local_ip_prefix_del)(int, struct zclient *, uint16_t, vrf_id_t);
|
||||
int (*local_macip_add)(int, struct zclient *, uint16_t, vrf_id_t);
|
||||
int (*local_macip_del)(int, struct zclient *, uint16_t, vrf_id_t);
|
||||
int (*pw_status_update)(int, struct zclient *, uint16_t, vrf_id_t);
|
||||
@ -234,6 +240,7 @@ struct zserv_header {
|
||||
|
||||
struct zapi_nexthop {
|
||||
enum nexthop_types_t type;
|
||||
vrf_id_t vrf_id;
|
||||
ifindex_t ifindex;
|
||||
union {
|
||||
union g_addr gate;
|
||||
@ -281,7 +288,6 @@ struct zapi_route {
|
||||
u_int32_t mtu;
|
||||
|
||||
vrf_id_t vrf_id;
|
||||
vrf_id_t nh_vrf_id;
|
||||
|
||||
struct ethaddr rmac;
|
||||
};
|
||||
@ -343,8 +349,8 @@ enum zapi_route_notify_owner {
|
||||
};
|
||||
|
||||
/* Zebra MAC types */
|
||||
#define ZEBRA_MAC_TYPE_STICKY 0x01 /* Sticky MAC*/
|
||||
#define ZEBRA_MAC_TYPE_GW 0x02 /* gateway (SVI) mac*/
|
||||
#define ZEBRA_MACIP_TYPE_STICKY 0x01 /* Sticky MAC*/
|
||||
#define ZEBRA_MACIP_TYPE_GW 0x02 /* gateway (SVI) mac*/
|
||||
|
||||
struct zclient_options {
|
||||
bool receive_notify;
|
||||
@ -377,6 +383,17 @@ extern u_short *redist_check_instance(struct redist_proto *, u_short);
|
||||
extern void redist_add_instance(struct redist_proto *, u_short);
|
||||
extern void redist_del_instance(struct redist_proto *, u_short);
|
||||
|
||||
/*
|
||||
* Send to zebra that the specified vrf is using label to resolve
|
||||
* itself for L3VPN's. Repeated calls of this function with
|
||||
* different labels will cause an effective update of the
|
||||
* label for lookup. If you pass in MPLS_LABEL_NONE
|
||||
* we will cause a delete action and remove this label pop
|
||||
* operation.
|
||||
*/
|
||||
extern void zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id,
|
||||
mpls_label_t label, enum lsp_types_t ltype);
|
||||
|
||||
extern void zclient_send_reg_requests(struct zclient *, vrf_id_t);
|
||||
extern void zclient_send_dereg_requests(struct zclient *, vrf_id_t);
|
||||
|
||||
@ -500,6 +517,7 @@ static inline void zapi_route_set_blackhole(struct zapi_route *api,
|
||||
{
|
||||
api->nexthop_num = 1;
|
||||
api->nexthops[0].type = NEXTHOP_TYPE_BLACKHOLE;
|
||||
api->nexthops[0].vrf_id = VRF_DEFAULT;
|
||||
api->nexthops[0].bh_type = bh_type;
|
||||
SET_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP);
|
||||
};
|
||||
|
||||
@ -96,7 +96,6 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix
|
||||
api.type = ZEBRA_ROUTE_NHRP;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.prefix = *p;
|
||||
|
||||
switch (type) {
|
||||
@ -120,6 +119,7 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
api.nexthop_num = 1;
|
||||
api_nh = &api.nexthops[0];
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
|
||||
switch (api.prefix.family) {
|
||||
case AF_INET:
|
||||
|
||||
@ -148,6 +148,32 @@ static void ospf6_as_external_lsa_originate(struct ospf6_route *route)
|
||||
ospf6_lsa_originate_process(lsa, ospf6);
|
||||
}
|
||||
|
||||
int ospf6_orig_as_external_lsa(struct thread *thread)
|
||||
{
|
||||
struct ospf6_interface *oi;
|
||||
struct ospf6_lsa *lsa;
|
||||
uint32_t type, adv_router;
|
||||
|
||||
oi = (struct ospf6_interface *)THREAD_ARG(thread);
|
||||
oi->thread_as_extern_lsa = NULL;
|
||||
|
||||
if (oi->state == OSPF6_INTERFACE_DOWN)
|
||||
return 0;
|
||||
|
||||
type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
|
||||
adv_router = oi->area->ospf6->router_id;
|
||||
for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, adv_router, lsa)) {
|
||||
if (IS_OSPF6_DEBUG_ASBR)
|
||||
zlog_debug("%s: Send update of AS-External LSA %s seq 0x%x",
|
||||
__PRETTY_FUNCTION__, lsa->name,
|
||||
ntohl(lsa->header->seqnum));
|
||||
|
||||
ospf6_flood_interface(NULL, lsa, oi);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static route_tag_t ospf6_as_external_lsa_get_tag(struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_as_external_lsa *external;
|
||||
|
||||
@ -192,10 +192,6 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa)
|
||||
struct timeval now;
|
||||
struct ospf6_lsa *old;
|
||||
|
||||
if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)
|
||||
|| IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type))
|
||||
zlog_debug("Install LSA: %s", lsa->name);
|
||||
|
||||
/* Remove the old instance from all neighbors' Link state
|
||||
retransmission list (RFC2328 13.2 last paragraph) */
|
||||
old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
|
||||
@ -237,6 +233,13 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa)
|
||||
ospf6_lsa_checksum(lsa->header);
|
||||
}
|
||||
|
||||
if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)
|
||||
|| IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type))
|
||||
zlog_debug("%s Install LSA: %s age %d seqnum %x in LSDB.",
|
||||
__PRETTY_FUNCTION__, lsa->name,
|
||||
ntohs(lsa->header->age),
|
||||
ntohl(lsa->header->seqnum));
|
||||
|
||||
/* actually install */
|
||||
lsa->installed = now;
|
||||
ospf6_lsdb_add(lsa, lsa->lsdb);
|
||||
@ -246,7 +249,7 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa)
|
||||
|
||||
/* RFC2740 section 3.5.2. Sending Link State Update packets */
|
||||
/* RFC2328 section 13.3 Next step in the flooding procedure */
|
||||
static void ospf6_flood_interface(struct ospf6_neighbor *from,
|
||||
void ospf6_flood_interface(struct ospf6_neighbor *from,
|
||||
struct ospf6_lsa *lsa,
|
||||
struct ospf6_interface *oi)
|
||||
{
|
||||
@ -343,15 +346,24 @@ static void ospf6_flood_interface(struct ospf6_neighbor *from,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* (d) add retrans-list, schedule retransmission */
|
||||
if (is_debug)
|
||||
zlog_debug("Add retrans-list of this neighbor");
|
||||
ospf6_increment_retrans_count(lsa);
|
||||
ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list);
|
||||
thread_add_timer(master, ospf6_lsupdate_send_neighbor, on,
|
||||
on->ospf6_if->rxmt_interval,
|
||||
&on->thread_send_lsupdate);
|
||||
retrans_added++;
|
||||
if (ospf6->inst_shutdown) {
|
||||
if (is_debug)
|
||||
zlog_debug("%s: Send LSA %s (age %d) update now",
|
||||
__PRETTY_FUNCTION__, lsa->name,
|
||||
ntohs(lsa->header->age));
|
||||
ospf6_lsupdate_send_neighbor_now(on, lsa);
|
||||
continue;
|
||||
} else {
|
||||
/* (d) add retrans-list, schedule retransmission */
|
||||
if (is_debug)
|
||||
zlog_debug("Add retrans-list of this neighbor");
|
||||
ospf6_increment_retrans_count(lsa);
|
||||
ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list);
|
||||
thread_add_timer(master, ospf6_lsupdate_send_neighbor,
|
||||
on, on->ospf6_if->rxmt_interval,
|
||||
&on->thread_send_lsupdate);
|
||||
retrans_added++;
|
||||
}
|
||||
}
|
||||
|
||||
/* (2) examin next interface if not added to retrans-list */
|
||||
@ -806,6 +818,17 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
|
||||
zlog_debug("Received is duplicated LSA");
|
||||
SET_FLAG(new->flag, OSPF6_LSA_DUPLICATE);
|
||||
}
|
||||
if (old->header->adv_router ==
|
||||
from->ospf6_if->area->ospf6->router_id
|
||||
&& OSPF6_LSA_IS_MAXAGE(new)) {
|
||||
ospf6_acknowledge_lsa(new, ismore_recent, from);
|
||||
ospf6_lsa_delete(new);
|
||||
if (is_debug)
|
||||
zlog_debug("%s: Received is self orig MAXAGE LSA %s, discard (ismore_recent %d)",
|
||||
__PRETTY_FUNCTION__, old->name,
|
||||
ismore_recent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* if no database copy or received is more recent */
|
||||
@ -959,12 +982,34 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
|
||||
"Send back directly and then discard");
|
||||
}
|
||||
|
||||
/* Neighbor router sent recent age for LSA,
|
||||
* Router could be restarted while current copy is
|
||||
* MAXAGEd and not removed.*/
|
||||
if (OSPF6_LSA_IS_MAXAGE(old) &&
|
||||
!OSPF6_LSA_IS_MAXAGE(new)) {
|
||||
|
||||
if (is_debug)
|
||||
zlog_debug("%s: Current copy of LSA %s is MAXAGE, but new has recent Age.",
|
||||
old->name,
|
||||
__PRETTY_FUNCTION__);
|
||||
|
||||
ospf6_lsa_purge(old);
|
||||
if (new->header->adv_router
|
||||
!= from->ospf6_if->area->
|
||||
ospf6->router_id)
|
||||
ospf6_flood(from, new);
|
||||
|
||||
ospf6_install_lsa(new);
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX, MinLSArrival check !? RFC 2328 13 (8) */
|
||||
|
||||
ospf6_lsdb_add(ospf6_lsa_copy(old),
|
||||
from->lsupdate_list);
|
||||
thread_add_event(master, ospf6_lsupdate_send_neighbor,
|
||||
from, 0, &from->thread_send_lsupdate);
|
||||
|
||||
ospf6_lsa_delete(new);
|
||||
return;
|
||||
}
|
||||
@ -972,7 +1017,6 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEFUN (debug_ospf6_flooding,
|
||||
debug_ospf6_flooding_cmd,
|
||||
"debug ospf6 flooding",
|
||||
|
||||
@ -58,5 +58,10 @@ extern void ospf6_install_lsa(struct ospf6_lsa *lsa);
|
||||
|
||||
extern int config_write_ospf6_debug_flood(struct vty *vty);
|
||||
extern void install_element_ospf6_debug_flood(void);
|
||||
extern void ospf6_flood_interface(struct ospf6_neighbor *from,
|
||||
struct ospf6_lsa *lsa,
|
||||
struct ospf6_interface *oi);
|
||||
extern int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor *on,
|
||||
struct ospf6_lsa *lsa);
|
||||
|
||||
#endif /* OSPF6_FLOOD_H */
|
||||
|
||||
@ -301,6 +301,7 @@ void ospf6_interface_disable(struct ospf6_interface *oi)
|
||||
THREAD_OFF(oi->thread_network_lsa);
|
||||
THREAD_OFF(oi->thread_link_lsa);
|
||||
THREAD_OFF(oi->thread_intra_prefix_lsa);
|
||||
THREAD_OFF(oi->thread_as_extern_lsa);
|
||||
}
|
||||
|
||||
static struct in6_addr *
|
||||
@ -532,6 +533,7 @@ static void ospf6_interface_state_change(u_char next_state,
|
||||
OSPF6_NETWORK_LSA_EXECUTE(oi);
|
||||
OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi);
|
||||
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
|
||||
OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi);
|
||||
} else if (prev_state == OSPF6_INTERFACE_DR
|
||||
|| next_state == OSPF6_INTERFACE_DR) {
|
||||
OSPF6_NETWORK_LSA_SCHEDULE(oi);
|
||||
|
||||
@ -108,6 +108,7 @@ struct ospf6_interface {
|
||||
struct thread *thread_network_lsa;
|
||||
struct thread *thread_link_lsa;
|
||||
struct thread *thread_intra_prefix_lsa;
|
||||
struct thread *thread_as_extern_lsa;
|
||||
|
||||
struct ospf6_route_table *route_connected;
|
||||
|
||||
|
||||
@ -185,11 +185,21 @@ struct ospf6_intra_prefix_lsa {
|
||||
0, &(oi)->thread_intra_prefix_lsa); \
|
||||
} while (0)
|
||||
|
||||
#define OSPF6_AS_EXTERN_LSA_SCHEDULE(oi) \
|
||||
do { \
|
||||
if (!CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \
|
||||
thread_add_event( \
|
||||
master, \
|
||||
ospf6_orig_as_external_lsa, oi, \
|
||||
0, &(oi)->thread_as_extern_lsa); \
|
||||
} while (0)
|
||||
|
||||
#define OSPF6_NETWORK_LSA_EXECUTE(oi) \
|
||||
do { \
|
||||
THREAD_OFF((oi)->thread_network_lsa); \
|
||||
thread_execute(master, ospf6_network_lsa_originate, oi, 0); \
|
||||
} while (0)
|
||||
|
||||
#define OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi) \
|
||||
do { \
|
||||
THREAD_OFF((oi)->thread_intra_prefix_lsa); \
|
||||
@ -198,6 +208,11 @@ struct ospf6_intra_prefix_lsa {
|
||||
0); \
|
||||
} while (0)
|
||||
|
||||
#define OSPF6_AS_EXTERN_LSA_EXECUTE(oi) \
|
||||
do { \
|
||||
THREAD_OFF((oi)->thread_as_extern_lsa); \
|
||||
thread_execute(master, ospf6_orig_as_external_lsa, oi, 0); \
|
||||
} while (0)
|
||||
|
||||
/* Function Prototypes */
|
||||
extern char *ospf6_router_lsdesc_lookup(u_char type, u_int32_t interface_id,
|
||||
@ -215,7 +230,7 @@ extern int ospf6_intra_prefix_lsa_originate_transit(struct thread *);
|
||||
extern int ospf6_intra_prefix_lsa_originate_stub(struct thread *);
|
||||
extern void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa);
|
||||
extern void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa);
|
||||
|
||||
extern int ospf6_orig_as_external_lsa(struct thread *thread);
|
||||
extern void ospf6_intra_route_calculation(struct ospf6_area *oa);
|
||||
extern void ospf6_intra_brouter_calculation(struct ospf6_area *oa);
|
||||
|
||||
|
||||
@ -706,6 +706,37 @@ int ospf6_lsa_refresh(struct thread *thread)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ospf6_flush_self_originated_lsas_now(void)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct ospf6_area *oa;
|
||||
struct ospf6_lsa *lsa;
|
||||
const struct route_node *end = NULL;
|
||||
uint32_t type, adv_router;
|
||||
|
||||
ospf6->inst_shutdown = 1;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
|
||||
end = ospf6_lsdb_head(oa->lsdb_self, 0, 0,
|
||||
ospf6->router_id, &lsa);
|
||||
while (lsa) {
|
||||
/* RFC 2328 (14.1): Set MAXAGE */
|
||||
lsa->header->age = htons(OSPF_LSA_MAXAGE);
|
||||
/* Flood MAXAGE LSA*/
|
||||
ospf6_flood(NULL, lsa);
|
||||
|
||||
lsa = ospf6_lsdb_next(end, lsa);
|
||||
}
|
||||
}
|
||||
|
||||
type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
|
||||
adv_router = ospf6->router_id;
|
||||
for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, adv_router, lsa)) {
|
||||
/* RFC 2328 (14.1): Set MAXAGE */
|
||||
lsa->header->age = htons(OSPF_LSA_MAXAGE);
|
||||
ospf6_flood(NULL, lsa);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fletcher Checksum -- Refer to RFC1008. */
|
||||
|
||||
|
||||
@ -253,5 +253,6 @@ extern void ospf6_lsa_terminate(void);
|
||||
extern int config_write_ospf6_debug_lsa(struct vty *vty);
|
||||
extern void install_element_ospf6_debug_lsa(void);
|
||||
extern void ospf6_lsa_age_set(struct ospf6_lsa *lsa);
|
||||
extern void ospf6_flush_self_originated_lsas_now(void);
|
||||
|
||||
#endif /* OSPF6_LSA_H */
|
||||
|
||||
@ -334,6 +334,7 @@ int ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb)
|
||||
}
|
||||
if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
|
||||
zlog_debug("Remove MaxAge %s", lsa->name);
|
||||
|
||||
if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED)) {
|
||||
UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
|
||||
/*
|
||||
|
||||
@ -2163,6 +2163,40 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor *on,
|
||||
struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_header *oh;
|
||||
struct ospf6_lsupdate *lsupdate;
|
||||
u_char *p;
|
||||
int lsa_cnt = 0;
|
||||
|
||||
memset(sendbuf, 0, iobuflen);
|
||||
oh = (struct ospf6_header *)sendbuf;
|
||||
lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
|
||||
+ sizeof(struct ospf6_header));
|
||||
|
||||
p = (u_char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
|
||||
ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
|
||||
memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header));
|
||||
p += OSPF6_LSA_SIZE(lsa->header);
|
||||
lsa_cnt++;
|
||||
|
||||
oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
|
||||
oh->length = htons(p - sendbuf);
|
||||
lsupdate->lsa_number = htonl(lsa_cnt);
|
||||
|
||||
if (IS_OSPF6_DEBUG_FLOODING ||
|
||||
IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
|
||||
zlog_debug("%s: Send lsupdate with lsa %s (age %u)",
|
||||
__PRETTY_FUNCTION__, lsa->name,
|
||||
ntohs(lsa->header->age));
|
||||
|
||||
ospf6_send_lsupdate(on, NULL, oh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ospf6_lsupdate_send_interface(struct thread *thread)
|
||||
{
|
||||
struct ospf6_interface *oi;
|
||||
|
||||
@ -189,6 +189,11 @@ static void ospf6_neighbor_state_change(u_char next_state,
|
||||
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(on->ospf6_if);
|
||||
}
|
||||
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(on->ospf6_if->area);
|
||||
|
||||
if (prev_state == OSPF6_NEIGHBOR_LOADING &&
|
||||
next_state == OSPF6_NEIGHBOR_FULL) {
|
||||
OSPF6_AS_EXTERN_LSA_SCHEDULE(on->ospf6_if);
|
||||
}
|
||||
}
|
||||
|
||||
if ((prev_state == OSPF6_NEIGHBOR_EXCHANGE
|
||||
|
||||
@ -315,6 +315,7 @@ void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route,
|
||||
if (i >= entries)
|
||||
return;
|
||||
|
||||
nexthops[i].vrf_id = VRF_DEFAULT;
|
||||
nexthops[i].ifindex = nh->ifindex;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&nh->address)) {
|
||||
nexthops[i].gate.ipv6 = nh->address;
|
||||
|
||||
@ -180,6 +180,8 @@ void ospf6_delete(struct ospf6 *o)
|
||||
struct ospf6_area *oa;
|
||||
|
||||
QOBJ_UNREG(o);
|
||||
|
||||
ospf6_flush_self_originated_lsas_now();
|
||||
ospf6_disable(ospf6);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
|
||||
|
||||
@ -94,6 +94,10 @@ struct ospf6 {
|
||||
|
||||
struct route_table *distance_table;
|
||||
|
||||
/* Used during ospf instance going down send LSDB
|
||||
* update to neighbors immediatly */
|
||||
uint8_t inst_shutdown;
|
||||
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
DECLARE_QOBJ_TYPE(ospf6)
|
||||
|
||||
@ -337,7 +337,6 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_OSPF6;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = *dest;
|
||||
@ -388,7 +387,6 @@ void ospf6_zebra_add_discard(struct ospf6_route *request)
|
||||
if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_OSPF6;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = *dest;
|
||||
@ -422,7 +420,6 @@ void ospf6_zebra_delete_discard(struct ospf6_route *request)
|
||||
if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_OSPF6;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = *dest;
|
||||
|
||||
@ -511,8 +511,8 @@ static int compute_link_nhlfe(struct sr_link *srl)
|
||||
srl->nhlfe[1].label_in =
|
||||
index2label(srl->sid[1], srl->srn->srgb);
|
||||
|
||||
srl->nhlfe[0].label_out = MPLS_IMP_NULL_LABEL;
|
||||
srl->nhlfe[1].label_out = MPLS_IMP_NULL_LABEL;
|
||||
srl->nhlfe[0].label_out = MPLS_LABEL_IMPLICIT_NULL;
|
||||
srl->nhlfe[1].label_out = MPLS_LABEL_IMPLICIT_NULL;
|
||||
|
||||
rc = 1;
|
||||
return rc;
|
||||
@ -599,7 +599,7 @@ static int compute_prefix_nhlfe(struct sr_prefix *srp)
|
||||
*/
|
||||
if ((srp->nexthop == NULL)
|
||||
&& (!CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)))
|
||||
srp->nhlfe.label_out = MPLS_IMP_NULL_LABEL;
|
||||
srp->nhlfe.label_out = MPLS_LABEL_IMPLICIT_NULL;
|
||||
else if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_VFLG))
|
||||
srp->nhlfe.label_out = srp->sid;
|
||||
else
|
||||
@ -694,7 +694,7 @@ static inline void add_sid_nhlfe(struct sr_nhlfe nhlfe)
|
||||
{
|
||||
if ((nhlfe.label_in != 0) && (nhlfe.label_out != 0)) {
|
||||
ospf_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_ADD, nhlfe);
|
||||
if (nhlfe.label_out != MPLS_IMP_NULL_LABEL)
|
||||
if (nhlfe.label_out != MPLS_LABEL_IMPLICIT_NULL)
|
||||
ospf_zebra_send_mpls_ftn(ZEBRA_ROUTE_ADD, nhlfe);
|
||||
}
|
||||
}
|
||||
@ -704,7 +704,7 @@ static inline void del_sid_nhlfe(struct sr_nhlfe nhlfe)
|
||||
{
|
||||
if ((nhlfe.label_in != 0) && (nhlfe.label_out != 0)) {
|
||||
ospf_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_DELETE, nhlfe);
|
||||
if (nhlfe.label_out != MPLS_IMP_NULL_LABEL)
|
||||
if (nhlfe.label_out != MPLS_LABEL_IMPLICIT_NULL)
|
||||
ospf_zebra_send_mpls_ftn(ZEBRA_ROUTE_DELETE, nhlfe);
|
||||
}
|
||||
}
|
||||
@ -1535,7 +1535,7 @@ void ospf_sr_update_prefix(struct interface *ifp, struct prefix *p)
|
||||
EXT_SUBTLV_PREFIX_SID_NPFLG)) {
|
||||
srp->nhlfe.label_in = index2label(srp->sid,
|
||||
OspfSR.self->srgb);
|
||||
srp->nhlfe.label_out = MPLS_IMP_NULL_LABEL;
|
||||
srp->nhlfe.label_out = MPLS_LABEL_IMPLICIT_NULL;
|
||||
add_sid_nhlfe(srp->nhlfe);
|
||||
}
|
||||
}
|
||||
@ -1992,7 +1992,7 @@ DEFUN (sr_prefix_sid,
|
||||
if (argv_find(argv, argc, "no-php-flag", &idx)) {
|
||||
SET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_NPFLG);
|
||||
new->nhlfe.label_in = index2label(new->sid, OspfSR.self->srgb);
|
||||
new->nhlfe.label_out = MPLS_IMP_NULL_LABEL;
|
||||
new->nhlfe.label_out = MPLS_LABEL_IMPLICIT_NULL;
|
||||
}
|
||||
|
||||
if (IS_DEBUG_OSPF_SR)
|
||||
@ -2168,7 +2168,7 @@ static void show_vty_sr_node(struct vty *vty, struct sr_node *srn)
|
||||
for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
|
||||
strncpy(pref, inet_ntoa(srp->nhlfe.prefv4.prefix), 16);
|
||||
snprintf(sid, 22, "SR Pfx (idx %u)", srp->sid);
|
||||
if (srp->nhlfe.label_out == MPLS_IMP_NULL_LABEL)
|
||||
if (srp->nhlfe.label_out == MPLS_LABEL_IMPLICIT_NULL)
|
||||
sprintf(label, "pop");
|
||||
else
|
||||
sprintf(label, "%u", srp->nhlfe.label_out);
|
||||
@ -2182,7 +2182,7 @@ static void show_vty_sr_node(struct vty *vty, struct sr_node *srn)
|
||||
for (ALL_LIST_ELEMENTS_RO(srn->ext_link, node, srl)) {
|
||||
strncpy(pref, inet_ntoa(srl->nhlfe[0].prefv4.prefix), 16);
|
||||
snprintf(sid, 22, "SR Adj. (lbl %u)", srl->sid[0]);
|
||||
if (srl->nhlfe[0].label_out == MPLS_IMP_NULL_LABEL)
|
||||
if (srl->nhlfe[0].label_out == MPLS_LABEL_IMPLICIT_NULL)
|
||||
sprintf(label, "pop");
|
||||
else
|
||||
sprintf(label, "%u", srl->nhlfe[0].label_out);
|
||||
@ -2192,7 +2192,7 @@ static void show_vty_sr_node(struct vty *vty, struct sr_node *srn)
|
||||
label, sid, itf ? itf->name : "-",
|
||||
inet_ntoa(srl->nhlfe[0].nexthop));
|
||||
snprintf(sid, 22, "SR Adj. (lbl %u)", srl->sid[1]);
|
||||
if (srl->nhlfe[1].label_out == MPLS_IMP_NULL_LABEL)
|
||||
if (srl->nhlfe[1].label_out == MPLS_LABEL_IMPLICIT_NULL)
|
||||
sprintf(label, "pop");
|
||||
else
|
||||
sprintf(label, "%u", srl->nhlfe[0].label_out);
|
||||
|
||||
@ -389,7 +389,6 @@ void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = ospf->vrf_id;
|
||||
api.nh_vrf_id = ospf->vrf_id;
|
||||
api.type = ZEBRA_ROUTE_OSPF;
|
||||
api.instance = ospf->instance;
|
||||
api.safi = SAFI_UNICAST;
|
||||
@ -442,6 +441,7 @@ void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,
|
||||
api_nh->ifindex = path->ifindex;
|
||||
api_nh->type = NEXTHOP_TYPE_IFINDEX;
|
||||
}
|
||||
api_nh->vrf_id = ospf->vrf_id;
|
||||
count++;
|
||||
|
||||
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
|
||||
@ -467,7 +467,6 @@ void ospf_zebra_delete(struct ospf *ospf, struct prefix_ipv4 *p,
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = ospf->vrf_id;
|
||||
api.nh_vrf_id = ospf->vrf_id;
|
||||
api.type = ZEBRA_ROUTE_OSPF;
|
||||
api.instance = ospf->instance;
|
||||
api.safi = SAFI_UNICAST;
|
||||
@ -489,7 +488,6 @@ void ospf_zebra_add_discard(struct ospf *ospf, struct prefix_ipv4 *p)
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = ospf->vrf_id;
|
||||
api.nh_vrf_id = ospf->vrf_id;
|
||||
api.type = ZEBRA_ROUTE_OSPF;
|
||||
api.instance = ospf->instance;
|
||||
api.safi = SAFI_UNICAST;
|
||||
@ -509,7 +507,6 @@ void ospf_zebra_delete_discard(struct ospf *ospf, struct prefix_ipv4 *p)
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = ospf->vrf_id;
|
||||
api.nh_vrf_id = ospf->vrf_id;
|
||||
api.type = ZEBRA_ROUTE_OSPF;
|
||||
api.instance = ospf->instance;
|
||||
api.safi = SAFI_UNICAST;
|
||||
|
||||
@ -48,7 +48,6 @@ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd)
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_RIP;
|
||||
api.safi = SAFI_UNICAST;
|
||||
|
||||
@ -57,6 +56,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd)
|
||||
if (count >= MULTIPATH_NUM)
|
||||
break;
|
||||
api_nh = &api.nexthops[count];
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
api_nh->gate = rinfo->nh.gate;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4;
|
||||
if (cmd == ZEBRA_ROUTE_ADD)
|
||||
|
||||
10
ripd/ripd.c
10
ripd/ripd.c
@ -2319,13 +2319,15 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
|
||||
tmp_rinfo))
|
||||
if (tmp_rinfo->type == ZEBRA_ROUTE_RIP
|
||||
&& tmp_rinfo->nh.ifindex
|
||||
== ifc->ifp->ifindex)
|
||||
rinfo->metric_out =
|
||||
== ifc->ifp->ifindex)
|
||||
tmp_rinfo->metric_out =
|
||||
RIP_METRIC_INFINITY;
|
||||
if (tmp_rinfo->type == ZEBRA_ROUTE_CONNECT
|
||||
|
||||
if (rinfo->type == ZEBRA_ROUTE_CONNECT
|
||||
&& prefix_match((struct prefix *)p,
|
||||
ifc->address))
|
||||
rinfo->metric_out = RIP_METRIC_INFINITY;
|
||||
rinfo->metric_out =
|
||||
RIP_METRIC_INFINITY;
|
||||
}
|
||||
|
||||
/* Prepare preamble, auth headers, if needs be */
|
||||
|
||||
@ -48,7 +48,6 @@ static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd)
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_RIPNG;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = rp->p;
|
||||
@ -58,6 +57,7 @@ static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd)
|
||||
if (count >= MULTIPATH_NUM)
|
||||
break;
|
||||
api_nh = &api.nexthops[count];
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
api_nh->gate.ipv6 = rinfo->nexthop;
|
||||
api_nh->ifindex = rinfo->ifindex;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
|
||||
@ -26,6 +26,8 @@
|
||||
#include "prefix.h"
|
||||
#include "nexthop.h"
|
||||
#include "log.h"
|
||||
#include "vrf.h"
|
||||
#include "zclient.h"
|
||||
|
||||
#include "sharpd/sharp_zebra.h"
|
||||
#include "sharpd/sharp_vty.h"
|
||||
@ -39,7 +41,8 @@ extern uint32_t removed_routes;
|
||||
|
||||
DEFPY (install_routes,
|
||||
install_routes_cmd,
|
||||
"install routes A.B.C.D$start nexthop A.B.C.D$nexthop (1-1000000)$routes",
|
||||
"sharp install routes A.B.C.D$start nexthop A.B.C.D$nexthop (1-1000000)$routes",
|
||||
"Sharp routing Protocol\n"
|
||||
"install some routes\n"
|
||||
"Routes to install\n"
|
||||
"Address to start /32 generation at\n"
|
||||
@ -76,9 +79,37 @@ DEFPY (install_routes,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY(vrf_label, vrf_label_cmd,
|
||||
"sharp label vrf NAME$name label (0-100000)$label",
|
||||
"Sharp Routing Protocol\n"
|
||||
"Give a vrf a label\n"
|
||||
VRF_CMD_HELP_STR
|
||||
"The label to use, 0 specifies remove the label installed from previous\n"
|
||||
"Specified range to use\n")
|
||||
{
|
||||
struct vrf *vrf;
|
||||
|
||||
if (strcmp(name, "default") == 0)
|
||||
vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||
else
|
||||
vrf = vrf_lookup_by_name(name);
|
||||
|
||||
if (!vrf) {
|
||||
vty_out(vty, "Unable to find vrf you silly head");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (label == 0)
|
||||
label = MPLS_LABEL_NONE;
|
||||
|
||||
vrf_label_add(vrf->vrf_id, label);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (remove_routes,
|
||||
remove_routes_cmd,
|
||||
"remove routes A.B.C.D$start (1-1000000)$routes",
|
||||
"sharp remove routes A.B.C.D$start (1-1000000)$routes",
|
||||
"Sharp Routing Protocol\n"
|
||||
"Remove some routes\n"
|
||||
"Routes to remove\n"
|
||||
"Starting spot\n"
|
||||
@ -112,5 +143,6 @@ void sharp_vty_init(void)
|
||||
{
|
||||
install_element(ENABLE_NODE, &install_routes_cmd);
|
||||
install_element(ENABLE_NODE, &remove_routes_cmd);
|
||||
install_element(ENABLE_NODE, &vrf_label_cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -152,6 +152,11 @@ static void zebra_connected(struct zclient *zclient)
|
||||
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
||||
}
|
||||
|
||||
void vrf_label_add(vrf_id_t vrf_id, mpls_label_t label)
|
||||
{
|
||||
zclient_send_vrf_label(zclient, vrf_id, label, ZEBRA_LSP_SHARP);
|
||||
}
|
||||
|
||||
void route_add(struct prefix *p, struct nexthop *nh)
|
||||
{
|
||||
struct zapi_route api;
|
||||
@ -159,7 +164,6 @@ void route_add(struct prefix *p, struct nexthop *nh)
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_SHARP;
|
||||
api.safi = SAFI_UNICAST;
|
||||
memcpy(&api.prefix, p, sizeof(*p));
|
||||
@ -167,6 +171,7 @@ void route_add(struct prefix *p, struct nexthop *nh)
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
|
||||
api_nh = &api.nexthops[0];
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
api_nh->gate.ipv4 = nh->gate.ipv4;
|
||||
api_nh->type = nh->type;
|
||||
api_nh->ifindex = nh->ifindex;
|
||||
@ -181,7 +186,6 @@ void route_delete(struct prefix *p)
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.nh_vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_SHARP;
|
||||
api.safi = SAFI_UNICAST;
|
||||
memcpy(&api.prefix, p, sizeof(*p));
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
|
||||
extern void sharp_zebra_init(void);
|
||||
|
||||
extern void vrf_label_add(vrf_id_t vrf_id, mpls_label_t label);
|
||||
extern void route_add(struct prefix *p, struct nexthop *nh);
|
||||
extern void route_delete(struct prefix *p);
|
||||
#endif
|
||||
|
||||
@ -352,13 +352,15 @@ void vtysh_config_dump(FILE *fp)
|
||||
for (i = 0; i < vector_active(configvec); i++)
|
||||
if ((master = vector_slot(configvec, i)) != NULL) {
|
||||
for (ALL_LIST_ELEMENTS(master, node, nnode, config)) {
|
||||
/* Don't print empty sections for interface/vrf.
|
||||
/* Don't print empty sections for interface.
|
||||
* Route maps on the
|
||||
* other hand could have a legitimate empty
|
||||
* section at the end.
|
||||
* VRF is handled in the backend, we could have
|
||||
* "configured" VRFs with static routes which
|
||||
* are not under the VRF node.
|
||||
*/
|
||||
if ((config->index == INTERFACE_NODE
|
||||
|| config->index == VRF_NODE)
|
||||
if (config->index == INTERFACE_NODE
|
||||
&& list_isempty(config->line))
|
||||
continue;
|
||||
|
||||
|
||||
@ -203,7 +203,9 @@ void connected_up(struct interface *ifp, struct connected *ifc)
|
||||
afi_t afi;
|
||||
struct prefix p;
|
||||
struct nexthop nh = {
|
||||
.type = NEXTHOP_TYPE_IFINDEX, .ifindex = ifp->ifindex,
|
||||
.type = NEXTHOP_TYPE_IFINDEX,
|
||||
.ifindex = ifp->ifindex,
|
||||
.vrf_id = ifp->vrf_id,
|
||||
};
|
||||
|
||||
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
|
||||
@ -238,13 +240,11 @@ void connected_up(struct interface *ifp, struct connected *ifc)
|
||||
break;
|
||||
}
|
||||
|
||||
rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ifp->vrf_id,
|
||||
ZEBRA_ROUTE_CONNECT, 0, 0,
|
||||
&p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
|
||||
rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p,
|
||||
NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
|
||||
|
||||
rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ifp->vrf_id,
|
||||
ZEBRA_ROUTE_CONNECT, 0, 0,
|
||||
&p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
|
||||
rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p,
|
||||
NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
|
||||
char buf[PREFIX_STRLEN];
|
||||
@ -362,7 +362,9 @@ void connected_down(struct interface *ifp, struct connected *ifc)
|
||||
afi_t afi;
|
||||
struct prefix p;
|
||||
struct nexthop nh = {
|
||||
.type = NEXTHOP_TYPE_IFINDEX, .ifindex = ifp->ifindex,
|
||||
.type = NEXTHOP_TYPE_IFINDEX,
|
||||
.ifindex = ifp->ifindex,
|
||||
.vrf_id = ifp->vrf_id,
|
||||
};
|
||||
|
||||
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
|
||||
|
||||
@ -907,6 +907,8 @@ void rtm_read(struct rt_msghdr *rtm)
|
||||
SET_FLAG(zebra_flags, ZEBRA_FLAG_STATIC);
|
||||
|
||||
memset(&nh, 0, sizeof(nh));
|
||||
|
||||
nh.vrf_id = VRF_DEFAULT;
|
||||
/* This is a reject or blackhole route */
|
||||
if (flags & RTF_REJECT) {
|
||||
nh.type = NEXTHOP_TYPE_BLACKHOLE;
|
||||
@ -1049,7 +1051,7 @@ void rtm_read(struct rt_msghdr *rtm)
|
||||
|
||||
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|
||||
|| rtm->rtm_type == RTM_CHANGE)
|
||||
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, VRF_DEFAULT,
|
||||
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
|
||||
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
|
||||
&nh, 0, 0, 0, 0, 0);
|
||||
else
|
||||
@ -1097,7 +1099,7 @@ void rtm_read(struct rt_msghdr *rtm)
|
||||
|
||||
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|
||||
|| rtm->rtm_type == RTM_CHANGE)
|
||||
rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, VRF_DEFAULT,
|
||||
rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
|
||||
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
|
||||
&nh, 0, 0, 0, 0, 0);
|
||||
else
|
||||
@ -1195,7 +1197,7 @@ int rtm_write(int message, union sockunion *dest, union sockunion *mask,
|
||||
msg.rtm.rtm_flags |= RTF_MPLS;
|
||||
|
||||
if (mpls->smpls.smpls_label
|
||||
!= htonl(MPLS_IMP_NULL_LABEL << MPLS_LABEL_OFFSET))
|
||||
!= htonl(MPLS_LABEL_IMPLICIT_NULL << MPLS_LABEL_OFFSET))
|
||||
msg.rtm.rtm_mpls = MPLS_OP_PUSH;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -283,13 +283,13 @@ struct label_manager_chunk *assign_label_chunk(u_char proto, u_short instance,
|
||||
return NULL;
|
||||
|
||||
if (list_isempty(lbl_mgr.lc_list))
|
||||
lmc->start = MPLS_MIN_UNRESERVED_LABEL;
|
||||
lmc->start = MPLS_LABEL_UNRESERVED_MIN;
|
||||
else
|
||||
lmc->start = ((struct label_manager_chunk *)listgetdata(
|
||||
listtail(lbl_mgr.lc_list)))
|
||||
->end
|
||||
+ 1;
|
||||
if (lmc->start > MPLS_MAX_UNRESERVED_LABEL - size + 1) {
|
||||
if (lmc->start > MPLS_LABEL_UNRESERVED_MAX - size + 1) {
|
||||
zlog_err("Reached max labels. Start: %u, size: %u", lmc->start,
|
||||
size);
|
||||
XFREE(MTYPE_LM_CHUNK, lmc);
|
||||
|
||||
20
zebra/rib.h
20
zebra/rib.h
@ -59,7 +59,6 @@ struct route_entry {
|
||||
|
||||
/* VRF identifier. */
|
||||
vrf_id_t vrf_id;
|
||||
vrf_id_t nh_vrf_id;
|
||||
|
||||
/* Which routing table */
|
||||
uint32_t table;
|
||||
@ -231,22 +230,27 @@ typedef enum {
|
||||
} rib_update_event_t;
|
||||
|
||||
extern struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *,
|
||||
ifindex_t);
|
||||
ifindex_t,
|
||||
vrf_id_t nh_vrf_id);
|
||||
extern struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *,
|
||||
enum blackhole_type);
|
||||
extern struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *,
|
||||
struct in_addr *,
|
||||
struct in_addr *);
|
||||
struct in_addr *,
|
||||
vrf_id_t nh_vrf_id);
|
||||
extern struct nexthop *
|
||||
route_entry_nexthop_ipv4_ifindex_add(struct route_entry *, struct in_addr *,
|
||||
struct in_addr *, ifindex_t);
|
||||
struct in_addr *, ifindex_t,
|
||||
vrf_id_t nh_vrf_id);
|
||||
extern void route_entry_nexthop_delete(struct route_entry *re,
|
||||
struct nexthop *nexthop);
|
||||
extern struct nexthop *route_entry_nexthop_ipv6_add(struct route_entry *,
|
||||
struct in6_addr *);
|
||||
struct in6_addr *,
|
||||
vrf_id_t nh_vrf_id);
|
||||
extern struct nexthop *
|
||||
route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
|
||||
struct in6_addr *ipv6, ifindex_t ifindex);
|
||||
struct in6_addr *ipv6, ifindex_t ifindex,
|
||||
vrf_id_t nh_vrf_id);
|
||||
extern void route_entry_nexthop_add(struct route_entry *re,
|
||||
struct nexthop *nexthop);
|
||||
extern void route_entry_copy_nexthops(struct route_entry *re,
|
||||
@ -294,8 +298,8 @@ extern void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re);
|
||||
/* NOTE:
|
||||
* All rib_add function will not just add prefix into RIB, but
|
||||
* also implicitly withdraw equal prefix of same type. */
|
||||
extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, vrf_id_t nh_vrf_id,
|
||||
int type, u_short instance, int flags, struct prefix *p,
|
||||
extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
|
||||
u_short instance, int flags, struct prefix *p,
|
||||
struct prefix_ipv6 *src_p, const struct nexthop *nh,
|
||||
u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
|
||||
uint8_t distance, route_tag_t tag);
|
||||
|
||||
@ -443,10 +443,10 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
|
||||
if (ifp)
|
||||
nh_vrf_id = ifp->vrf_id;
|
||||
}
|
||||
nh.vrf_id = nh_vrf_id;
|
||||
|
||||
rib_add(afi, SAFI_UNICAST, vrf_id, nh_vrf_id, proto,
|
||||
0, flags, &p, NULL, &nh, table, metric,
|
||||
mtu, distance, tag);
|
||||
rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p,
|
||||
NULL, &nh, table, metric, mtu, distance, tag);
|
||||
} else {
|
||||
/* This is a multipath route */
|
||||
|
||||
@ -463,13 +463,13 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
|
||||
re->metric = metric;
|
||||
re->mtu = mtu;
|
||||
re->vrf_id = vrf_id;
|
||||
re->nh_vrf_id = vrf_id;
|
||||
re->table = table;
|
||||
re->nexthop_num = 0;
|
||||
re->uptime = time(NULL);
|
||||
re->tag = tag;
|
||||
|
||||
for (;;) {
|
||||
vrf_id_t nh_vrf_id;
|
||||
if (len < (int)sizeof(*rtnh)
|
||||
|| rtnh->rtnh_len > len)
|
||||
break;
|
||||
@ -485,8 +485,17 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
|
||||
ifp = if_lookup_by_index(index,
|
||||
VRF_UNKNOWN);
|
||||
if (ifp)
|
||||
re->nh_vrf_id = ifp->vrf_id;
|
||||
}
|
||||
nh_vrf_id = ifp->vrf_id;
|
||||
else {
|
||||
zlog_warn(
|
||||
"%s: Unknown interface %u specified, defaulting to VRF_DEFAULT",
|
||||
__PRETTY_FUNCTION__,
|
||||
index);
|
||||
nh_vrf_id = VRF_DEFAULT;
|
||||
}
|
||||
} else
|
||||
nh_vrf_id = vrf_id;
|
||||
|
||||
gate = 0;
|
||||
if (rtnh->rtnh_len > sizeof(*rtnh)) {
|
||||
memset(tb, 0, sizeof(tb));
|
||||
@ -503,24 +512,27 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
|
||||
if (index)
|
||||
route_entry_nexthop_ipv4_ifindex_add(
|
||||
re, gate,
|
||||
prefsrc, index);
|
||||
prefsrc, index,
|
||||
nh_vrf_id);
|
||||
else
|
||||
route_entry_nexthop_ipv4_add(
|
||||
re, gate,
|
||||
prefsrc);
|
||||
prefsrc,
|
||||
nh_vrf_id);
|
||||
} else if (rtm->rtm_family
|
||||
== AF_INET6) {
|
||||
if (index)
|
||||
route_entry_nexthop_ipv6_ifindex_add(
|
||||
re, gate,
|
||||
index);
|
||||
re, gate, index,
|
||||
nh_vrf_id);
|
||||
else
|
||||
route_entry_nexthop_ipv6_add(
|
||||
re, gate);
|
||||
re, gate,
|
||||
nh_vrf_id);
|
||||
}
|
||||
} else
|
||||
route_entry_nexthop_ifindex_add(re,
|
||||
index);
|
||||
route_entry_nexthop_ifindex_add(
|
||||
re, index, nh_vrf_id);
|
||||
|
||||
len -= NLMSG_ALIGN(rtnh->rtnh_len);
|
||||
rtnh = RTNH_NEXT(rtnh);
|
||||
@ -852,7 +864,7 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
|
||||
char label_buf1[20];
|
||||
|
||||
for (i = 0; i < nh_label->num_labels; i++) {
|
||||
if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) {
|
||||
if (nh_label->label[i] != MPLS_LABEL_IMPLICIT_NULL) {
|
||||
bos = ((i == (nh_label->num_labels - 1)) ? 1
|
||||
: 0);
|
||||
out_lse[i] = mpls_lse_encode(nh_label->label[i],
|
||||
@ -1062,7 +1074,7 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
|
||||
char label_buf1[20];
|
||||
|
||||
for (i = 0; i < nh_label->num_labels; i++) {
|
||||
if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) {
|
||||
if (nh_label->label[i] != MPLS_LABEL_IMPLICIT_NULL) {
|
||||
bos = ((i == (nh_label->num_labels - 1)) ? 1
|
||||
: 0);
|
||||
out_lse[i] = mpls_lse_encode(nh_label->label[i],
|
||||
|
||||
@ -94,12 +94,12 @@ static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry)
|
||||
prefix.prefixlen = ip_masklen(tmpaddr);
|
||||
|
||||
memset(&nh, 0, sizeof(nh));
|
||||
nh.vrf_id = VRF_DEFAULT;
|
||||
nh.type = NEXTHOP_TYPE_IPV4;
|
||||
nh.gate.ipv4.s_addr = routeEntry->ipRouteNextHop;
|
||||
|
||||
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, VRF_DEFAULT,
|
||||
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &prefix, NULL,
|
||||
&nh, 0, 0, 0, 0, 0);
|
||||
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
|
||||
zebra_flags, &prefix, NULL, &nh, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void route_read(struct zebra_ns *zns)
|
||||
|
||||
@ -411,12 +411,13 @@ static int fec_change_update_lsp(struct zebra_vrf *zvrf, zebra_fec_t *fec,
|
||||
afi_t afi;
|
||||
|
||||
/* Uninstall label forwarding entry, if previously installed. */
|
||||
if (old_label != MPLS_INVALID_LABEL && old_label != MPLS_IMP_NULL_LABEL)
|
||||
if (old_label != MPLS_INVALID_LABEL &&
|
||||
old_label != MPLS_LABEL_IMPLICIT_NULL)
|
||||
lsp_uninstall(zvrf, old_label);
|
||||
|
||||
/* Install label forwarding entry corr. to new label, if needed. */
|
||||
if (fec->label == MPLS_INVALID_LABEL
|
||||
|| fec->label == MPLS_IMP_NULL_LABEL)
|
||||
|| fec->label == MPLS_LABEL_IMPLICIT_NULL)
|
||||
return 0;
|
||||
|
||||
afi = family2afi(PREFIX_FAMILY(&fec->rn->p));
|
||||
@ -614,7 +615,7 @@ static int nhlfe_nexthop_active_ipv4(zebra_nhlfe_t *nhlfe,
|
||||
struct route_entry *match;
|
||||
struct nexthop *match_nh;
|
||||
|
||||
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
|
||||
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, nexthop->vrf_id);
|
||||
if (!table)
|
||||
return 0;
|
||||
|
||||
@ -663,7 +664,7 @@ static int nhlfe_nexthop_active_ipv6(zebra_nhlfe_t *nhlfe,
|
||||
struct route_node *rn;
|
||||
struct route_entry *match;
|
||||
|
||||
table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT);
|
||||
table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, nexthop->vrf_id);
|
||||
if (!table)
|
||||
return 0;
|
||||
|
||||
@ -711,6 +712,22 @@ static int nhlfe_nexthop_active(zebra_nhlfe_t *nhlfe)
|
||||
|
||||
/* Check on nexthop based on type. */
|
||||
switch (nexthop->type) {
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
/*
|
||||
* Lookup if this type is special. The
|
||||
* NEXTHOP_TYPE_IFINDEX is a pop and
|
||||
* forward into a different table for
|
||||
* processing. As such this ifindex
|
||||
* passed to us may be a VRF device
|
||||
* which will not be in the default
|
||||
* VRF. So let's look in all of them
|
||||
*/
|
||||
ifp = if_lookup_by_index(nexthop->ifindex, VRF_UNKNOWN);
|
||||
if (ifp && if_is_operative(ifp))
|
||||
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
else
|
||||
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
if (nhlfe_nexthop_active_ipv4(nhlfe, nexthop))
|
||||
@ -728,7 +745,8 @@ static int nhlfe_nexthop_active(zebra_nhlfe_t *nhlfe)
|
||||
|
||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&nexthop->gate.ipv6)) {
|
||||
ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT);
|
||||
ifp = if_lookup_by_index(nexthop->ifindex,
|
||||
nexthop->vrf_id);
|
||||
if (ifp && if_is_operative(ifp))
|
||||
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
else
|
||||
@ -1052,6 +1070,8 @@ static char *nhlfe2str(zebra_nhlfe_t *nhlfe, char *buf, int size)
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, size);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
snprintf(buf, size, "Ifindex: %u", nexthop->ifindex);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1090,6 +1110,9 @@ static int nhlfe_nhop_match(zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype,
|
||||
if (!cmp && nhop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
|
||||
cmp = !(nhop->ifindex == ifindex);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
cmp = !(nhop->ifindex == ifindex);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1149,6 +1172,7 @@ static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
|
||||
}
|
||||
nexthop_add_labels(nexthop, lsp_type, 1, &out_label);
|
||||
|
||||
nexthop->vrf_id = VRF_DEFAULT;
|
||||
nexthop->type = gtype;
|
||||
switch (nexthop->type) {
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
@ -1163,6 +1187,9 @@ static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
|
||||
if (ifindex)
|
||||
nexthop->ifindex = ifindex;
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
nexthop->ifindex = ifindex;
|
||||
break;
|
||||
default:
|
||||
nexthop_free(nexthop);
|
||||
XFREE(MTYPE_NHLFE, nhlfe);
|
||||
@ -1324,9 +1351,9 @@ static json_object *nhlfe_json(zebra_nhlfe_t *nhlfe)
|
||||
inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
|
||||
|
||||
if (nexthop->ifindex)
|
||||
json_object_string_add(
|
||||
json_nhlfe, "interface",
|
||||
ifindex2ifname(nexthop->ifindex, VRF_DEFAULT));
|
||||
json_object_string_add(json_nhlfe, "interface",
|
||||
ifindex2ifname(nexthop->ifindex,
|
||||
nexthop->vrf_id));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -1356,7 +1383,8 @@ static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty)
|
||||
vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4));
|
||||
if (nexthop->ifindex)
|
||||
vty_out(vty, " dev %s",
|
||||
ifindex2ifname(nexthop->ifindex, VRF_DEFAULT));
|
||||
ifindex2ifname(nexthop->ifindex,
|
||||
nexthop->vrf_id));
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||
@ -1364,7 +1392,8 @@ static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty)
|
||||
inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
|
||||
if (nexthop->ifindex)
|
||||
vty_out(vty, " dev %s",
|
||||
ifindex2ifname(nexthop->ifindex, VRF_DEFAULT));
|
||||
ifindex2ifname(nexthop->ifindex,
|
||||
nexthop->vrf_id));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -1793,7 +1822,7 @@ int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
/* We cannot install a label forwarding entry if local label is the
|
||||
* implicit-null label.
|
||||
*/
|
||||
if (fec->label == MPLS_IMP_NULL_LABEL)
|
||||
if (fec->label == MPLS_LABEL_IMPLICIT_NULL)
|
||||
return 0;
|
||||
|
||||
if (lsp_install(zvrf, fec->label, rn, re))
|
||||
@ -2537,8 +2566,8 @@ int zebra_mpls_lsp_label_consistent(struct zebra_vrf *zvrf,
|
||||
int cur_op, new_op;
|
||||
|
||||
cur_op = (slsp->snhlfe_list->out_label
|
||||
== MPLS_IMP_NULL_LABEL);
|
||||
new_op = (out_label == MPLS_IMP_NULL_LABEL);
|
||||
== MPLS_LABEL_IMPLICIT_NULL);
|
||||
new_op = (out_label == MPLS_LABEL_IMPLICIT_NULL);
|
||||
if (cur_op != new_op)
|
||||
return 0;
|
||||
}
|
||||
@ -2764,6 +2793,15 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
|
||||
nexthop = nhlfe->nexthop;
|
||||
|
||||
switch (nexthop->type) {
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
{
|
||||
struct interface *ifp;
|
||||
|
||||
ifp = if_lookup_by_index(
|
||||
nexthop->ifindex, VRF_UNKNOWN);
|
||||
vty_out(vty, "%15s", ifp->name);
|
||||
break;
|
||||
}
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
vty_out(vty, "%15s",
|
||||
@ -2780,8 +2818,16 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
|
||||
break;
|
||||
}
|
||||
|
||||
vty_out(vty, " %8d\n",
|
||||
nexthop->nh_label->label[0]);
|
||||
if (nexthop->type != NEXTHOP_TYPE_IFINDEX)
|
||||
vty_out(vty, " %8s\n",
|
||||
mpls_label2str(
|
||||
nexthop->nh_label
|
||||
->num_labels,
|
||||
&nexthop->nh_label
|
||||
->label[0],
|
||||
buf, BUFSIZ, 1));
|
||||
else
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2810,11 +2856,11 @@ int zebra_mpls_write_lsp_config(struct vty *vty, struct zebra_vrf *zvrf)
|
||||
|
||||
snhlfe2str(snhlfe, buf, sizeof(buf));
|
||||
switch (snhlfe->out_label) {
|
||||
case MPLS_V4_EXP_NULL_LABEL:
|
||||
case MPLS_V6_EXP_NULL_LABEL:
|
||||
case MPLS_LABEL_IPV4_EXPLICIT_NULL:
|
||||
case MPLS_LABEL_IPV6_EXPLICIT_NULL:
|
||||
strlcpy(lstr, "explicit-null", sizeof(lstr));
|
||||
break;
|
||||
case MPLS_IMP_NULL_LABEL:
|
||||
case MPLS_LABEL_IMPLICIT_NULL:
|
||||
strlcpy(lstr, "implicit-null", sizeof(lstr));
|
||||
break;
|
||||
default:
|
||||
@ -2875,6 +2921,16 @@ int zebra_mpls_write_label_block_config(struct vty *vty, struct zebra_vrf *zvrf)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when VRF becomes inactive, cleans up information but keeps
|
||||
* the table itself.
|
||||
* NOTE: Currently supported only for default VRF.
|
||||
*/
|
||||
void zebra_mpls_cleanup_tables(struct zebra_vrf *zvrf)
|
||||
{
|
||||
hash_iterate(zvrf->lsp_table, lsp_uninstall_from_kernel, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called upon process exiting, need to delete LSP forwarding
|
||||
* entries from the kernel.
|
||||
|
||||
@ -384,6 +384,13 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
|
||||
*/
|
||||
int zebra_mpls_write_lsp_config(struct vty *vty, struct zebra_vrf *zvrf);
|
||||
|
||||
/*
|
||||
* Called when VRF becomes inactive, cleans up information but keeps
|
||||
* the table itself.
|
||||
* NOTE: Currently supported only for default VRF.
|
||||
*/
|
||||
void zebra_mpls_cleanup_tables(struct zebra_vrf *zvrf);
|
||||
|
||||
/*
|
||||
* Called upon process exiting, need to delete LSP forwarding
|
||||
* entries from the kernel.
|
||||
@ -421,9 +428,19 @@ static inline u_char lsp_distance(enum lsp_types_t type)
|
||||
return (route_distance(ZEBRA_ROUTE_LDP));
|
||||
case ZEBRA_LSP_BGP:
|
||||
return (route_distance(ZEBRA_ROUTE_BGP));
|
||||
default:
|
||||
case ZEBRA_LSP_NONE:
|
||||
case ZEBRA_LSP_SHARP:
|
||||
case ZEBRA_LSP_SR:
|
||||
return 150;
|
||||
}
|
||||
|
||||
/*
|
||||
* For some reason certain compilers do not believe
|
||||
* that all the cases have been handled. And
|
||||
* WTF does this work differently than when I removed
|
||||
* the default case????
|
||||
*/
|
||||
return 150;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -437,6 +454,8 @@ static inline enum lsp_types_t lsp_type_from_re_type(int re_type)
|
||||
return ZEBRA_LSP_STATIC;
|
||||
case ZEBRA_ROUTE_BGP:
|
||||
return ZEBRA_LSP_BGP;
|
||||
case ZEBRA_ROUTE_SHARP:
|
||||
return ZEBRA_LSP_SHARP;
|
||||
default:
|
||||
return ZEBRA_LSP_NONE;
|
||||
}
|
||||
@ -457,9 +476,18 @@ static inline int re_type_from_lsp_type(enum lsp_types_t lsp_type)
|
||||
case ZEBRA_LSP_SR:
|
||||
return ZEBRA_ROUTE_OSPF;
|
||||
case ZEBRA_LSP_NONE:
|
||||
default:
|
||||
return ZEBRA_ROUTE_KERNEL;
|
||||
case ZEBRA_LSP_SHARP:
|
||||
return ZEBRA_ROUTE_SHARP;
|
||||
}
|
||||
|
||||
/*
|
||||
* For some reason certain compilers do not believe
|
||||
* that all the cases have been handled. And
|
||||
* WTF does this work differently than when I removed
|
||||
* the default case????
|
||||
*/
|
||||
return ZEBRA_ROUTE_KERNEL;
|
||||
}
|
||||
|
||||
/* NHLFE type as printable string. */
|
||||
@ -474,9 +502,19 @@ static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type)
|
||||
return "BGP";
|
||||
case ZEBRA_LSP_SR:
|
||||
return "SR";
|
||||
default:
|
||||
case ZEBRA_LSP_SHARP:
|
||||
return "SHARP";
|
||||
case ZEBRA_LSP_NONE:
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
/*
|
||||
* For some reason certain compilers do not believe
|
||||
* that all the cases have been handled. And
|
||||
* WTF does this work differently than when I removed
|
||||
* the default case????
|
||||
*/
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static inline void mpls_mark_lsps_for_processing(struct zebra_vrf *zvrf)
|
||||
|
||||
@ -68,7 +68,7 @@ static int zebra_mpls_transit_lsp(struct vty *vty, int add_cmd,
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
out_label = MPLS_IMP_NULL_LABEL; /* as initialization */
|
||||
out_label = MPLS_LABEL_IMPLICIT_NULL; /* as initialization */
|
||||
label = atoi(inlabel_str);
|
||||
if (!IS_MPLS_UNRESERVED_LABEL(label)) {
|
||||
vty_out(vty, "%% Invalid label\n");
|
||||
@ -107,11 +107,11 @@ static int zebra_mpls_transit_lsp(struct vty *vty, int add_cmd,
|
||||
|
||||
if (outlabel_str) {
|
||||
if (outlabel_str[0] == 'i')
|
||||
out_label = MPLS_IMP_NULL_LABEL;
|
||||
out_label = MPLS_LABEL_IMPLICIT_NULL;
|
||||
else if (outlabel_str[0] == 'e' && gtype == NEXTHOP_TYPE_IPV4)
|
||||
out_label = MPLS_V4_EXP_NULL_LABEL;
|
||||
out_label = MPLS_LABEL_IPV4_EXPLICIT_NULL;
|
||||
else if (outlabel_str[0] == 'e' && gtype == NEXTHOP_TYPE_IPV6)
|
||||
out_label = MPLS_V6_EXP_NULL_LABEL;
|
||||
out_label = MPLS_LABEL_IPV6_EXPLICIT_NULL;
|
||||
else
|
||||
out_label = atoi(outlabel_str);
|
||||
}
|
||||
@ -221,12 +221,12 @@ static int zebra_mpls_bind(struct vty *vty, int add_cmd, const char *prefix,
|
||||
}
|
||||
|
||||
if (!strcmp(label_str, "implicit-null"))
|
||||
label = MPLS_IMP_NULL_LABEL;
|
||||
label = MPLS_LABEL_IMPLICIT_NULL;
|
||||
else if (!strcmp(label_str, "explicit-null")) {
|
||||
if (p.family == AF_INET)
|
||||
label = MPLS_V4_EXP_NULL_LABEL;
|
||||
label = MPLS_LABEL_IPV4_EXPLICIT_NULL;
|
||||
else
|
||||
label = MPLS_V6_EXP_NULL_LABEL;
|
||||
label = MPLS_LABEL_IPV6_EXPLICIT_NULL;
|
||||
} else {
|
||||
label = atoi(label_str);
|
||||
if (!IS_MPLS_UNRESERVED_LABEL(label)) {
|
||||
|
||||
@ -41,6 +41,7 @@ struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id)
|
||||
return dzns;
|
||||
}
|
||||
|
||||
/* Do global enable actions - open sockets, read kernel config etc. */
|
||||
int zebra_ns_enable(ns_id_t ns_id, void **info)
|
||||
{
|
||||
struct zebra_ns *zns = (struct zebra_ns *)(*info);
|
||||
@ -49,8 +50,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info)
|
||||
rtadv_init(zns);
|
||||
#endif
|
||||
|
||||
zns->if_table = route_table_init();
|
||||
zebra_vxlan_ns_init(zns);
|
||||
kernel_init(zns);
|
||||
interface_list(zns);
|
||||
route_read(zns);
|
||||
@ -79,8 +78,14 @@ int zebra_ns_init(void)
|
||||
|
||||
ns_init();
|
||||
|
||||
/* Do any needed per-NS data structure allocation. */
|
||||
dzns->if_table = route_table_init();
|
||||
zebra_vxlan_ns_init(dzns);
|
||||
|
||||
/* Register zebra VRF callbacks, create and activate default VRF. */
|
||||
zebra_vrf_init();
|
||||
|
||||
/* Default NS is activated */
|
||||
zebra_ns_enable(NS_DEFAULT, (void **)&dzns);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -86,6 +86,7 @@ static const struct {
|
||||
[ZEBRA_ROUTE_BGP_DIRECT] = {ZEBRA_ROUTE_BGP_DIRECT, 20},
|
||||
[ZEBRA_ROUTE_BGP_DIRECT_EXT] = {ZEBRA_ROUTE_BGP_DIRECT_EXT, 20},
|
||||
[ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 100},
|
||||
[ZEBRA_ROUTE_SHARP] = {ZEBRA_ROUTE_SHARP, 150},
|
||||
|
||||
/* no entry/default: 150 */
|
||||
};
|
||||
@ -212,13 +213,15 @@ void route_entry_nexthop_delete(struct route_entry *re, struct nexthop *nexthop)
|
||||
|
||||
|
||||
struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *re,
|
||||
ifindex_t ifindex)
|
||||
ifindex_t ifindex,
|
||||
vrf_id_t nh_vrf_id)
|
||||
{
|
||||
struct nexthop *nexthop;
|
||||
|
||||
nexthop = nexthop_new();
|
||||
nexthop->type = NEXTHOP_TYPE_IFINDEX;
|
||||
nexthop->ifindex = ifindex;
|
||||
nexthop->vrf_id = nh_vrf_id;
|
||||
|
||||
route_entry_nexthop_add(re, nexthop);
|
||||
|
||||
@ -227,12 +230,14 @@ struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *re,
|
||||
|
||||
struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *re,
|
||||
struct in_addr *ipv4,
|
||||
struct in_addr *src)
|
||||
struct in_addr *src,
|
||||
vrf_id_t nh_vrf_id)
|
||||
{
|
||||
struct nexthop *nexthop;
|
||||
|
||||
nexthop = nexthop_new();
|
||||
nexthop->type = NEXTHOP_TYPE_IPV4;
|
||||
nexthop->vrf_id = nh_vrf_id;
|
||||
nexthop->gate.ipv4 = *ipv4;
|
||||
if (src)
|
||||
nexthop->src.ipv4 = *src;
|
||||
@ -245,18 +250,20 @@ struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *re,
|
||||
struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
|
||||
struct in_addr *ipv4,
|
||||
struct in_addr *src,
|
||||
ifindex_t ifindex)
|
||||
ifindex_t ifindex,
|
||||
vrf_id_t nh_vrf_id)
|
||||
{
|
||||
struct nexthop *nexthop;
|
||||
struct interface *ifp;
|
||||
|
||||
nexthop = nexthop_new();
|
||||
nexthop->vrf_id = nh_vrf_id;
|
||||
nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
nexthop->gate.ipv4 = *ipv4;
|
||||
if (src)
|
||||
nexthop->src.ipv4 = *src;
|
||||
nexthop->ifindex = ifindex;
|
||||
ifp = if_lookup_by_index(nexthop->ifindex, re->nh_vrf_id);
|
||||
ifp = if_lookup_by_index(nexthop->ifindex, nh_vrf_id);
|
||||
/*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)
|
||||
@ -271,11 +278,13 @@ struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
|
||||
}
|
||||
|
||||
struct nexthop *route_entry_nexthop_ipv6_add(struct route_entry *re,
|
||||
struct in6_addr *ipv6)
|
||||
struct in6_addr *ipv6,
|
||||
vrf_id_t nh_vrf_id)
|
||||
{
|
||||
struct nexthop *nexthop;
|
||||
|
||||
nexthop = nexthop_new();
|
||||
nexthop->vrf_id = nh_vrf_id;
|
||||
nexthop->type = NEXTHOP_TYPE_IPV6;
|
||||
nexthop->gate.ipv6 = *ipv6;
|
||||
|
||||
@ -286,11 +295,13 @@ struct nexthop *route_entry_nexthop_ipv6_add(struct route_entry *re,
|
||||
|
||||
struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
|
||||
struct in6_addr *ipv6,
|
||||
ifindex_t ifindex)
|
||||
ifindex_t ifindex,
|
||||
vrf_id_t nh_vrf_id)
|
||||
{
|
||||
struct nexthop *nexthop;
|
||||
|
||||
nexthop = nexthop_new();
|
||||
nexthop->vrf_id = nh_vrf_id;
|
||||
nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
nexthop->gate.ipv6 = *ipv6;
|
||||
nexthop->ifindex = ifindex;
|
||||
@ -306,6 +317,7 @@ struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *re,
|
||||
struct nexthop *nexthop;
|
||||
|
||||
nexthop = nexthop_new();
|
||||
nexthop->vrf_id = VRF_DEFAULT;
|
||||
nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
|
||||
nexthop->bh_type = bh_type;
|
||||
|
||||
@ -322,6 +334,7 @@ static void nexthop_set_resolved(afi_t afi, struct nexthop *newhop,
|
||||
resolved_hop = nexthop_new();
|
||||
SET_FLAG(resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
|
||||
resolved_hop->vrf_id = nexthop->vrf_id;
|
||||
switch (newhop->type) {
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
@ -403,7 +416,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
||||
|
||||
if (set) {
|
||||
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
|
||||
zebra_deregister_rnh_static_nexthops(re->nh_vrf_id,
|
||||
zebra_deregister_rnh_static_nexthops(nexthop->vrf_id,
|
||||
nexthop->resolved, top);
|
||||
nexthops_free(nexthop->resolved);
|
||||
nexthop->resolved = NULL;
|
||||
@ -422,7 +435,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
||||
* address in the routing table.
|
||||
*/
|
||||
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) {
|
||||
ifp = if_lookup_by_index(nexthop->ifindex, re->nh_vrf_id);
|
||||
ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
|
||||
if (ifp && connected_is_unnumbered(ifp)) {
|
||||
if (if_is_operative(ifp))
|
||||
return 1;
|
||||
@ -450,7 +463,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
||||
break;
|
||||
}
|
||||
/* Lookup table. */
|
||||
table = zebra_vrf_table(afi, SAFI_UNICAST, re->nh_vrf_id);
|
||||
table = zebra_vrf_table(afi, SAFI_UNICAST, nexthop->vrf_id);
|
||||
if (!table)
|
||||
return 0;
|
||||
|
||||
@ -472,7 +485,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
||||
/* However, do not resolve over default route unless explicitly
|
||||
* allowed. */
|
||||
if (is_default_prefix(&rn->p)
|
||||
&& !nh_resolve_via_default(p.family))
|
||||
&& !rnh_resolve_via_default(p.family))
|
||||
return 0;
|
||||
|
||||
dest = rib_dest_from_rnode(rn);
|
||||
@ -838,7 +851,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
|
||||
family = 0;
|
||||
switch (nexthop->type) {
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
ifp = if_lookup_by_index(nexthop->ifindex, re->nh_vrf_id);
|
||||
ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
|
||||
if (ifp && if_is_operative(ifp))
|
||||
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
else
|
||||
@ -867,7 +880,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
|
||||
family = AFI_IP6;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&nexthop->gate.ipv6)) {
|
||||
ifp = if_lookup_by_index(nexthop->ifindex,
|
||||
re->nh_vrf_id);
|
||||
nexthop->vrf_id);
|
||||
if (ifp && if_is_operative(ifp))
|
||||
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
else
|
||||
@ -910,8 +923,8 @@ static unsigned nexthop_active_check(struct route_node *rn,
|
||||
memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr));
|
||||
|
||||
/* It'll get set if required inside */
|
||||
ret = zebra_route_map_check(family, re->type, p, nexthop, re->nh_vrf_id,
|
||||
re->tag);
|
||||
ret = zebra_route_map_check(family, re->type, p, nexthop,
|
||||
nexthop->vrf_id, re->tag);
|
||||
if (ret == RMAP_DENYMATCH) {
|
||||
if (IS_ZEBRA_DEBUG_RIB) {
|
||||
srcdest_rnode2str(rn, buf, sizeof(buf));
|
||||
@ -919,7 +932,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
|
||||
"%u:%s: Filtering out with NH out %s due to route map",
|
||||
re->vrf_id, buf,
|
||||
ifindex2ifname(nexthop->ifindex,
|
||||
re->nh_vrf_id));
|
||||
nexthop->vrf_id));
|
||||
}
|
||||
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
}
|
||||
@ -2554,10 +2567,9 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
|
||||
}
|
||||
|
||||
|
||||
int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, vrf_id_t nh_vrf_id,
|
||||
int type, u_short instance, int flags, struct prefix *p,
|
||||
struct prefix_ipv6 *src_p, const struct nexthop *nh,
|
||||
u_int32_t table_id, u_int32_t metric,
|
||||
int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
|
||||
int flags, struct prefix *p, struct prefix_ipv6 *src_p,
|
||||
const struct nexthop *nh, u_int32_t table_id, u_int32_t metric,
|
||||
u_int32_t mtu, uint8_t distance, route_tag_t tag)
|
||||
{
|
||||
struct route_entry *re;
|
||||
@ -2573,7 +2585,6 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, vrf_id_t nh_vrf_id,
|
||||
re->mtu = mtu;
|
||||
re->table = table_id;
|
||||
re->vrf_id = vrf_id;
|
||||
re->nh_vrf_id = nh_vrf_id;
|
||||
re->nexthop_num = 0;
|
||||
re->uptime = time(NULL);
|
||||
re->tag = tag;
|
||||
|
||||
@ -659,7 +659,7 @@ static struct route_entry *zebra_rnh_resolve_nexthop_entry(vrf_id_t vrfid,
|
||||
* match route to be exact if so specified
|
||||
*/
|
||||
if (is_default_prefix(&rn->p) &&
|
||||
!nh_resolve_via_default(rn->p.family))
|
||||
!rnh_resolve_via_default(rn->p.family))
|
||||
return NULL;
|
||||
|
||||
/* Identify appropriate route entry. */
|
||||
@ -952,7 +952,6 @@ static void copy_state(struct rnh *rnh, struct route_entry *re,
|
||||
state->distance = re->distance;
|
||||
state->metric = re->metric;
|
||||
state->vrf_id = re->vrf_id;
|
||||
state->nh_vrf_id = re->vrf_id;
|
||||
|
||||
route_entry_copy_nexthops(state, re->nexthop);
|
||||
rnh->state = state;
|
||||
|
||||
@ -54,6 +54,15 @@ typedef enum { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE } rnh_type_t;
|
||||
extern int zebra_rnh_ip_default_route;
|
||||
extern int zebra_rnh_ipv6_default_route;
|
||||
|
||||
static inline int rnh_resolve_via_default(int family)
|
||||
{
|
||||
if (((family == AF_INET) && zebra_rnh_ip_default_route)
|
||||
|| ((family == AF_INET6) && zebra_rnh_ipv6_default_route))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid,
|
||||
rnh_type_t type);
|
||||
extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
|
||||
|
||||
@ -1329,7 +1329,7 @@ route_map_result_t zebra_nht_route_map_check(int family, int client_proto,
|
||||
struct nh_rmap_obj nh_obj;
|
||||
|
||||
nh_obj.nexthop = nexthop;
|
||||
nh_obj.vrf_id = re->nh_vrf_id;
|
||||
nh_obj.vrf_id = nexthop->vrf_id;
|
||||
nh_obj.source_protocol = re->type;
|
||||
nh_obj.metric = re->metric;
|
||||
nh_obj.tag = re->tag;
|
||||
|
||||
@ -87,7 +87,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||
switch (si->type) {
|
||||
case STATIC_IPV4_GATEWAY:
|
||||
nexthop = route_entry_nexthop_ipv4_add(
|
||||
re, &si->addr.ipv4, NULL);
|
||||
re, &si->addr.ipv4, NULL, si->nh_vrf_id);
|
||||
nh_p.family = AF_INET;
|
||||
nh_p.prefixlen = IPV4_MAX_BITLEN;
|
||||
nh_p.u.prefix4 = si->addr.ipv4;
|
||||
@ -95,19 +95,20 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||
break;
|
||||
case STATIC_IPV4_GATEWAY_IFNAME:
|
||||
nexthop = route_entry_nexthop_ipv4_ifindex_add(
|
||||
re, &si->addr.ipv4, NULL, si->ifindex);
|
||||
re, &si->addr.ipv4, NULL, si->ifindex,
|
||||
si->nh_vrf_id);
|
||||
break;
|
||||
case STATIC_IFNAME:
|
||||
nexthop = route_entry_nexthop_ifindex_add(re,
|
||||
si->ifindex);
|
||||
nexthop = route_entry_nexthop_ifindex_add(
|
||||
re, si->ifindex, si->nh_vrf_id);
|
||||
break;
|
||||
case STATIC_BLACKHOLE:
|
||||
nexthop = route_entry_nexthop_blackhole_add(
|
||||
re, bh_type);
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
nexthop = route_entry_nexthop_ipv6_add(re,
|
||||
&si->addr.ipv6);
|
||||
nexthop = route_entry_nexthop_ipv6_add(
|
||||
re, &si->addr.ipv6, si->nh_vrf_id);
|
||||
nh_p.family = AF_INET6;
|
||||
nh_p.prefixlen = IPV6_MAX_BITLEN;
|
||||
nh_p.u.prefix6 = si->addr.ipv6;
|
||||
@ -115,7 +116,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||
nexthop = route_entry_nexthop_ipv6_ifindex_add(
|
||||
re, &si->addr.ipv6, si->ifindex);
|
||||
re, &si->addr.ipv6, si->ifindex, si->nh_vrf_id);
|
||||
break;
|
||||
}
|
||||
/* Update label(s), if present. */
|
||||
@ -155,7 +156,6 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||
re->metric = 0;
|
||||
re->mtu = 0;
|
||||
re->vrf_id = si->vrf_id;
|
||||
re->nh_vrf_id = si->nh_vrf_id;
|
||||
re->table =
|
||||
(si->vrf_id != VRF_DEFAULT)
|
||||
? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id
|
||||
@ -166,7 +166,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||
switch (si->type) {
|
||||
case STATIC_IPV4_GATEWAY:
|
||||
nexthop = route_entry_nexthop_ipv4_add(
|
||||
re, &si->addr.ipv4, NULL);
|
||||
re, &si->addr.ipv4, NULL, si->nh_vrf_id);
|
||||
nh_p.family = AF_INET;
|
||||
nh_p.prefixlen = IPV4_MAX_BITLEN;
|
||||
nh_p.u.prefix4 = si->addr.ipv4;
|
||||
@ -174,19 +174,20 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||
break;
|
||||
case STATIC_IPV4_GATEWAY_IFNAME:
|
||||
nexthop = route_entry_nexthop_ipv4_ifindex_add(
|
||||
re, &si->addr.ipv4, NULL, si->ifindex);
|
||||
re, &si->addr.ipv4, NULL, si->ifindex,
|
||||
si->nh_vrf_id);
|
||||
break;
|
||||
case STATIC_IFNAME:
|
||||
nexthop = route_entry_nexthop_ifindex_add(re,
|
||||
si->ifindex);
|
||||
nexthop = route_entry_nexthop_ifindex_add(
|
||||
re, si->ifindex, si->nh_vrf_id);
|
||||
break;
|
||||
case STATIC_BLACKHOLE:
|
||||
nexthop = route_entry_nexthop_blackhole_add(
|
||||
re, bh_type);
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
nexthop = route_entry_nexthop_ipv6_add(re,
|
||||
&si->addr.ipv6);
|
||||
nexthop = route_entry_nexthop_ipv6_add(
|
||||
re, &si->addr.ipv6, si->nh_vrf_id);
|
||||
nh_p.family = AF_INET6;
|
||||
nh_p.prefixlen = IPV6_MAX_BITLEN;
|
||||
nh_p.u.prefix6 = si->addr.ipv6;
|
||||
@ -194,7 +195,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||
nexthop = route_entry_nexthop_ipv6_ifindex_add(
|
||||
re, &si->addr.ipv6, si->ifindex);
|
||||
re, &si->addr.ipv6, si->ifindex, si->nh_vrf_id);
|
||||
break;
|
||||
}
|
||||
/* Update label(s), if present. */
|
||||
|
||||
@ -41,6 +41,11 @@
|
||||
|
||||
extern struct zebra_t zebrad;
|
||||
|
||||
static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
|
||||
safi_t safi);
|
||||
static void zebra_rnhtable_node_cleanup(struct route_table *table,
|
||||
struct route_node *node);
|
||||
|
||||
/* VRF information update. */
|
||||
static void zebra_vrf_add_update(struct zebra_vrf *zvrf)
|
||||
{
|
||||
@ -82,7 +87,7 @@ static int zebra_vrf_new(struct vrf *vrf)
|
||||
struct zebra_vrf *zvrf;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
zlog_info("ZVRF %s with id %u", vrf->name, vrf->vrf_id);
|
||||
zlog_info("VRF %s created, id %u", vrf->name, vrf->vrf_id);
|
||||
|
||||
zvrf = zebra_vrf_alloc();
|
||||
zvrf->zns = zebra_ns_lookup(
|
||||
@ -101,14 +106,36 @@ static int zebra_vrf_enable(struct vrf *vrf)
|
||||
struct route_table *stable;
|
||||
struct route_node *rn;
|
||||
struct static_route *si;
|
||||
struct route_table *table;
|
||||
struct interface *ifp;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
|
||||
assert(zvrf);
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
zlog_debug("VRF %s id %u is now active",
|
||||
zvrf_name(zvrf), zvrf_id(zvrf));
|
||||
|
||||
/* Inform clients that the VRF is now active. This is an
|
||||
* add for the clients.
|
||||
*/
|
||||
zebra_vrf_add_update(zvrf);
|
||||
|
||||
/* Allocate tables */
|
||||
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
||||
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
|
||||
zebra_vrf_table_create(zvrf, afi, safi);
|
||||
|
||||
table = route_table_init();
|
||||
table->cleanup = zebra_rnhtable_node_cleanup;
|
||||
zvrf->rnh_table[afi] = table;
|
||||
|
||||
table = route_table_init();
|
||||
table->cleanup = zebra_rnhtable_node_cleanup;
|
||||
zvrf->import_check_table[afi] = table;
|
||||
}
|
||||
|
||||
/* Install any static routes configured for this VRF. */
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
|
||||
stable = zvrf->stable[afi][safi];
|
||||
@ -132,6 +159,9 @@ static int zebra_vrf_enable(struct vrf *vrf)
|
||||
}
|
||||
}
|
||||
|
||||
/* Kick off any VxLAN-EVPN processing. */
|
||||
zebra_vxlan_vrf_enable(zvrf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -142,13 +172,19 @@ static int zebra_vrf_disable(struct vrf *vrf)
|
||||
struct route_table *stable;
|
||||
struct route_node *rn;
|
||||
struct static_route *si;
|
||||
struct route_table *table;
|
||||
struct interface *ifp;
|
||||
u_int32_t table_id;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
unsigned i;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||
zlog_debug("VRF %s id %u is now disabled.", zvrf_name(zvrf),
|
||||
zvrf_id(zvrf));
|
||||
assert(zvrf);
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
zlog_debug("VRF %s id %u is now inactive",
|
||||
zvrf_name(zvrf), zvrf_id(zvrf));
|
||||
|
||||
/* Uninstall any static routes configured for this VRF. */
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
|
||||
stable = zvrf->stable[afi][safi];
|
||||
@ -161,6 +197,84 @@ static int zebra_vrf_disable(struct vrf *vrf)
|
||||
afi, safi, &rn->p, NULL, si);
|
||||
}
|
||||
|
||||
/* Stop any VxLAN-EVPN processing. */
|
||||
zebra_vxlan_vrf_disable(zvrf);
|
||||
|
||||
/* Inform clients that the VRF is now inactive. This is a
|
||||
* delete for the clients.
|
||||
*/
|
||||
zebra_vrf_delete_update(zvrf);
|
||||
|
||||
/* If asked to retain routes, there's nothing more to do. */
|
||||
if (CHECK_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN))
|
||||
return 0;
|
||||
|
||||
/* Remove all routes. */
|
||||
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
||||
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
|
||||
rib_close_table(zvrf->table[afi][safi]);
|
||||
|
||||
if (vrf->vrf_id == VRF_DEFAULT)
|
||||
for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX;
|
||||
table_id++)
|
||||
if (zvrf->other_table[afi][table_id])
|
||||
rib_close_table(zvrf->other_table[afi][table_id]);
|
||||
}
|
||||
|
||||
/* Cleanup Vxlan, MPLS and PW tables. */
|
||||
zebra_vxlan_cleanup_tables(zvrf);
|
||||
zebra_mpls_cleanup_tables(zvrf);
|
||||
zebra_pw_exit(zvrf);
|
||||
|
||||
/* Remove link-local IPv4 addresses created for BGP unnumbered peering. */
|
||||
FOR_ALL_INTERFACES (vrf, ifp)
|
||||
if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
|
||||
|
||||
/* clean-up work queues */
|
||||
for (i = 0; i < MQ_SIZE; i++) {
|
||||
struct listnode *lnode, *nnode;
|
||||
struct route_node *rnode;
|
||||
rib_dest_t *dest;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode, rnode)) {
|
||||
dest = rib_dest_from_rnode(rnode);
|
||||
if (dest && rib_dest_vrf(dest) == zvrf) {
|
||||
route_unlock_node(rnode);
|
||||
list_delete_node(zebrad.mq->subq[i], lnode);
|
||||
zebrad.mq->size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup (free) routing tables and NHT tables. */
|
||||
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
||||
void *table_info;
|
||||
|
||||
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
|
||||
table = zvrf->table[afi][safi];
|
||||
table_info = table->info;
|
||||
route_table_finish(table);
|
||||
XFREE(MTYPE_RIB_TABLE_INFO, table_info);
|
||||
zvrf->table[afi][safi] = NULL;
|
||||
}
|
||||
|
||||
if (vrf->vrf_id == VRF_DEFAULT)
|
||||
for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX;
|
||||
table_id++)
|
||||
if (zvrf->other_table[afi][table_id]) {
|
||||
table = zvrf->other_table[afi][table_id];
|
||||
table_info = table->info;
|
||||
route_table_finish(table);
|
||||
XFREE(MTYPE_RIB_TABLE_INFO, table_info);
|
||||
zvrf->other_table[afi][table_id] = NULL;
|
||||
}
|
||||
|
||||
route_table_finish(zvrf->rnh_table[afi]);
|
||||
zvrf->rnh_table[afi] = NULL;
|
||||
route_table_finish(zvrf->import_check_table[afi]);
|
||||
zvrf->import_check_table[afi] = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -174,38 +288,9 @@ static int zebra_vrf_delete(struct vrf *vrf)
|
||||
unsigned i;
|
||||
|
||||
assert(zvrf);
|
||||
|
||||
zebra_vrf_delete_update(zvrf);
|
||||
|
||||
/* uninstall everything */
|
||||
if (!CHECK_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN)) {
|
||||
struct interface *ifp;
|
||||
|
||||
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
||||
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST;
|
||||
safi++)
|
||||
rib_close_table(zvrf->table[afi][safi]);
|
||||
|
||||
if (vrf->vrf_id == VRF_DEFAULT)
|
||||
for (table_id = 0;
|
||||
table_id < ZEBRA_KERNEL_TABLE_MAX;
|
||||
table_id++)
|
||||
if (zvrf->other_table[afi][table_id])
|
||||
rib_close_table(
|
||||
zvrf->other_table
|
||||
[afi]
|
||||
[table_id]);
|
||||
}
|
||||
|
||||
/* Cleanup Vxlan table and update kernel */
|
||||
zebra_vxlan_close_tables(zvrf);
|
||||
|
||||
zebra_mpls_close_tables(zvrf);
|
||||
zebra_pw_exit(zvrf);
|
||||
|
||||
FOR_ALL_INTERFACES (vrf, ifp)
|
||||
if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
|
||||
}
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
zlog_debug("VRF %s id %u deleted",
|
||||
zvrf_name(zvrf), zvrf_id(zvrf));
|
||||
|
||||
/* clean-up work queues */
|
||||
for (i = 0; i < MQ_SIZE; i++) {
|
||||
@ -213,8 +298,7 @@ static int zebra_vrf_delete(struct vrf *vrf)
|
||||
struct route_node *rnode;
|
||||
rib_dest_t *dest;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode,
|
||||
rnode)) {
|
||||
for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode, rnode)) {
|
||||
dest = rib_dest_from_rnode(rnode);
|
||||
if (dest && rib_dest_vrf(dest) == zvrf) {
|
||||
route_unlock_node(rnode);
|
||||
@ -224,22 +308,27 @@ static int zebra_vrf_delete(struct vrf *vrf)
|
||||
}
|
||||
}
|
||||
|
||||
/* Free Vxlan and MPLS. */
|
||||
zebra_vxlan_close_tables(zvrf);
|
||||
zebra_mpls_close_tables(zvrf);
|
||||
|
||||
/* release allocated memory */
|
||||
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
||||
void *table_info;
|
||||
|
||||
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
|
||||
table = zvrf->table[afi][safi];
|
||||
table_info = table->info;
|
||||
route_table_finish(table);
|
||||
XFREE(MTYPE_RIB_TABLE_INFO, table_info);
|
||||
if (table) {
|
||||
table_info = table->info;
|
||||
route_table_finish(table);
|
||||
XFREE(MTYPE_RIB_TABLE_INFO, table_info);
|
||||
}
|
||||
|
||||
table = zvrf->stable[afi][safi];
|
||||
route_table_finish(table);
|
||||
}
|
||||
|
||||
for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX;
|
||||
table_id++)
|
||||
for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++)
|
||||
if (zvrf->other_table[afi][table_id]) {
|
||||
table = zvrf->other_table[afi][table_id];
|
||||
table_info = table->info;
|
||||
@ -251,7 +340,7 @@ static int zebra_vrf_delete(struct vrf *vrf)
|
||||
route_table_finish(zvrf->import_check_table[afi]);
|
||||
}
|
||||
|
||||
/* cleanup evpn states for vrf */
|
||||
/* Cleanup EVPN states for vrf */
|
||||
zebra_vxlan_vrf_delete(zvrf);
|
||||
|
||||
list_delete_all_node(zvrf->rid_all_sorted_list);
|
||||
@ -262,6 +351,37 @@ static int zebra_vrf_delete(struct vrf *vrf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return if this VRF has any FRR configuration or not.
|
||||
* IMPORTANT: This function needs to be updated when additional configuration
|
||||
* is added for a VRF.
|
||||
*/
|
||||
int zebra_vrf_has_config(struct zebra_vrf *zvrf)
|
||||
{
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
struct route_table *stable;
|
||||
|
||||
/* NOTE: This is a don't care for the default VRF, but we go through
|
||||
* the motions to keep things consistent.
|
||||
*/
|
||||
/* Any static routes? */
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
|
||||
stable = zvrf->stable[afi][safi];
|
||||
if (!stable)
|
||||
continue;
|
||||
if (route_table_count(stable))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* EVPN L3-VNI? */
|
||||
if (zvrf->l3vni)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Lookup the routing table in a VRF based on both VRF-Id and table-id.
|
||||
* NOTE: Table-id is relevant only in the Default VRF.
|
||||
*/
|
||||
@ -354,9 +474,9 @@ struct zebra_vrf *zebra_vrf_alloc(void)
|
||||
|
||||
zvrf = XCALLOC(MTYPE_ZEBRA_VRF, sizeof(struct zebra_vrf));
|
||||
|
||||
/* Allocate table for static route configuration. */
|
||||
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
||||
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
|
||||
zebra_vrf_table_create(zvrf, afi, safi);
|
||||
if (afi == AFI_IP6)
|
||||
table = srcdest_table_init();
|
||||
else
|
||||
@ -364,14 +484,6 @@ struct zebra_vrf *zebra_vrf_alloc(void)
|
||||
table->cleanup = zebra_stable_node_cleanup;
|
||||
zvrf->stable[afi][safi] = table;
|
||||
}
|
||||
|
||||
table = route_table_init();
|
||||
table->cleanup = zebra_rnhtable_node_cleanup;
|
||||
zvrf->rnh_table[afi] = table;
|
||||
|
||||
table = route_table_init();
|
||||
table->cleanup = zebra_rnhtable_node_cleanup;
|
||||
zvrf->import_check_table[afi] = table;
|
||||
}
|
||||
|
||||
zebra_vxlan_init_tables(zvrf);
|
||||
@ -477,16 +589,23 @@ static int vrf_config_write(struct vty *vty)
|
||||
if (!zvrf)
|
||||
continue;
|
||||
|
||||
if (vrf->vrf_id != VRF_DEFAULT)
|
||||
if (zvrf_id(zvrf) == VRF_DEFAULT) {
|
||||
if (zvrf->l3vni)
|
||||
vty_out(vty, "vni %u\n", zvrf->l3vni);
|
||||
vty_out(vty, "!\n");
|
||||
}
|
||||
|
||||
if (vrf_is_user_cfged(vrf)) {
|
||||
vty_out(vty, "vrf %s\n", zvrf_name(zvrf));
|
||||
if (zvrf->l3vni)
|
||||
vty_out(vty, " vni %u\n", zvrf->l3vni);
|
||||
vty_out(vty, "!\n");
|
||||
}
|
||||
|
||||
static_config(vty, zvrf, AFI_IP, SAFI_UNICAST, "ip route");
|
||||
static_config(vty, zvrf, AFI_IP, SAFI_MULTICAST, "ip mroute");
|
||||
static_config(vty, zvrf, AFI_IP6, SAFI_UNICAST, "ipv6 route");
|
||||
|
||||
if (vrf->vrf_id != VRF_DEFAULT && zvrf->l3vni)
|
||||
vty_out(vty, " vni %u\n", zvrf->l3vni);
|
||||
|
||||
if (vrf->vrf_id != VRF_DEFAULT)
|
||||
vty_out(vty, "!\n");
|
||||
}
|
||||
|
||||
@ -79,6 +79,9 @@ struct zebra_vrf {
|
||||
*/
|
||||
struct zebra_ns *zns;
|
||||
|
||||
/* MPLS Label to handle L3VPN <-> vrf popping */
|
||||
mpls_label_t label;
|
||||
|
||||
/* MPLS static LSP config table */
|
||||
struct hash *slsp_table;
|
||||
|
||||
@ -149,5 +152,6 @@ extern struct route_table *zebra_vrf_static_table(afi_t, safi_t,
|
||||
struct zebra_vrf *zvrf);
|
||||
extern struct route_table *
|
||||
zebra_vrf_other_route_table(afi_t afi, u_int32_t table_id, vrf_id_t vrf_id);
|
||||
extern int zebra_vrf_has_config(struct zebra_vrf *zvrf);
|
||||
extern void zebra_vrf_init(void);
|
||||
#endif
|
||||
|
||||
@ -165,8 +165,8 @@ static int zebra_static_route_leak(struct vty *vty,
|
||||
case -2:
|
||||
vty_out(vty,
|
||||
"%% Cannot use reserved label(s) (%d-%d)\n",
|
||||
MPLS_MIN_RESERVED_LABEL,
|
||||
MPLS_MAX_RESERVED_LABEL);
|
||||
MPLS_LABEL_RESERVED_MIN,
|
||||
MPLS_LABEL_RESERVED_MAX);
|
||||
break;
|
||||
case -3:
|
||||
vty_out(vty,
|
||||
@ -231,13 +231,19 @@ static int zebra_static_route_leak(struct vty *vty,
|
||||
type = STATIC_IPV6_GATEWAY;
|
||||
}
|
||||
|
||||
if (!negate)
|
||||
if (!negate) {
|
||||
static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
|
||||
bh_type, tag, distance, zvrf, nh_zvrf,
|
||||
&snh_label);
|
||||
else
|
||||
/* Mark as having FRR configuration */
|
||||
vrf_set_user_cfged(zvrf->vrf);
|
||||
} else {
|
||||
static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
|
||||
tag, distance, zvrf, &snh_label);
|
||||
/* If no other FRR config for this VRF, mark accordingly. */
|
||||
if (!zebra_vrf_has_config(zvrf))
|
||||
vrf_reset_user_cfged(zvrf->vrf);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -247,19 +253,39 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
|
||||
const char *mask_str, const char *src_str,
|
||||
const char *gate_str, const char *ifname,
|
||||
const char *flag_str, const char *tag_str,
|
||||
const char *distance_str, const char *vrf_id_str,
|
||||
const char *distance_str, const char *vrf_name,
|
||||
const char *label_str)
|
||||
{
|
||||
struct zebra_vrf *zvrf;
|
||||
struct vrf *vrf;
|
||||
|
||||
/* VRF id */
|
||||
zvrf = zebra_vrf_lookup_by_name(vrf_id_str);
|
||||
zvrf = zebra_vrf_lookup_by_name(vrf_name);
|
||||
|
||||
if (!zvrf) {
|
||||
vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str);
|
||||
/* When trying to delete, the VRF must exist. */
|
||||
if (negate && !zvrf) {
|
||||
vty_out(vty, "%% vrf %s is not defined\n", vrf_name);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* When trying to create, create the VRF if it doesn't exist.
|
||||
* Note: The VRF isn't active until we hear about it from the kernel.
|
||||
*/
|
||||
if (!zvrf) {
|
||||
vrf = vrf_get(VRF_UNKNOWN, vrf_name);
|
||||
if (!vrf) {
|
||||
vty_out(vty, "%% Could not create vrf %s\n", vrf_name);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
zvrf = vrf->info;
|
||||
if (!zvrf) {
|
||||
vty_out(vty, "%% Could not create vrf-info %s\n",
|
||||
vrf_name);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
/* Mark as having FRR configuration */
|
||||
vrf_set_user_cfged(vrf);
|
||||
}
|
||||
return zebra_static_route_leak(vty, zvrf, zvrf, afi, safi,
|
||||
negate, dest_str, mask_str, src_str,
|
||||
gate_str, ifname, flag_str, tag_str,
|
||||
@ -535,7 +561,11 @@ DEFPY(ip_route_address_interface_vrf,
|
||||
ifname = NULL;
|
||||
}
|
||||
|
||||
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
|
||||
if (nexthop_vrf)
|
||||
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
|
||||
else
|
||||
nh_zvrf = zvrf;
|
||||
|
||||
if (!nh_zvrf) {
|
||||
vty_out(vty, "%% nexthop vrf %s is not defined\n",
|
||||
nexthop_vrf);
|
||||
@ -642,7 +672,11 @@ DEFPY(ip_route_vrf,
|
||||
ifname = NULL;
|
||||
}
|
||||
|
||||
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
|
||||
if (nexthop_vrf)
|
||||
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
|
||||
else
|
||||
nh_zvrf = zvrf;
|
||||
|
||||
if (!nh_zvrf) {
|
||||
vty_out(vty, "%% nexthop vrf %s is not defined\n",
|
||||
nexthop_vrf);
|
||||
@ -736,8 +770,9 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
|
||||
inet_ntoa(nexthop->gate.ipv4));
|
||||
if (nexthop->ifindex)
|
||||
vty_out(vty, ", via %s",
|
||||
ifindex2ifname(nexthop->ifindex,
|
||||
re->nh_vrf_id));
|
||||
ifindex2ifname(
|
||||
nexthop->ifindex,
|
||||
nexthop->vrf_id));
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||
@ -746,13 +781,14 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
|
||||
buf, sizeof buf));
|
||||
if (nexthop->ifindex)
|
||||
vty_out(vty, ", via %s",
|
||||
ifindex2ifname(nexthop->ifindex,
|
||||
re->nh_vrf_id));
|
||||
ifindex2ifname(
|
||||
nexthop->ifindex,
|
||||
nexthop->vrf_id));
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
vty_out(vty, " directly connected, %s",
|
||||
ifindex2ifname(nexthop->ifindex,
|
||||
re->nh_vrf_id));
|
||||
nexthop->vrf_id));
|
||||
break;
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
vty_out(vty, " unreachable");
|
||||
@ -775,9 +811,9 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
|
||||
break;
|
||||
}
|
||||
|
||||
if (re->vrf_id != re->nh_vrf_id) {
|
||||
if (re->vrf_id != nexthop->vrf_id) {
|
||||
struct vrf *vrf =
|
||||
vrf_lookup_by_id(re->nh_vrf_id);
|
||||
vrf_lookup_by_id(nexthop->vrf_id);
|
||||
|
||||
vty_out(vty, "(vrf %s)", vrf->name);
|
||||
}
|
||||
@ -920,8 +956,9 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
||||
nexthop->ifindex);
|
||||
json_object_string_add(
|
||||
json_nexthop, "interfaceName",
|
||||
ifindex2ifname(nexthop->ifindex,
|
||||
re->nh_vrf_id));
|
||||
ifindex2ifname(
|
||||
nexthop->ifindex,
|
||||
nexthop->vrf_id));
|
||||
}
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
@ -939,8 +976,9 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
||||
nexthop->ifindex);
|
||||
json_object_string_add(
|
||||
json_nexthop, "interfaceName",
|
||||
ifindex2ifname(nexthop->ifindex,
|
||||
re->nh_vrf_id));
|
||||
ifindex2ifname(
|
||||
nexthop->ifindex,
|
||||
nexthop->vrf_id));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -953,7 +991,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
||||
json_object_string_add(
|
||||
json_nexthop, "interfaceName",
|
||||
ifindex2ifname(nexthop->ifindex,
|
||||
re->nh_vrf_id));
|
||||
nexthop->vrf_id));
|
||||
break;
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
json_object_boolean_true_add(json_nexthop,
|
||||
@ -980,9 +1018,9 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
||||
break;
|
||||
}
|
||||
|
||||
if (re->nh_vrf_id != re->vrf_id) {
|
||||
if (nexthop->vrf_id != re->vrf_id) {
|
||||
struct vrf *vrf =
|
||||
vrf_lookup_by_id(re->nh_vrf_id);
|
||||
vrf_lookup_by_id(nexthop->vrf_id);
|
||||
|
||||
json_object_string_add(json_nexthop,
|
||||
"vrf",
|
||||
@ -1095,7 +1133,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
||||
if (nexthop->ifindex)
|
||||
vty_out(vty, ", %s",
|
||||
ifindex2ifname(nexthop->ifindex,
|
||||
re->nh_vrf_id));
|
||||
nexthop->vrf_id));
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||
@ -1105,13 +1143,13 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
||||
if (nexthop->ifindex)
|
||||
vty_out(vty, ", %s",
|
||||
ifindex2ifname(nexthop->ifindex,
|
||||
re->nh_vrf_id));
|
||||
nexthop->vrf_id));
|
||||
break;
|
||||
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
vty_out(vty, " is directly connected, %s",
|
||||
ifindex2ifname(nexthop->ifindex,
|
||||
re->nh_vrf_id));
|
||||
nexthop->vrf_id));
|
||||
break;
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
vty_out(vty, " unreachable");
|
||||
@ -1133,9 +1171,8 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
||||
break;
|
||||
}
|
||||
|
||||
if (re->nh_vrf_id != re->vrf_id) {
|
||||
struct vrf *vrf =
|
||||
vrf_lookup_by_id(re->nh_vrf_id);
|
||||
if (nexthop->vrf_id != re->vrf_id) {
|
||||
struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
|
||||
|
||||
vty_out(vty, "(vrf %s)", vrf->name);
|
||||
}
|
||||
@ -2066,7 +2103,11 @@ DEFPY(ipv6_route_address_interface_vrf,
|
||||
struct zebra_vrf *zvrf = vrf->info;
|
||||
struct zebra_vrf *nh_zvrf;
|
||||
|
||||
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
|
||||
if (nexthop_vrf)
|
||||
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
|
||||
else
|
||||
nh_zvrf = zvrf;
|
||||
|
||||
if (!nh_zvrf) {
|
||||
vty_out(vty, "%% nexthop vrf %s is not defined\n",
|
||||
nexthop_vrf);
|
||||
@ -2160,7 +2201,11 @@ DEFPY(ipv6_route_vrf,
|
||||
struct zebra_vrf *zvrf = vrf->info;
|
||||
struct zebra_vrf *nh_zvrf;
|
||||
|
||||
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
|
||||
if (nexthop_vrf)
|
||||
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
|
||||
else
|
||||
nh_zvrf = zvrf;
|
||||
|
||||
if (!nh_zvrf) {
|
||||
vty_out(vty, "%% nexthop vrf %s is not defined\n",
|
||||
nexthop_vrf);
|
||||
@ -2286,16 +2331,67 @@ DEFUN (show_vrf,
|
||||
else
|
||||
vty_out(vty, "id %u table %u", zvrf_id(zvrf),
|
||||
zvrf->table_id);
|
||||
if (vrf_is_user_cfged(vrf))
|
||||
vty_out(vty, " (configured)");
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (default_vrf_vni_mapping,
|
||||
default_vrf_vni_mapping_cmd,
|
||||
"vni " CMD_VNI_RANGE,
|
||||
"VNI corresponding to the DEFAULT VRF\n"
|
||||
"VNI-ID\n")
|
||||
{
|
||||
int ret = 0;
|
||||
char err[ERR_STR_SZ];
|
||||
struct zebra_vrf *zvrf = NULL;
|
||||
vni_t vni = strtoul(argv[1]->arg, NULL, 10);
|
||||
|
||||
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
||||
if (!zvrf)
|
||||
return CMD_WARNING;
|
||||
|
||||
ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 1);
|
||||
if (ret != 0) {
|
||||
vty_out(vty, "%s\n", err);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_default_vrf_vni_mapping,
|
||||
no_default_vrf_vni_mapping_cmd,
|
||||
"no vni " CMD_VNI_RANGE,
|
||||
NO_STR
|
||||
"VNI corresponding to DEFAULT VRF\n"
|
||||
"VNI-ID")
|
||||
{
|
||||
int ret = 0;
|
||||
char err[ERR_STR_SZ];
|
||||
vni_t vni = strtoul(argv[2]->arg, NULL, 10);
|
||||
struct zebra_vrf *zvrf = NULL;
|
||||
|
||||
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
||||
if (!zvrf)
|
||||
return CMD_WARNING;
|
||||
|
||||
ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 0);
|
||||
if (ret != 0) {
|
||||
vty_out(vty, "%s\n", err);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (vrf_vni_mapping,
|
||||
vrf_vni_mapping_cmd,
|
||||
"vni " CMD_VNI_RANGE,
|
||||
"VNI\n"
|
||||
"VNI corresponding to tenant VRF\n"
|
||||
"VNI-ID\n")
|
||||
{
|
||||
int ret = 0;
|
||||
@ -2307,6 +2403,8 @@ DEFUN (vrf_vni_mapping,
|
||||
assert(vrf);
|
||||
assert(zvrf);
|
||||
|
||||
/* Mark as having FRR configuration */
|
||||
vrf_set_user_cfged(vrf);
|
||||
ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 1);
|
||||
if (ret != 0) {
|
||||
vty_out(vty, "%s\n", err);
|
||||
@ -2320,7 +2418,7 @@ DEFUN (no_vrf_vni_mapping,
|
||||
no_vrf_vni_mapping_cmd,
|
||||
"no vni " CMD_VNI_RANGE,
|
||||
NO_STR
|
||||
"VNI\n"
|
||||
"VNI corresponding to tenant VRF\n"
|
||||
"VNI-ID")
|
||||
{
|
||||
int ret = 0;
|
||||
@ -2338,6 +2436,10 @@ DEFUN (no_vrf_vni_mapping,
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
/* If no other FRR config for this VRF, mark accordingly. */
|
||||
if (!zebra_vrf_has_config(zvrf))
|
||||
vrf_reset_user_cfged(vrf);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2361,29 +2463,16 @@ DEFUN (show_vrf_vni,
|
||||
json_vrfs = json_object_new_array();
|
||||
}
|
||||
|
||||
if (!uj)
|
||||
vty_out(vty, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
|
||||
"VRF", "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
|
||||
|
||||
RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
|
||||
zvrf = vrf->info;
|
||||
if (!zvrf)
|
||||
continue;
|
||||
|
||||
if (!zvrf->l3vni)
|
||||
continue;
|
||||
|
||||
if (!uj) {
|
||||
vty_out(vty, "vrf: %s VNI: %u",
|
||||
zvrf_name(zvrf),
|
||||
zvrf->l3vni);
|
||||
vty_out(vty, "\n");
|
||||
} else {
|
||||
json_object *json_vrf = NULL;
|
||||
|
||||
json_vrf = json_object_new_object();
|
||||
json_object_string_add(json_vrf, "vrf",
|
||||
zvrf_name(zvrf));
|
||||
json_object_int_add(json_vrf, "l3vni",
|
||||
zvrf->l3vni);
|
||||
json_object_array_add(json_vrfs, json_vrf);
|
||||
}
|
||||
zebra_vxlan_print_vrf_vni(vty, zvrf, json_vrfs);
|
||||
}
|
||||
|
||||
if (uj) {
|
||||
@ -2396,6 +2485,19 @@ DEFUN (show_vrf_vni,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_evpn_global,
|
||||
show_evpn_global_cmd,
|
||||
"show evpn [json]",
|
||||
SHOW_STR
|
||||
"EVPN\n"
|
||||
JSON_STR)
|
||||
{
|
||||
u_char uj = use_json(argc, argv);
|
||||
|
||||
zebra_vxlan_print_evpn(vty, uj);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_evpn_vni,
|
||||
show_evpn_vni_cmd,
|
||||
"show evpn vni [json]",
|
||||
@ -2431,44 +2533,13 @@ DEFUN (show_evpn_vni_vni,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_evpn_l3vni,
|
||||
show_evpn_l3vni_cmd,
|
||||
"show evpn l3vni [json]",
|
||||
SHOW_STR
|
||||
"EVPN\n"
|
||||
"L3 VNI\n"
|
||||
JSON_STR)
|
||||
{
|
||||
u_char uj = use_json(argc, argv);
|
||||
|
||||
zebra_vxlan_print_l3vnis(vty, uj);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_evpn_l3vni_vni,
|
||||
show_evpn_l3vni_vni_cmd,
|
||||
"show evpn l3vni " CMD_VNI_RANGE "[json]",
|
||||
SHOW_STR
|
||||
"EVPN\n"
|
||||
"L3 VxLAN Network Identifier\n"
|
||||
"VNI number\n"
|
||||
JSON_STR)
|
||||
{
|
||||
vni_t vni;
|
||||
u_char uj = use_json(argc, argv);
|
||||
|
||||
vni = strtoul(argv[3]->arg, NULL, 10);
|
||||
zebra_vxlan_print_l3vni(vty, vni, uj);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_evpn_rmac_l3vni_mac,
|
||||
show_evpn_rmac_l3vni_mac_cmd,
|
||||
"show evpn rmac l3vni " CMD_VNI_RANGE " mac WORD [json]",
|
||||
DEFUN (show_evpn_rmac_vni_mac,
|
||||
show_evpn_rmac_vni_mac_cmd,
|
||||
"show evpn rmac vni " CMD_VNI_RANGE " mac WORD [json]",
|
||||
SHOW_STR
|
||||
"EVPN\n"
|
||||
"RMAC\n"
|
||||
"L3-VNI\n"
|
||||
"L3 VNI\n"
|
||||
"VNI number\n"
|
||||
"MAC\n"
|
||||
"mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
|
||||
@ -2487,13 +2558,13 @@ DEFUN (show_evpn_rmac_l3vni_mac,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_evpn_rmac_l3vni,
|
||||
show_evpn_rmac_l3vni_cmd,
|
||||
"show evpn rmac l3vni " CMD_VNI_RANGE "[json]",
|
||||
DEFUN (show_evpn_rmac_vni,
|
||||
show_evpn_rmac_vni_cmd,
|
||||
"show evpn rmac vni " CMD_VNI_RANGE "[json]",
|
||||
SHOW_STR
|
||||
"EVPN\n"
|
||||
"RMAC\n"
|
||||
"L3-VNI\n"
|
||||
"L3 VNI\n"
|
||||
"VNI number\n"
|
||||
JSON_STR)
|
||||
{
|
||||
@ -2506,13 +2577,13 @@ DEFUN (show_evpn_rmac_l3vni,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_evpn_rmac_l3vni_all,
|
||||
show_evpn_rmac_l3vni_all_cmd,
|
||||
"show evpn rmac l3vni all [json]",
|
||||
DEFUN (show_evpn_rmac_vni_all,
|
||||
show_evpn_rmac_vni_all_cmd,
|
||||
"show evpn rmac vni all [json]",
|
||||
SHOW_STR
|
||||
"EVPN\n"
|
||||
"RMAC addresses\n"
|
||||
"L3-VNI\n"
|
||||
"L3 VNI\n"
|
||||
"All VNIs\n"
|
||||
JSON_STR)
|
||||
{
|
||||
@ -2523,13 +2594,13 @@ DEFUN (show_evpn_rmac_l3vni_all,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_evpn_nh_l3vni_ip,
|
||||
show_evpn_nh_l3vni_ip_cmd,
|
||||
"show evpn next-hops l3vni " CMD_VNI_RANGE " ip WORD [json]",
|
||||
DEFUN (show_evpn_nh_vni_ip,
|
||||
show_evpn_nh_vni_ip_cmd,
|
||||
"show evpn next-hops vni " CMD_VNI_RANGE " ip WORD [json]",
|
||||
SHOW_STR
|
||||
"EVPN\n"
|
||||
"Remote Vteps\n"
|
||||
"L3-VNI\n"
|
||||
"L3 VNI\n"
|
||||
"VNI number\n"
|
||||
"Ip address\n"
|
||||
"Host address (ipv4 or ipv6)\n"
|
||||
@ -2550,13 +2621,13 @@ DEFUN (show_evpn_nh_l3vni_ip,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_evpn_nh_l3vni,
|
||||
show_evpn_nh_l3vni_cmd,
|
||||
"show evpn next-hops l3vni " CMD_VNI_RANGE "[json]",
|
||||
DEFUN (show_evpn_nh_vni,
|
||||
show_evpn_nh_vni_cmd,
|
||||
"show evpn next-hops vni " CMD_VNI_RANGE "[json]",
|
||||
SHOW_STR
|
||||
"EVPN\n"
|
||||
"Remote Vteps\n"
|
||||
"L3-VNI\n"
|
||||
"L3 VNI\n"
|
||||
"VNI number\n"
|
||||
JSON_STR)
|
||||
{
|
||||
@ -2569,13 +2640,13 @@ DEFUN (show_evpn_nh_l3vni,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_evpn_nh_l3vni_all,
|
||||
show_evpn_nh_l3vni_all_cmd,
|
||||
"show evpn next-hops l3vni all [json]",
|
||||
DEFUN (show_evpn_nh_vni_all,
|
||||
show_evpn_nh_vni_all_cmd,
|
||||
"show evpn next-hops vni all [json]",
|
||||
SHOW_STR
|
||||
"EVPN\n"
|
||||
"Remote VTEPs\n"
|
||||
"L3-VNI\n"
|
||||
"L3 VNI\n"
|
||||
"All VNIs\n"
|
||||
JSON_STR)
|
||||
{
|
||||
@ -3283,16 +3354,15 @@ void zebra_vty_init(void)
|
||||
/* Commands for VRF */
|
||||
install_element(VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd);
|
||||
|
||||
install_element(VIEW_NODE, &show_evpn_global_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_vni_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_vni_vni_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_l3vni_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_l3vni_vni_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_rmac_l3vni_mac_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_rmac_l3vni_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_rmac_l3vni_all_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_nh_l3vni_ip_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_nh_l3vni_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_nh_l3vni_all_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_rmac_vni_mac_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_rmac_vni_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_rmac_vni_all_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_nh_vni_ip_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_nh_vni_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_nh_vni_all_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
|
||||
@ -3303,7 +3373,8 @@ void zebra_vty_init(void)
|
||||
install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
|
||||
|
||||
install_element(CONFIG_NODE, &no_vrf_vni_mapping_cmd);
|
||||
install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
|
||||
install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
|
||||
install_element(VRF_NODE, &vrf_vni_mapping_cmd);
|
||||
install_element(VRF_NODE, &no_vrf_vni_mapping_cmd);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -31,6 +31,7 @@
|
||||
#include "vlan.h"
|
||||
#include "vxlan.h"
|
||||
|
||||
#include "lib/json.h"
|
||||
#include "zebra/zebra_vrf.h"
|
||||
|
||||
/* Is EVPN enabled? */
|
||||
@ -53,8 +54,12 @@ is_evpn_enabled()
|
||||
|
||||
extern ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id);
|
||||
extern int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf);
|
||||
extern int zebra_vxlan_vrf_enable(struct zebra_vrf *zvrf);
|
||||
extern int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf);
|
||||
extern int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf);
|
||||
extern void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
|
||||
struct ipaddr *ip, u_char uj);
|
||||
extern void zebra_vxlan_print_evpn(struct vty *vty, u_char uj);
|
||||
extern void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
|
||||
struct ethaddr *rmac,
|
||||
u_char use_json);
|
||||
@ -99,9 +104,8 @@ extern void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t vni, u_char
|
||||
extern void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, u_char use_json);
|
||||
extern void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni,
|
||||
u_char use_json);
|
||||
extern void zebra_vxlan_print_l3vnis(struct vty *vty,
|
||||
u_char use_json);
|
||||
|
||||
extern void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf,
|
||||
json_object *json_vrfs);
|
||||
extern int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
|
||||
int add);
|
||||
extern int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if);
|
||||
@ -140,6 +144,8 @@ extern int zebra_vxlan_remote_vtep_add(struct zserv *client,
|
||||
u_short length, struct zebra_vrf *zvrf);
|
||||
extern int zebra_vxlan_remote_vtep_del(struct zserv *client,
|
||||
u_short length, struct zebra_vrf *zvrf);
|
||||
extern int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvrf);
|
||||
extern int zebra_vxlan_advertise_gw_macip(struct zserv *client,
|
||||
u_short length,
|
||||
struct zebra_vrf *zvrf);
|
||||
@ -151,6 +157,7 @@ extern int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
|
||||
int err_str_sz, int add);
|
||||
extern void zebra_vxlan_init_tables(struct zebra_vrf *zvrf);
|
||||
extern void zebra_vxlan_close_tables(struct zebra_vrf *);
|
||||
extern void zebra_vxlan_cleanup_tables(struct zebra_vrf *);
|
||||
extern void zebra_vxlan_ns_init(struct zebra_ns *zns);
|
||||
extern void zebra_vxlan_ns_disable(struct zebra_ns *zns);
|
||||
extern void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id,
|
||||
|
||||
@ -83,6 +83,10 @@ void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf)
|
||||
{
|
||||
}
|
||||
|
||||
void zebra_vxlan_print_evpn(struct vty *vty, u_char uj)
|
||||
{
|
||||
}
|
||||
|
||||
void zebra_vxlan_print_rmacs_l3vni(struct vty*, vni_t, u_char)
|
||||
{
|
||||
}
|
||||
@ -103,10 +107,6 @@ void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni)
|
||||
{
|
||||
}
|
||||
|
||||
void zebra_vxlan_print_l3vnis(struct vty *vty)
|
||||
{
|
||||
}
|
||||
|
||||
int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
|
||||
{
|
||||
return 0;
|
||||
@ -207,3 +207,7 @@ void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
|
||||
void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
|
||||
{
|
||||
}
|
||||
|
||||
void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf)
|
||||
{
|
||||
}
|
||||
|
||||
@ -70,6 +70,9 @@ struct zebra_vni_t_ {
|
||||
/* Flag for advertising gw macip */
|
||||
u_int8_t advertise_gw_macip;
|
||||
|
||||
/* Flag for advertising gw macip */
|
||||
u_int8_t advertise_subnet;
|
||||
|
||||
/* Corresponding VxLAN interface. */
|
||||
struct interface *vxlan_if;
|
||||
|
||||
@ -233,6 +236,7 @@ struct zebra_mac_t_ {
|
||||
#define ZEBRA_MAC_AUTO 0x04 /* Auto created for neighbor. */
|
||||
#define ZEBRA_MAC_STICKY 0x08 /* Static MAC */
|
||||
#define ZEBRA_MAC_REMOTE_RMAC 0x10 /* remote router mac */
|
||||
#define ZEBRA_MAC_DEF_GW 0x20
|
||||
|
||||
/* Local or remote info. */
|
||||
union {
|
||||
@ -314,6 +318,7 @@ struct zebra_neigh_t_ {
|
||||
#define ZEBRA_NEIGH_LOCAL 0x01
|
||||
#define ZEBRA_NEIGH_REMOTE 0x02
|
||||
#define ZEBRA_NEIGH_REMOTE_NH 0x04 /* neigh entry for remote vtep */
|
||||
#define ZEBRA_NEIGH_DEF_GW 0x08
|
||||
|
||||
enum zebra_neigh_state state;
|
||||
|
||||
|
||||
102
zebra/zserv.c
102
zebra/zserv.c
@ -592,7 +592,6 @@ int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = re->vrf_id;
|
||||
api.nh_vrf_id = re->nh_vrf_id;
|
||||
api.type = re->type;
|
||||
api.instance = re->instance;
|
||||
api.flags = re->flags;
|
||||
@ -614,6 +613,7 @@ int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
|
||||
continue;
|
||||
|
||||
api_nh = &api.nexthops[count];
|
||||
api_nh->vrf_id = nexthop->vrf_id;
|
||||
api_nh->type = nexthop->type;
|
||||
switch (nexthop->type) {
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
@ -1137,7 +1137,6 @@ static int zread_route_add(struct zserv *client, u_short length,
|
||||
re->flags = api.flags;
|
||||
re->uptime = time(NULL);
|
||||
re->vrf_id = vrf_id;
|
||||
re->nh_vrf_id = api.nh_vrf_id;
|
||||
re->table = zvrf->table_id;
|
||||
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
@ -1148,11 +1147,12 @@ static int zread_route_add(struct zserv *client, u_short length,
|
||||
switch (api_nh->type) {
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
nexthop = route_entry_nexthop_ifindex_add(
|
||||
re, api_nh->ifindex);
|
||||
re, api_nh->ifindex, re->vrf_id);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
nexthop = route_entry_nexthop_ipv4_add(
|
||||
re, &api_nh->gate.ipv4, NULL);
|
||||
re, &api_nh->gate.ipv4, NULL,
|
||||
re->vrf_id);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX: {
|
||||
|
||||
@ -1168,8 +1168,8 @@ static int zread_route_add(struct zserv *client, u_short length,
|
||||
}
|
||||
|
||||
nexthop = route_entry_nexthop_ipv4_ifindex_add(
|
||||
re, &api_nh->gate.ipv4, NULL,
|
||||
ifindex);
|
||||
re, &api_nh->gate.ipv4, NULL, ifindex,
|
||||
re->vrf_id);
|
||||
|
||||
/* if this an EVPN route entry,
|
||||
program the nh as neigh
|
||||
@ -1192,12 +1192,12 @@ static int zread_route_add(struct zserv *client, u_short length,
|
||||
}
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
nexthop = route_entry_nexthop_ipv6_add(
|
||||
re, &api_nh->gate.ipv6);
|
||||
re, &api_nh->gate.ipv6, re->vrf_id);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||
nexthop = route_entry_nexthop_ipv6_ifindex_add(
|
||||
re, &api_nh->gate.ipv6,
|
||||
api_nh->ifindex);
|
||||
re, &api_nh->gate.ipv6, api_nh->ifindex,
|
||||
re->vrf_id);
|
||||
break;
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
nexthop = route_entry_nexthop_blackhole_add(
|
||||
@ -1364,7 +1364,6 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
|
||||
|
||||
/* VRF ID */
|
||||
re->vrf_id = zvrf_id(zvrf);
|
||||
re->nh_vrf_id = zvrf_id(zvrf);
|
||||
|
||||
/* Nexthop parse. */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
@ -1381,13 +1380,14 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
|
||||
switch (nexthop_type) {
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
STREAM_GETL(s, ifindex);
|
||||
route_entry_nexthop_ifindex_add(re, ifindex);
|
||||
route_entry_nexthop_ifindex_add(re, ifindex,
|
||||
re->vrf_id);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
STREAM_GET(&nhop_addr.s_addr, s,
|
||||
IPV4_MAX_BYTELEN);
|
||||
nexthop = route_entry_nexthop_ipv4_add(
|
||||
re, &nhop_addr, NULL);
|
||||
re, &nhop_addr, NULL, re->vrf_id);
|
||||
/* For labeled-unicast, each nexthop is followed
|
||||
* by label. */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) {
|
||||
@ -1401,7 +1401,8 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
|
||||
IPV4_MAX_BYTELEN);
|
||||
STREAM_GETL(s, ifindex);
|
||||
route_entry_nexthop_ipv4_ifindex_add(
|
||||
re, &nhop_addr, NULL, ifindex);
|
||||
re, &nhop_addr, NULL, ifindex,
|
||||
re->vrf_id);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
zlog_warn("%s: Please use ZEBRA_ROUTE_ADD if you want to pass v6 nexthops",
|
||||
@ -1574,7 +1575,6 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
|
||||
|
||||
/* VRF ID */
|
||||
re->vrf_id = zvrf_id(zvrf);
|
||||
re->nh_vrf_id = zvrf_id(zvrf);
|
||||
|
||||
/* We need to give nh-addr, nh-ifindex with the same next-hop object
|
||||
* to the re to ensure that IPv6 multipathing works; need to coalesce
|
||||
@ -1635,10 +1635,11 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
|
||||
nexthop =
|
||||
route_entry_nexthop_ipv6_ifindex_add(
|
||||
re, &nexthops[i],
|
||||
ifindices[i]);
|
||||
ifindices[i],
|
||||
re->vrf_id);
|
||||
else
|
||||
nexthop = route_entry_nexthop_ipv6_add(
|
||||
re, &nexthops[i]);
|
||||
re, &nexthops[i], re->vrf_id);
|
||||
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
||||
nexthop_add_labels(nexthop, label_type,
|
||||
@ -1646,7 +1647,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
|
||||
} else {
|
||||
if ((i < if_count) && ifindices[i])
|
||||
route_entry_nexthop_ifindex_add(
|
||||
re, ifindices[i]);
|
||||
re, ifindices[i], re->vrf_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1760,6 +1761,9 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
|
||||
} else
|
||||
src_pp = NULL;
|
||||
|
||||
/* VRF ID */
|
||||
re->vrf_id = zvrf_id(zvrf);
|
||||
|
||||
/* We need to give nh-addr, nh-ifindex with the same next-hop object
|
||||
* to the re to ensure that IPv6 multipathing works; need to coalesce
|
||||
* these. Clients should send the same number of paired set of
|
||||
@ -1797,7 +1801,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
|
||||
STREAM_GET(&nhop_addr, s, 16);
|
||||
STREAM_GETL(s, ifindex);
|
||||
route_entry_nexthop_ipv6_ifindex_add(
|
||||
re, &nhop_addr, ifindex);
|
||||
re, &nhop_addr, ifindex, re->vrf_id);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
if (if_count < multipath_num) {
|
||||
@ -1824,17 +1828,18 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
|
||||
nexthop =
|
||||
route_entry_nexthop_ipv6_ifindex_add(
|
||||
re, &nexthops[i],
|
||||
ifindices[i]);
|
||||
ifindices[i],
|
||||
re->vrf_id);
|
||||
else
|
||||
nexthop = route_entry_nexthop_ipv6_add(
|
||||
re, &nexthops[i]);
|
||||
re, &nexthops[i], re->vrf_id);
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
||||
nexthop_add_labels(nexthop, label_type,
|
||||
1, &labels[i]);
|
||||
} else {
|
||||
if ((i < if_count) && ifindices[i])
|
||||
route_entry_nexthop_ifindex_add(
|
||||
re, ifindices[i]);
|
||||
re, ifindices[i], re->vrf_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1858,10 +1863,6 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
|
||||
else
|
||||
re->mtu = 0;
|
||||
|
||||
/* VRF ID */
|
||||
re->vrf_id = zvrf_id(zvrf);
|
||||
re->nh_vrf_id = zvrf_id(zvrf);
|
||||
|
||||
re->table = zvrf->table_id;
|
||||
|
||||
ret = rib_add_multipath(AFI_IP6, safi, &p, src_pp, re);
|
||||
@ -2485,6 +2486,51 @@ stream_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void zread_vrf_label(struct zserv *client,
|
||||
struct zebra_vrf *zvrf)
|
||||
{
|
||||
struct interface *ifp;
|
||||
mpls_label_t nlabel;
|
||||
struct stream *s;
|
||||
struct zebra_vrf *def_zvrf;
|
||||
enum lsp_types_t ltype;
|
||||
|
||||
s = client->ibuf;
|
||||
STREAM_GETL(s, nlabel);
|
||||
if (nlabel == zvrf->label) {
|
||||
/*
|
||||
* Nothing to do here move along
|
||||
*/
|
||||
return;
|
||||
}
|
||||
STREAM_GETC(s, ltype);
|
||||
|
||||
if (zvrf->vrf->vrf_id != VRF_DEFAULT)
|
||||
ifp = if_lookup_by_name(zvrf->vrf->name, zvrf->vrf->vrf_id);
|
||||
else
|
||||
ifp = if_lookup_by_name("lo", VRF_DEFAULT);
|
||||
|
||||
if (!ifp) {
|
||||
zlog_debug("Unable to find specified Interface for %s",
|
||||
zvrf->vrf->name);
|
||||
return;
|
||||
}
|
||||
|
||||
def_zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
|
||||
|
||||
if (zvrf->label != MPLS_LABEL_NONE)
|
||||
mpls_lsp_uninstall(def_zvrf, ltype, zvrf->label,
|
||||
NEXTHOP_TYPE_IFINDEX, NULL, ifp->ifindex);
|
||||
|
||||
if (nlabel != MPLS_LABEL_NONE)
|
||||
mpls_lsp_install(def_zvrf, ltype, nlabel, MPLS_LABEL_IMPLICIT_NULL,
|
||||
NEXTHOP_TYPE_IFINDEX, NULL, ifp->ifindex);
|
||||
|
||||
zvrf->label = nlabel;
|
||||
stream_failure:
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void zserv_handle_commands(struct zserv *client,
|
||||
uint16_t command,
|
||||
uint16_t length,
|
||||
@ -2569,6 +2615,9 @@ static inline void zserv_handle_commands(struct zserv *client,
|
||||
case ZEBRA_VRF_UNREGISTER:
|
||||
zread_vrf_unregister(client, length, zvrf);
|
||||
break;
|
||||
case ZEBRA_VRF_LABEL:
|
||||
zread_vrf_label(client, zvrf);
|
||||
break;
|
||||
case ZEBRA_BFD_CLIENT_REGISTER:
|
||||
zebra_ptm_bfd_client_register(client, length);
|
||||
break;
|
||||
@ -2603,6 +2652,9 @@ static inline void zserv_handle_commands(struct zserv *client,
|
||||
case ZEBRA_ADVERTISE_DEFAULT_GW:
|
||||
zebra_vxlan_advertise_gw_macip(client, length, zvrf);
|
||||
break;
|
||||
case ZEBRA_ADVERTISE_SUBNET:
|
||||
zebra_vxlan_advertise_subnet(client, length, zvrf);
|
||||
break;
|
||||
case ZEBRA_ADVERTISE_ALL_VNI:
|
||||
zebra_vxlan_advertise_all_vni(client, length, zvrf);
|
||||
break;
|
||||
|
||||
@ -114,6 +114,8 @@ struct zserv {
|
||||
u_int32_t l3vnidel_cnt;
|
||||
u_int32_t macipadd_cnt;
|
||||
u_int32_t macipdel_cnt;
|
||||
u_int32_t prefixadd_cnt;
|
||||
u_int32_t prefixdel_cnt;
|
||||
|
||||
time_t connect_time;
|
||||
time_t last_read_time;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user