diff options
68 files changed, 1345 insertions, 610 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c index 814366f320..df263a91c9 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -540,6 +540,7 @@ static void bfd_session_free(struct bfd_session *bs) struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc) { struct bfd_session *bfd, *l_bfd; + struct interface *ifp = NULL; int psock; /* check to see if this needs a new session */ @@ -553,6 +554,24 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc) } /* + * No session found, we have to allocate a new one. + * + * First a few critical checks: + * + * * Check that the specified interface exists. + * * Attempt to create the UDP socket (might fail if we exceed + * our limits). + */ + if (bpc->bpc_has_localif) { + ifp = if_lookup_by_name(bpc->bpc_localif, VRF_DEFAULT); + if (ifp == NULL) { + log_error( + "session-new: specified interface doesn't exists."); + return NULL; + } + } + + /* * Get socket for transmitting control packets. Note that if we * could use the destination port (3784) for the source * port we wouldn't need a socket per session. @@ -574,19 +593,21 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc) return NULL; } - if (bpc->bpc_has_localif && !bpc->bpc_mhop) { - bfd->ifindex = ptm_bfd_fetch_ifindex(bpc->bpc_localif); - ptm_bfd_fetch_local_mac(bpc->bpc_localif, bfd->local_mac); - } + if (bpc->bpc_has_localif && !bpc->bpc_mhop) + bfd->ifp = ifp; if (bpc->bpc_ipv4 == false) { BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6); /* Set the IPv6 scope id for link-local addresses. */ if (IN6_IS_ADDR_LINKLOCAL(&bpc->bpc_local.sa_sin6.sin6_addr)) - bpc->bpc_local.sa_sin6.sin6_scope_id = bfd->ifindex; + bpc->bpc_local.sa_sin6.sin6_scope_id = + bfd->ifp != NULL ? bfd->ifp->ifindex + : IFINDEX_INTERNAL; if (IN6_IS_ADDR_LINKLOCAL(&bpc->bpc_peer.sa_sin6.sin6_addr)) - bpc->bpc_peer.sa_sin6.sin6_scope_id = bfd->ifindex; + bpc->bpc_peer.sa_sin6.sin6_scope_id = + bfd->ifp != NULL ? bfd->ifp->ifindex + : IFINDEX_INTERNAL; } /* Initialize the session */ @@ -770,10 +791,10 @@ void integer2timestr(uint64_t time, char *buf, size_t buflen) int rv; #define MINUTES (60) -#define HOURS (24 * MINUTES) -#define DAYS (30 * HOURS) -#define MONTHS (12 * DAYS) -#define YEARS (MONTHS) +#define HOURS (60 * MINUTES) +#define DAYS (24 * HOURS) +#define MONTHS (30 * DAYS) +#define YEARS (12 * MONTHS) if (time >= YEARS) { year = time / YEARS; time -= year * YEARS; diff --git a/bfdd/bfd.h b/bfdd/bfd.h index 3a58a8d53c..a3e5ad1447 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -31,6 +31,7 @@ #include "lib/libfrr.h" #include "lib/qobj.h" #include "lib/queue.h" +#include "lib/vrf.h" #include "bfdctl.h" @@ -237,7 +238,7 @@ struct bfd_session { struct sockaddr_any local_address; struct sockaddr_any local_ip; - int ifindex; + struct interface *ifp; uint8_t local_mac[ETHERNET_ADDRESS_LENGTH]; uint8_t peer_mac[ETHERNET_ADDRESS_LENGTH]; @@ -512,7 +513,6 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc); int ptm_bfd_ses_del(struct bfd_peer_cfg *bpc); void ptm_bfd_ses_dn(struct bfd_session *bfd, uint8_t diag); void ptm_bfd_ses_up(struct bfd_session *bfd); -void fetch_portname_from_ifindex(int ifindex, char *ifname, size_t ifnamelen); void ptm_bfd_echo_stop(struct bfd_session *bfd, int polling); void ptm_bfd_echo_start(struct bfd_session *bfd); void ptm_bfd_xmt_TO(struct bfd_session *bfd, int fbit); @@ -584,20 +584,4 @@ void bfdd_zclient_stop(void); int ptm_bfd_notify(struct bfd_session *bs); - -/* - * OS compatibility functions. - */ -#if defined(BFD_LINUX) || defined(BFD_BSD) -int ptm_bfd_fetch_ifindex(const char *ifname); -void ptm_bfd_fetch_local_mac(const char *ifname, uint8_t *mac); -void fetch_portname_from_ifindex(int ifindex, char *ifname, size_t ifnamelen); -#endif /* BFD_LINUX || BFD_BSD */ - -#ifdef BFD_BSD -ssize_t bsd_echo_sock_read(int sd, uint8_t *buf, ssize_t *buflen, - struct sockaddr_storage *ss, socklen_t *sslen, - uint8_t *ttl, uint32_t *id); -#endif /* BFD_BSD */ - #endif /* _BFD_H_ */ diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c index 606f739b46..9cfd7e866f 100644 --- a/bfdd/bfd_packet.c +++ b/bfdd/bfd_packet.c @@ -241,6 +241,7 @@ ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl, size_t vrfnamelen, struct sockaddr_any *local, struct sockaddr_any *peer) { + struct interface *ifp; struct cmsghdr *cm; int ifindex; ssize_t mlen; @@ -307,8 +308,14 @@ ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl, #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN local->sa_sin.sin_len = sizeof(local->sa_sin); #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ - fetch_portname_from_ifindex(pi->ipi_ifindex, port, - portlen); + + ifp = if_lookup_by_index(pi->ipi_ifindex, VRF_DEFAULT); + if (ifp == NULL) + break; + + if (strlcpy(port, ifp->name, portlen) >= portlen) + log_debug( + "ipv4-recv: interface name truncated"); break; } #endif /* BFD_LINUX */ @@ -345,8 +352,15 @@ ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl, /* OS agnostic way of getting interface name. */ if (port[0] == 0) { ifindex = getsockopt_ifindex(AF_INET, &msghdr); - if (ifindex > 0) - fetch_portname_from_ifindex(ifindex, port, portlen); + if (ifindex <= 0) + return mlen; + + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + if (ifp == NULL) + return mlen; + + if (strlcpy(port, ifp->name, portlen) >= portlen) + log_debug("ipv4-recv: interface name truncated"); } return mlen; @@ -357,6 +371,7 @@ ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl, size_t vrfnamelen, struct sockaddr_any *local, struct sockaddr_any *peer) { + struct interface *ifp; struct cmsghdr *cm; struct in6_pktinfo *pi6 = NULL; int ifindex = 0; @@ -413,9 +428,16 @@ ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl, #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN local->sa_sin6.sin6_len = sizeof(local->sa_sin6); #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ - fetch_portname_from_ifindex(pi6->ipi6_ifindex, - port, portlen); + ifindex = pi6->ipi6_ifindex; + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + if (ifp == NULL) + break; + + if (strlcpy(port, ifp->name, portlen) + >= portlen) + log_debug( + "ipv6-recv: interface name truncated"); } } } @@ -610,8 +632,8 @@ int bfd_recv_cb(struct thread *t) * If no interface was detected, save the interface where the * packet came in. */ - if (bfd->ifindex == 0) - bfd->ifindex = ptm_bfd_fetch_ifindex(port); + if (bfd->ifp == NULL) + bfd->ifp = if_lookup_by_name(port, VRF_DEFAULT); /* Log remote discriminator changes. */ if ((bfd->discrs.remote_discr != 0) @@ -1046,7 +1068,8 @@ int bp_peer_socket(struct bfd_peer_cfg *bpc) int bp_peer_socketv6(struct bfd_peer_cfg *bpc) { - int sd, pcount, ifindex; + struct interface *ifp; + int sd, pcount; struct sockaddr_in6 sin6; static int srcPort = BFD_SRCPORTINIT; @@ -1076,9 +1099,11 @@ int bp_peer_socketv6(struct bfd_peer_cfg *bpc) sin6.sin6_len = sizeof(sin6); #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ sin6 = bpc->bpc_local.sa_sin6; - ifindex = ptm_bfd_fetch_ifindex(bpc->bpc_localif); - if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr)) - sin6.sin6_scope_id = ifindex; + if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr)) { + ifp = if_lookup_by_name(bpc->bpc_localif, VRF_DEFAULT); + sin6.sin6_scope_id = + (ifp != NULL) ? ifp->ifindex : IFINDEX_INTERNAL; + } if (bpc->bpc_has_localif) { if (bp_bind_dev(sd, bpc->bpc_localif) != 0) { diff --git a/bfdd/bsd.c b/bfdd/bsd.c index e0fb340e30..923fbd909e 100644 --- a/bfdd/bsd.c +++ b/bfdd/bsd.c @@ -35,70 +35,6 @@ /* * Definitions. */ -int ptm_bfd_fetch_ifindex(const char *ifname) -{ - return if_nametoindex(ifname); -} - -void ptm_bfd_fetch_local_mac(const char *ifname, uint8_t *mac) -{ - struct ifaddrs *ifap, *ifa; - struct if_data *ifi; - struct sockaddr_dl *sdl; - size_t maclen; - - /* Always clean the target, zeroed macs mean failure. */ - memset(mac, 0, ETHERNET_ADDRESS_LENGTH); - - if (getifaddrs(&ifap) != 0) - return; - - for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { - /* Find interface with that name. */ - if (strcmp(ifa->ifa_name, ifname) != 0) - continue; - /* Skip non link addresses. We want the MAC address. */ - if (ifa->ifa_addr->sa_family != AF_LINK) - continue; - - sdl = (struct sockaddr_dl *)ifa->ifa_addr; - ifi = (struct if_data *)ifa->ifa_data; - /* Skip non ethernet related data. */ - if (ifi->ifi_type != IFT_ETHER) - continue; - - if (sdl->sdl_alen != ETHERNET_ADDRESS_LENGTH) - log_warning("%s:%d mac address length %d (expected %d)", - __func__, __LINE__, sdl->sdl_alen, - ETHERNET_ADDRESS_LENGTH); - - maclen = (sdl->sdl_alen > ETHERNET_ADDRESS_LENGTH) - ? ETHERNET_ADDRESS_LENGTH - : sdl->sdl_alen; - memcpy(mac, LLADDR(sdl), maclen); - break; - } - - freeifaddrs(ifap); -} - - -/* Was _fetch_portname_from_ifindex() */ -void fetch_portname_from_ifindex(int ifindex, char *ifname, size_t ifnamelen) -{ - char ifname_tmp[IF_NAMESIZE]; - - /* Set ifname to empty to signalize failures. */ - memset(ifname, 0, ifnamelen); - - if (if_indextoname(ifindex, ifname_tmp) == NULL) - return; - - if (strlcpy(ifname, ifname_tmp, ifnamelen) > ifnamelen) - log_warning("%s:%d interface name truncated", __func__, - __LINE__); -} - int bp_bind_dev(int sd, const char *dev) { /* diff --git a/bfdd/linux.c b/bfdd/linux.c index e260851ddb..3a76b459d7 100644 --- a/bfdd/linux.c +++ b/bfdd/linux.c @@ -29,64 +29,6 @@ /* * Definitions. */ -int ptm_bfd_fetch_ifindex(const char *ifname) -{ - struct ifreq ifr; - - if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) - > sizeof(ifr.ifr_name)) - log_error("interface-to-index: name truncated ('%s' -> '%s')", - ifr.ifr_name, ifname); - - if (ioctl(bglobal.bg_shop, SIOCGIFINDEX, &ifr) == -1) { - log_error("interface-to-index: %s translation failed: %s", - ifname, strerror(errno)); - return -1; - } - - return ifr.ifr_ifindex; -} - -void ptm_bfd_fetch_local_mac(const char *ifname, uint8_t *mac) -{ - struct ifreq ifr; - - if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) - > sizeof(ifr.ifr_name)) - log_error("interface-mac: name truncated ('%s' -> '%s')", - ifr.ifr_name, ifname); - - if (ioctl(bglobal.bg_shop, SIOCGIFHWADDR, &ifr) == -1) { - log_error("interface-mac: %s MAC retrieval failed: %s", ifname, - strerror(errno)); - return; - } - - memcpy(mac, ifr.ifr_hwaddr.sa_data, ETHERNET_ADDRESS_LENGTH); -} - - -/* Was _fetch_portname_from_ifindex() */ -void fetch_portname_from_ifindex(int ifindex, char *ifname, size_t ifnamelen) -{ - struct ifreq ifr; - - ifname[0] = 0; - - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_ifindex = ifindex; - - if (ioctl(bglobal.bg_shop, SIOCGIFNAME, &ifr) == -1) { - log_error("index-to-interface: index %d failure: %s", ifindex, - strerror(errno)); - return; - } - - if (strlcpy(ifname, ifr.ifr_name, ifnamelen) >= ifnamelen) - log_debug("index-to-interface: name truncated '%s' -> '%s'", - ifr.ifr_name, ifname); -} - int bp_bind_dev(int sd __attribute__((__unused__)), const char *dev __attribute__((__unused__))) { diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index f9c7c16fb1..a57167376a 100644 --- a/bfdd/ptm_adapter.c +++ b/bfdd/ptm_adapter.c @@ -189,7 +189,10 @@ int ptm_bfd_notify(struct bfd_session *bs) stream_putl(msg, ZEBRA_INTERFACE_BFD_DEST_UPDATE); /* NOTE: Interface is a shortcut to avoid comparing source address. */ - stream_putl(msg, bs->ifindex); + if (bs->ifp != NULL) + stream_putl(msg, bs->ifp->ifindex); + else + stream_putl(msg, IFINDEX_INTERNAL); /* BFD destination prefix information. */ if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) @@ -287,6 +290,7 @@ stream_failure: static int _ptm_msg_read(struct stream *msg, int command, struct bfd_peer_cfg *bpc, struct ptm_client **pc) { + struct interface *ifp; uint32_t pid; uint8_t ttl __attribute__((unused)); size_t ifnamelen; @@ -393,9 +397,19 @@ static int _ptm_msg_read(struct stream *msg, int command, */ if (bpc->bpc_ipv4 == false && IN6_IS_ADDR_LINKLOCAL( - &bpc->bpc_peer.sa_sin6.sin6_addr)) + &bpc->bpc_peer.sa_sin6.sin6_addr)) { + ifp = if_lookup_by_name_all_vrf( + bpc->bpc_localif); + if (ifp == NULL) { + log_error( + "ptm-read: interface %s doesn't exists", + bpc->bpc_localif); + return -1; + } + bpc->bpc_peer.sa_sin6.sin6_scope_id = - ptm_bfd_fetch_ifindex(bpc->bpc_localif); + ifp->ifindex; + } } } @@ -576,9 +590,34 @@ static void bfdd_zebra_connected(struct zclient *zc) stream_putl(msg, ZEBRA_BFD_DEST_REPLAY); stream_putw_at(msg, 0, stream_get_endp(msg)); + /* Ask for interfaces information. */ + zclient_create_header(msg, ZEBRA_INTERFACE_ADD, VRF_DEFAULT); + + /* Send requests. */ zclient_send_message(zclient); } +static int bfdd_interface_update(int cmd, struct zclient *zc, uint16_t len, + vrf_id_t vrfid) +{ + /* + * `zebra_interface_add_read` will handle the interface creation + * on `lib/if.c`. We'll use that data structure instead of + * rolling our own. + */ + if (cmd == ZEBRA_INTERFACE_ADD) { + zebra_interface_add_read(zc->ibuf, vrfid); + return 0; + } + + /* Update interface information. */ + zebra_interface_state_read(zc->ibuf, vrfid); + + /* TODO: stop all sessions using this interface. */ + + return 0; +} + void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv) { zclient = zclient_new(master, &zclient_options_default); @@ -594,6 +633,10 @@ void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv) /* Send replay request on zebra connect. */ zclient->zebra_connected = bfdd_zebra_connected; + + /* Learn interfaces from zebra instead of the OS. */ + zclient->interface_add = bfdd_interface_update; + zclient->interface_delete = bfdd_interface_update; } void bfdd_zclient_stop(void) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index b990e99bda..03f31eddfc 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -392,7 +392,7 @@ static bool overlay_index_same(const struct attr *a1, const struct attr *a2) if (!a1 && !a2) return true; return !memcmp(&(a1->evpn_overlay), &(a2->evpn_overlay), - sizeof(struct overlay_index)); + sizeof(struct bgp_route_evpn)); } /* Unknown transit attribute. */ diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 47a4182fee..6d5c647b21 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -92,12 +92,6 @@ struct bgp_tea_options { #endif -/* Overlay Index Info */ -struct overlay_index { - struct eth_segment_id eth_s_id; - union gw_addr gw_ip; -}; - enum pta_type { PMSI_TNLTYPE_NO_INFO = 0, PMSI_TNLTYPE_RSVP_TE_P2MP, @@ -204,7 +198,7 @@ struct attr { struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */ #endif /* EVPN */ - struct overlay_index evpn_overlay; + struct bgp_route_evpn evpn_overlay; /* EVPN MAC Mobility sequence number, if any. */ uint32_t mm_seqnum; diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c index 88e520fdc5..3e9d05ad97 100644 --- a/bgpd/bgp_attr_evpn.c +++ b/bgpd/bgp_attr_evpn.c @@ -267,13 +267,13 @@ extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v4, &src->u.prefix4, sizeof(struct in_addr)); - dst->prefixlen = (uint8_t)PREFIX_LEN_ROUTE_TYPE_5_IPV4; + dst->prefixlen = (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV4; } else { SET_IPADDR_V6(&p_evpn_p->prefix_addr.ip); memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v6, &src->u.prefix6, sizeof(struct in6_addr)); - dst->prefixlen = (uint8_t)PREFIX_LEN_ROUTE_TYPE_5_IPV6; + dst->prefixlen = (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV6; } } else return -1; diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index c4a20ca233..84a00488c1 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -26,6 +26,7 @@ #include "queue.h" #include "filter.h" #include "stream.h" +#include "jhash.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_community.h" @@ -35,6 +36,31 @@ #include "bgpd/bgp_regex.h" #include "bgpd/bgp_clist.h" +static uint32_t bgp_clist_hash_key_community_list(void *data) +{ + struct community_list *cl = data; + + if (cl->name_hash) + return cl->name_hash; + + cl->name_hash = bgp_clist_hash_key(cl->name); + return cl->name_hash; +} + +static bool bgp_clist_hash_cmp_community_list(const void *a1, const void *a2) +{ + const struct community_list *cl1 = a1; + const struct community_list *cl2 = a2; + + if (cl1->name_hash != cl2->name_hash) + return false; + + if (strcmp(cl1->name, cl2->name) == 0) + return true; + + return false; +} + /* Lookup master structure for community-list or extcommunity-list. */ struct community_list_master * @@ -125,6 +151,10 @@ community_list_insert(struct community_list_handler *ch, const char *name, /* Allocate new community_list and copy given name. */ new = community_list_new(); new->name = XSTRDUP(MTYPE_COMMUNITY_LIST_NAME, name); + new->name_hash = bgp_clist_hash_key_community_list(new); + + /* Save for later */ + hash_get(cm->hash, new, hash_alloc_intern); /* If name is made by all digit character. We treat it as number. */ @@ -194,9 +224,11 @@ community_list_insert(struct community_list_handler *ch, const char *name, } struct community_list *community_list_lookup(struct community_list_handler *ch, - const char *name, int master) + const char *name, + uint32_t name_hash, + int master) { - struct community_list *list; + struct community_list lookup; struct community_list_master *cm; if (!name) @@ -206,14 +238,9 @@ struct community_list *community_list_lookup(struct community_list_handler *ch, if (!cm) return NULL; - for (list = cm->num.head; list; list = list->next) - if (strcmp(list->name, name) == 0) - return list; - for (list = cm->str.head; list; list = list->next) - if (strcmp(list->name, name) == 0) - return list; - - return NULL; + lookup.name = (char *)name; + lookup.name_hash = name_hash; + return hash_get(cm->hash, &lookup, NULL); } static struct community_list * @@ -222,13 +249,14 @@ community_list_get(struct community_list_handler *ch, const char *name, { struct community_list *list; - list = community_list_lookup(ch, name, master); + list = community_list_lookup(ch, name, 0, master); if (!list) list = community_list_insert(ch, name, master); return list; } -static void community_list_delete(struct community_list *list) +static void community_list_delete(struct community_list_master *cm, + struct community_list *list) { struct community_list_list *clist; struct community_entry *entry, *next; @@ -250,6 +278,7 @@ static void community_list_delete(struct community_list *list) else clist->head = list->next; + hash_release(cm->hash, list); community_list_free(list); } @@ -273,7 +302,8 @@ static void community_list_entry_add(struct community_list *list, } /* Delete community-list entry from the list. */ -static void community_list_entry_delete(struct community_list *list, +static void community_list_entry_delete(struct community_list_master *cm, + struct community_list *list, struct community_entry *entry) { if (entry->next) @@ -289,7 +319,7 @@ static void community_list_entry_delete(struct community_list *list, community_entry_free(entry); if (community_list_empty_p(list)) - community_list_delete(list); + community_list_delete(cm, list); } /* Lookup community-list entry from the list. */ @@ -882,18 +912,20 @@ int community_list_set(struct community_list_handler *ch, const char *name, int community_list_unset(struct community_list_handler *ch, const char *name, const char *str, int direct, int style) { + struct community_list_master *cm = NULL; struct community_entry *entry = NULL; struct community_list *list; struct community *com = NULL; /* Lookup community list. */ - list = community_list_lookup(ch, name, COMMUNITY_LIST_MASTER); + list = community_list_lookup(ch, name, 0, COMMUNITY_LIST_MASTER); if (list == NULL) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + cm = community_list_master_lookup(ch, COMMUNITY_LIST_MASTER); /* Delete all of entry belongs to this community-list. */ if (!str) { - community_list_delete(list); + community_list_delete(cm, list); route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED); return 0; } @@ -910,7 +942,7 @@ int community_list_unset(struct community_list_handler *ch, const char *name, if (!entry) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - community_list_entry_delete(list, entry); + community_list_entry_delete(cm, list, entry); route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED); return 0; @@ -1031,19 +1063,21 @@ int lcommunity_list_set(struct community_list_handler *ch, const char *name, int lcommunity_list_unset(struct community_list_handler *ch, const char *name, const char *str, int direct, int style) { + struct community_list_master *cm = NULL; struct community_entry *entry = NULL; struct community_list *list; struct lcommunity *lcom = NULL; regex_t *regex = NULL; /* Lookup community list. */ - list = community_list_lookup(ch, name, LARGE_COMMUNITY_LIST_MASTER); + list = community_list_lookup(ch, name, 0, LARGE_COMMUNITY_LIST_MASTER); if (list == NULL) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + cm = community_list_master_lookup(ch, LARGE_COMMUNITY_LIST_MASTER); /* Delete all of entry belongs to this community-list. */ if (!str) { - community_list_delete(list); + community_list_delete(cm, list); return 0; } @@ -1068,7 +1102,7 @@ int lcommunity_list_unset(struct community_list_handler *ch, const char *name, if (!entry) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - community_list_entry_delete(list, entry); + community_list_entry_delete(cm, list, entry); return 0; } @@ -1147,18 +1181,20 @@ int extcommunity_list_set(struct community_list_handler *ch, const char *name, int extcommunity_list_unset(struct community_list_handler *ch, const char *name, const char *str, int direct, int style) { + struct community_list_master *cm = NULL; struct community_entry *entry = NULL; struct community_list *list; struct ecommunity *ecom = NULL; /* Lookup extcommunity list. */ - list = community_list_lookup(ch, name, EXTCOMMUNITY_LIST_MASTER); + list = community_list_lookup(ch, name, 0, EXTCOMMUNITY_LIST_MASTER); if (list == NULL) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + cm = community_list_master_lookup(ch, EXTCOMMUNITY_LIST_MASTER); /* Delete all of entry belongs to this extcommunity-list. */ if (!str) { - community_list_delete(list); + community_list_delete(cm, list); route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED); return 0; } @@ -1175,7 +1211,7 @@ int extcommunity_list_unset(struct community_list_handler *ch, const char *name, if (!entry) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - community_list_entry_delete(list, entry); + community_list_entry_delete(cm, list, entry); route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED); return 0; @@ -1187,6 +1223,22 @@ struct community_list_handler *community_list_init(void) struct community_list_handler *ch; ch = XCALLOC(MTYPE_COMMUNITY_LIST_HANDLER, sizeof(struct community_list_handler)); + + ch->community_list.hash = + hash_create_size(4, bgp_clist_hash_key_community_list, + bgp_clist_hash_cmp_community_list, + "Community List Number Quick Lookup"); + + ch->extcommunity_list.hash = + hash_create_size(4, bgp_clist_hash_key_community_list, + bgp_clist_hash_cmp_community_list, + "Extended Community List Quick Lookup"); + + ch->lcommunity_list.hash = + hash_create_size(4, bgp_clist_hash_key_community_list, + bgp_clist_hash_cmp_community_list, + "Large Community List Quick Lookup"); + return ch; } @@ -1198,21 +1250,24 @@ void community_list_terminate(struct community_list_handler *ch) cm = &ch->community_list; while ((list = cm->num.head) != NULL) - community_list_delete(list); + community_list_delete(cm, list); while ((list = cm->str.head) != NULL) - community_list_delete(list); + community_list_delete(cm, list); + hash_free(cm->hash); cm = &ch->lcommunity_list; while ((list = cm->num.head) != NULL) - community_list_delete(list); + community_list_delete(cm, list); while ((list = cm->str.head) != NULL) - community_list_delete(list); + community_list_delete(cm, list); + hash_free(cm->hash); cm = &ch->extcommunity_list; while ((list = cm->num.head) != NULL) - community_list_delete(list); + community_list_delete(cm, list); while ((list = cm->str.head) != NULL) - community_list_delete(list); + community_list_delete(cm, list); + hash_free(cm->hash); XFREE(MTYPE_COMMUNITY_LIST_HANDLER, ch); } diff --git a/bgpd/bgp_clist.h b/bgpd/bgp_clist.h index 9efb34d7b9..9cf8a14a6a 100644 --- a/bgpd/bgp_clist.h +++ b/bgpd/bgp_clist.h @@ -21,6 +21,8 @@ #ifndef _QUAGGA_BGP_CLIST_H #define _QUAGGA_BGP_CLIST_H +#include "jhash.h" + /* Master Community-list. */ #define COMMUNITY_LIST_MASTER 0 #define EXTCOMMUNITY_LIST_MASTER 1 @@ -47,6 +49,9 @@ struct community_list { /* Name of the community-list. */ char *name; + /* Stored hash value of name, to further speed up hash operations */ + uint32_t name_hash; + /* String or number. */ int sort; @@ -100,6 +105,7 @@ struct community_list_list { struct community_list_master { struct community_list_list num; struct community_list_list str; + struct hash *hash; }; /* Community-list handler. community_list_init() returns this @@ -151,7 +157,8 @@ extern struct community_list_master * community_list_master_lookup(struct community_list_handler *, int); extern struct community_list * -community_list_lookup(struct community_list_handler *, const char *, int); +community_list_lookup(struct community_list_handler *c, const char *name, + uint32_t name_hash, int master); extern int community_list_match(struct community *, struct community_list *); extern int ecommunity_list_match(struct ecommunity *, struct community_list *); @@ -163,4 +170,10 @@ extern struct community *community_list_match_delete(struct community *, extern struct lcommunity * lcommunity_list_match_delete(struct lcommunity *lcom, struct community_list *list); + +static inline uint32_t bgp_clist_hash_key(char *name) +{ + return jhash(name, sizeof(name), 0xdeadbeaf); +} + #endif /* _QUAGGA_BGP_CLIST_H */ diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c index c6386dcdb5..cd5bec6267 100644 --- a/bgpd/bgp_flowspec_util.c +++ b/bgpd/bgp_flowspec_util.c @@ -23,6 +23,7 @@ #include "prefix.h" #include "lib_errors.h" +#include "bgp_route.h" #include "bgp_table.h" #include "bgp_flowspec_util.h" #include "bgp_flowspec_private.h" @@ -581,3 +582,27 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, } return error; } + +/* return 1 if FS entry invalid or no NH IP */ +int bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi, + struct prefix *p) +{ + struct bgp_pbr_entry_main api; + int i; + struct bgp_node *rn = pi->net; + struct bgp_pbr_entry_action *api_action; + + memset(&api, 0, sizeof(struct bgp_pbr_entry_main)); + if (bgp_pbr_build_and_validate_entry(&rn->p, pi, &api) < 0) + return 1; + for (i = 0; i < api.action_num; i++) { + api_action = &api.actions[i]; + if (api_action->action != ACTION_REDIRECT_IP) + continue; + p->family = AF_INET; + p->prefixlen = IPV4_MAX_BITLEN; + p->u.prefix4 = api_action->u.zr.redirect_ip_v4; + return 0; + } + return 1; +} diff --git a/bgpd/bgp_flowspec_util.h b/bgpd/bgp_flowspec_util.h index 9bf05847d3..2ce911da4e 100644 --- a/bgpd/bgp_flowspec_util.h +++ b/bgpd/bgp_flowspec_util.h @@ -54,4 +54,8 @@ extern bool bgp_flowspec_contains_prefix(struct prefix *pfs, struct prefix *input, int prefix_check); +extern int bgp_flowspec_get_first_nh(struct bgp *bgp, + struct bgp_path_info *pi, + struct prefix *nh); + #endif /* _FRR_BGP_FLOWSPEC_UTIL_H */ diff --git a/bgpd/bgp_keepalives.c b/bgpd/bgp_keepalives.c index 50aad70ddc..87e3ff2495 100644 --- a/bgpd/bgp_keepalives.c +++ b/bgpd/bgp_keepalives.c @@ -181,7 +181,11 @@ void *bgp_keepalives_start(void *arg) pthread_cond_init(peerhash_cond, &attrs); pthread_condattr_destroy(&attrs); - frr_pthread_set_name(fpt, NULL, "bgpd_ka"); + /* + * We are not using normal FRR pthread mechanics and are + * not using fpt_run + */ + frr_pthread_set_name(fpt); /* initialize peer hashtable */ peerhash = hash_create_size(2048, peer_hash_key, peer_hash_cmp, NULL); diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c new file mode 100644 index 0000000000..24f93e4373 --- /dev/null +++ b/bgpd/bgp_mac.c @@ -0,0 +1,354 @@ +/* + * BGPd - Mac hash code + * Copyright (C) 2018 Cumulus Networks, Inc. + * Donald Sharp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <zebra.h> + +#include <jhash.h> +#include <hash.h> +#include <prefix.h> +#include <memory.h> + +#include "bgpd/bgpd.h" +#include "bgpd/bgp_mac.h" +#include "bgpd/bgp_memory.h" +#include "bgpd/bgp_route.h" +#include "bgpd/bgp_packet.h" +#include "bgpd/bgp_debug.h" +#include "bgpd/bgp_evpn_private.h" + +DEFINE_MTYPE_STATIC(BGPD, BSM, "Mac Hash Entry"); +DEFINE_MTYPE_STATIC(BGPD, BSM_STRING, "Mac Hash Entry Interface String"); + +struct bgp_self_mac { + struct ethaddr macaddr; + struct list *ifp_list; +}; + +static unsigned int bgp_mac_hash_key_make(void *data) +{ + struct bgp_self_mac *bsm = data; + + return jhash(&bsm->macaddr, ETH_ALEN, 0xa5a5dead); +} + +static bool bgp_mac_hash_cmp(const void *d1, const void *d2) +{ + const struct bgp_self_mac *bsm1 = d1; + const struct bgp_self_mac *bsm2 = d2; + + if (memcmp(&bsm1->macaddr, &bsm2->macaddr, ETH_ALEN) == 0) + return true; + + return false; +} + +void bgp_mac_init(void) +{ + bm->self_mac_hash = hash_create(bgp_mac_hash_key_make, bgp_mac_hash_cmp, + "BGP MAC Hash"); +} + +static void bgp_mac_hash_free(void *data) +{ + struct bgp_self_mac *bsm = data; + + if (bsm->ifp_list) + list_delete(&bsm->ifp_list); + + XFREE(MTYPE_BSM, bsm); +} + +void bgp_mac_finish(void) +{ + hash_clean(bm->self_mac_hash, bgp_mac_hash_free); + hash_free(bm->self_mac_hash); +} + +static void bgp_mac_hash_interface_string_del(void *val) +{ + char *data = val; + + XFREE(MTYPE_BSM_STRING, data); +} + +static void *bgp_mac_hash_alloc(void *p) +{ + const struct bgp_self_mac *orig = p; + struct bgp_self_mac *bsm; + + bsm = XCALLOC(MTYPE_BSM, sizeof(struct bgp_self_mac)); + memcpy(&bsm->macaddr, &orig->macaddr, ETH_ALEN); + + bsm->ifp_list = list_new(); + bsm->ifp_list->del = bgp_mac_hash_interface_string_del; + + return bsm; +} + +struct bgp_mac_find_internal { + struct bgp_self_mac *bsm; + const char *ifname; +}; + +static void bgp_mac_find_ifp_internal(struct hash_backet *backet, void *arg) +{ + struct bgp_mac_find_internal *bmfi = arg; + struct bgp_self_mac *bsm = backet->data; + struct listnode *node; + char *name; + + for (ALL_LIST_ELEMENTS_RO(bsm->ifp_list, node, name)) { + if (strcmp(name, bmfi->ifname) == 0) { + bmfi->bsm = bsm; + return; + } + } +} + +static struct bgp_self_mac *bgp_mac_find_interface_name(const char *ifname) +{ + struct bgp_mac_find_internal bmfi; + + bmfi.bsm = NULL; + bmfi.ifname = ifname; + hash_iterate(bm->self_mac_hash, bgp_mac_find_ifp_internal, &bmfi); + + return bmfi.bsm; +} + +static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer, + struct bgp_table *table) +{ + struct bgp_node *prn, *rn; + struct bgp_path_info *pi; + uint32_t count = 0; + + for (prn = bgp_table_top(table); prn; prn = bgp_route_next(prn)) { + struct bgp_table *sub = prn->info; + + if (!sub) + continue; + + for (rn = bgp_table_top(sub); rn; rn = bgp_route_next(rn)) { + struct prefix_rd prd; + uint32_t num_labels = 0; + mpls_label_t *label_pnt = NULL; + struct bgp_route_evpn evpn; + + count++; + for (pi = rn->info; pi; pi = pi->next) { + if (pi->peer == peer) + break; + } + + if (!pi) + continue; + + if (pi->extra) + num_labels = pi->extra->num_labels; + if (num_labels) + label_pnt = &pi->extra->label[0]; + + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + memcpy(&prd.val, &prn->p.u.val, 8); + + memcpy(&evpn, &pi->attr->evpn_overlay, sizeof(evpn)); + int32_t ret = bgp_update(peer, &rn->p, + pi->addpath_rx_id, + pi->attr, AFI_L2VPN, SAFI_EVPN, + ZEBRA_ROUTE_BGP, + BGP_ROUTE_NORMAL, &prd, + label_pnt, num_labels, + 1, &evpn); + + if (ret < 0) + bgp_unlock_node(rn); + } + } +} + +static void bgp_mac_rescan_evpn_table(struct bgp *bgp) +{ + struct listnode *node; + struct peer *peer; + safi_t safi; + afi_t afi; + + afi = AFI_L2VPN; + safi = SAFI_EVPN; + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { + + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + continue; + + if (peer->status != Established) + continue; + + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SOFT_RECONFIG)) { + if (bgp_debug_update(peer, NULL, NULL, 1)) + zlog_debug("Processing EVPN MAC interface change on peer %s (inbound, soft-reconfig)", + peer->host); + + bgp_soft_reconfig_in(peer, afi, safi); + } else { + struct bgp_table *table = bgp->rib[afi][safi]; + + if (bgp_debug_update(peer, NULL, NULL, 1)) + zlog_debug("Processing EVPN MAC interface change on peer %s", + peer->host); + bgp_process_mac_rescan_table(bgp, peer, table); + } + } +} + +static void bgp_mac_rescan_all_evpn_tables(void) +{ + struct listnode *node; + struct bgp *bgp; + + for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) { + struct bgp_table *table = bgp->rib[AFI_L2VPN][SAFI_EVPN]; + + if (table) + bgp_mac_rescan_evpn_table(bgp); + } +} + +static void bgp_mac_remove_ifp_internal(struct bgp_self_mac *bsm, char *ifname) +{ + struct listnode *node = NULL; + char *name; + + for (ALL_LIST_ELEMENTS_RO(bsm->ifp_list, node, name)) { + if (strcmp(name, ifname) == 0) + break; + } + + if (node) { + list_delete_node(bsm->ifp_list, node); + XFREE(MTYPE_BSM_STRING, name); + } + + if (bsm->ifp_list->count == 0) { + hash_release(bm->self_mac_hash, bsm); + list_delete(&bsm->ifp_list); + XFREE(MTYPE_BSM, bsm); + + bgp_mac_rescan_all_evpn_tables(); + } +} + +void bgp_mac_add_mac_entry(struct interface *ifp) +{ + struct bgp_self_mac lookup; + struct bgp_self_mac *bsm; + struct bgp_self_mac *old_bsm; + char *ifname; + + memcpy(&lookup.macaddr, &ifp->hw_addr, ETH_ALEN); + bsm = hash_get(bm->self_mac_hash, &lookup, bgp_mac_hash_alloc); + + /* + * Does this happen to be a move + */ + old_bsm = bgp_mac_find_interface_name(ifp->name); + ifname = XSTRDUP(MTYPE_BSM_STRING, ifp->name); + + if (bsm->ifp_list->count == 0) { + + listnode_add(bsm->ifp_list, ifname); + if (old_bsm) + bgp_mac_remove_ifp_internal(old_bsm, ifname); + } else { + /* + * If old mac address is the same as the new, + * then there is nothing to do here + */ + if (old_bsm == bsm) + return; + + if (old_bsm) + bgp_mac_remove_ifp_internal(old_bsm, ifp->name); + + listnode_add(bsm->ifp_list, ifname); + } + + bgp_mac_rescan_all_evpn_tables(); +} + +void bgp_mac_del_mac_entry(struct interface *ifp) +{ + struct bgp_self_mac lookup; + struct bgp_self_mac *bsm; + + memcpy(&lookup.macaddr, &ifp->hw_addr, ETH_ALEN); + bsm = hash_lookup(bm->self_mac_hash, &lookup); + if (!bsm) + return; + + /* + * Write code to allow old mac address to no-longer + * win if we happen to have received it from a peer. + */ + bgp_mac_remove_ifp_internal(bsm, ifp->name); +} + +bool bgp_mac_entry_exists(struct prefix *p) +{ + struct prefix_evpn *pevpn = (struct prefix_evpn *)p; + struct bgp_self_mac lookup; + struct bgp_self_mac *bsm; + + if (pevpn->family != AF_EVPN) + return false; + + if (pevpn->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) + return false; + + memcpy(&lookup.macaddr, &p->u.prefix_evpn.macip_addr.mac, ETH_ALEN); + bsm = hash_lookup(bm->self_mac_hash, &lookup); + if (!bsm) + return false; + + return true; +} + +static void bgp_mac_show_mac_entry(struct hash_backet *backet, void *arg) +{ + struct vty *vty = arg; + struct bgp_self_mac *bsm = backet->data; + struct listnode *node; + char *name; + char buf_mac[ETHER_ADDR_STRLEN]; + + vty_out(vty, "Mac Address: %s ", + prefix_mac2str(&bsm->macaddr, buf_mac, sizeof(buf_mac))); + + for (ALL_LIST_ELEMENTS_RO(bsm->ifp_list, node, name)) + vty_out(vty, "%s ", name); + + vty_out(vty, "\n"); +} + +void bgp_mac_dump_table(struct vty *vty) +{ + hash_iterate(bm->self_mac_hash, bgp_mac_show_mac_entry, vty); +} diff --git a/bgpd/bgp_mac.h b/bgpd/bgp_mac.h new file mode 100644 index 0000000000..1dd987ef12 --- /dev/null +++ b/bgpd/bgp_mac.h @@ -0,0 +1,41 @@ +/* + * BGPd - Mac hash header + * Copyright (C) 2018 Cumulus Networks, Inc. + * Donald Sharp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef __BGP_MAC_H__ +#define __BGP_MAC_H__ + +void bgp_mac_init(void); +void bgp_mac_finish(void); + +/* + * Functions to add/delete the mac entry from the appropriate + * bgp hash's. Additionally to do some additional processing + * to allow the win/loss to be processed. + */ +void bgp_mac_add_mac_entry(struct interface *ifp); +void bgp_mac_del_mac_entry(struct interface *ifp); + +void bgp_mac_dump_table(struct vty *vty); + +/* + * Function to lookup the prefix and see if we have a matching mac + */ +bool bgp_mac_entry_exists(struct prefix *p); + +#endif diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index cf91faf964..d0ccdcedfb 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -289,6 +289,8 @@ void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi) bgp->vrf_id); } + if (label == BGP_PREVENT_VRF_2_VRF_LEAK) + label = MPLS_LABEL_NONE; zclient_send_vrf_label(zclient, bgp->vrf_id, afi, label, ZEBRA_LSP_BGP); bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent = label; } @@ -316,6 +318,9 @@ void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi) bgp->name_pretty, bgp->vrf_id); } + if (label == BGP_PREVENT_VRF_2_VRF_LEAK) + label = MPLS_LABEL_NONE; + zclient_send_vrf_label(zclient, bgp->vrf_id, afi, label, ZEBRA_LSP_BGP); bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent = label; } diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index b6ef5a55c5..2b4ad22b93 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -42,6 +42,7 @@ #include "bgpd/bgp_nht.h" #include "bgpd/bgp_fsm.h" #include "bgpd/bgp_zebra.h" +#include "bgpd/bgp_flowspec_util.h" extern struct zclient *zclient; @@ -533,7 +534,15 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p) && (pi->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0; - + struct bgp_node *net = pi->net; + struct prefix *p_orig = &net->p; + + if (p_orig->family == AF_FLOWSPEC) { + if (!pi->peer) + return -1; + return bgp_flowspec_get_first_nh(pi->peer->bgp, + pi, p); + } memset(p, 0, sizeof(struct prefix)); switch (afi) { case AFI_IP: diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index f0a0e615e6..f002154701 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -626,7 +626,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) } /* return -1 if build or validation failed */ -static int bgp_pbr_build_and_validate_entry(struct prefix *p, +int bgp_pbr_build_and_validate_entry(struct prefix *p, struct bgp_path_info *path, struct bgp_pbr_entry_main *api) { diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h index 84095f9ab9..45c3c9ea13 100644 --- a/bgpd/bgp_pbr.h +++ b/bgpd/bgp_pbr.h @@ -290,4 +290,7 @@ extern void bgp_pbr_reset(struct bgp *bgp, afi_t afi); extern struct bgp_pbr_interface *bgp_pbr_interface_lookup(const char *name, struct bgp_pbr_interface_head *head); +extern int bgp_pbr_build_and_validate_entry(struct prefix *p, + struct bgp_path_info *path, + struct bgp_pbr_entry_main *api); #endif /* __BGP_PBR_H__ */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 31cd3d1f05..6bce7261ae 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -66,6 +66,7 @@ #include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_label.h" #include "bgpd/bgp_addpath.h" +#include "bgpd/bgp_mac.h" #if ENABLE_BGP_VNC #include "bgpd/rfapi/rfapi_backend.h" @@ -3057,6 +3058,11 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, goto filtered; } + if (bgp_mac_entry_exists(p)) { + reason = "self mac;"; + goto filtered; + } + attr_new = bgp_attr_intern(&new_attr); /* If the update is implicit withdraw. */ @@ -3778,16 +3784,22 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi, bgp_node_get_bgp_path_info(rn); uint32_t num_labels = 0; mpls_label_t *label_pnt = NULL; + struct bgp_route_evpn evpn; if (pi && pi->extra) num_labels = pi->extra->num_labels; if (num_labels) label_pnt = &pi->extra->label[0]; + if (pi) + memcpy(&evpn, &pi->attr->evpn_overlay, + sizeof(evpn)); + else + memset(&evpn, 0, sizeof(evpn)); ret = bgp_update(peer, &rn->p, ain->addpath_rx_id, ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd, label_pnt, - num_labels, 1, NULL); + num_labels, 1, &evpn); if (ret < 0) { bgp_unlock_node(rn); @@ -9266,7 +9278,7 @@ static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp, { struct community_list *list; - list = community_list_lookup(bgp_clist, lcom, + list = community_list_lookup(bgp_clist, lcom, 0, LARGE_COMMUNITY_LIST_MASTER); if (list == NULL) { vty_out(vty, "%% %s is not a valid large-community-list name\n", @@ -9787,7 +9799,7 @@ static int bgp_show_community_list(struct vty *vty, struct bgp *bgp, { struct community_list *list; - list = community_list_lookup(bgp_clist, com, COMMUNITY_LIST_MASTER); + list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER); if (list == NULL) { vty_out(vty, "%% %s is not a valid community-list name\n", com); return CMD_WARNING; diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 30159f9023..d7ee2aa19f 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -1037,6 +1037,7 @@ struct route_map_rule_cmd route_match_aspath_cmd = { /* `match community COMMUNIY' */ struct rmap_community { char *name; + uint32_t name_hash; int exact; }; @@ -1048,13 +1049,14 @@ static route_map_result_t route_match_community(void *rule, { struct community_list *list; struct bgp_path_info *path; - struct rmap_community *rcom; + struct rmap_community *rcom = rule; if (type == RMAP_BGP) { path = object; rcom = rule; list = community_list_lookup(bgp_clist, rcom->name, + rcom->name_hash, COMMUNITY_LIST_MASTER); if (!list) return RMAP_NOMATCH; @@ -1090,6 +1092,8 @@ static void *route_match_community_compile(const char *arg) rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); rcom->exact = 0; } + + rcom->name_hash = bgp_clist_hash_key(rcom->name); return rcom; } @@ -1115,13 +1119,13 @@ static route_map_result_t route_match_lcommunity(void *rule, { struct community_list *list; struct bgp_path_info *path; - struct rmap_community *rcom; + struct rmap_community *rcom = rule; if (type == RMAP_BGP) { path = object; - rcom = rule; list = community_list_lookup(bgp_clist, rcom->name, + rcom->name_hash, LARGE_COMMUNITY_LIST_MASTER); if (!list) return RMAP_NOMATCH; @@ -1150,6 +1154,8 @@ static void *route_match_lcommunity_compile(const char *arg) rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); rcom->exact = 0; } + + rcom->name_hash = bgp_clist_hash_key(rcom->name); return rcom; } @@ -1176,11 +1182,13 @@ static route_map_result_t route_match_ecommunity(void *rule, { struct community_list *list; struct bgp_path_info *path; + struct rmap_community *rcom = rule; if (type == RMAP_BGP) { path = object; - list = community_list_lookup(bgp_clist, (char *)rule, + list = community_list_lookup(bgp_clist, rcom->name, + rcom->name_hash, EXTCOMMUNITY_LIST_MASTER); if (!list) return RMAP_NOMATCH; @@ -1194,13 +1202,22 @@ static route_map_result_t route_match_ecommunity(void *rule, /* Compile function for extcommunity match. */ static void *route_match_ecommunity_compile(const char *arg) { - return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); + struct rmap_community *rcom; + + rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community)); + rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); + rcom->name_hash = bgp_clist_hash_key(rcom->name); + + return rcom; } /* Compile function for extcommunity match. */ static void route_match_ecommunity_free(void *rule) { - XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); + struct rmap_community *rcom = rule; + + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom); } /* Route map commands for community matching. */ @@ -1932,13 +1949,15 @@ static route_map_result_t route_set_lcommunity_delete(void *rule, struct lcommunity *new; struct lcommunity *old; struct bgp_path_info *path; + struct rmap_community *rcom = rule; if (type == RMAP_BGP) { - if (!rule) + if (!rcom) return RMAP_OKAY; path = object; - list = community_list_lookup(bgp_clist, rule, + list = community_list_lookup(bgp_clist, rcom->name, + rcom->name_hash, LARGE_COMMUNITY_LIST_MASTER); old = path->attr->lcommunity; @@ -1975,10 +1994,13 @@ static route_map_result_t route_set_lcommunity_delete(void *rule, /* Compile function for set lcommunity. */ static void *route_set_lcommunity_delete_compile(const char *arg) { + struct rmap_community *rcom; char *p; char *str; int len; + rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community)); + p = strchr(arg, ' '); if (p) { len = p - arg; @@ -1987,13 +2009,18 @@ static void *route_set_lcommunity_delete_compile(const char *arg) } else str = NULL; - return str; + rcom->name = str; + rcom->name_hash = bgp_clist_hash_key(rcom->name); + return rcom; } /* Free function for set lcommunity. */ static void route_set_lcommunity_delete_free(void *rule) { - XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); + struct rmap_community *rcom = rule; + + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom); } /* Set lcommunity rule structure. */ @@ -2017,13 +2044,15 @@ static route_map_result_t route_set_community_delete( struct community *new; struct community *old; struct bgp_path_info *path; + struct rmap_community *rcom = rule; if (type == RMAP_BGP) { - if (!rule) + if (!rcom) return RMAP_OKAY; path = object; - list = community_list_lookup(bgp_clist, rule, + list = community_list_lookup(bgp_clist, rcom->name, + rcom->name_hash, COMMUNITY_LIST_MASTER); old = path->attr->community; @@ -2060,10 +2089,13 @@ static route_map_result_t route_set_community_delete( /* Compile function for set community. */ static void *route_set_community_delete_compile(const char *arg) { + struct rmap_community *rcom; char *p; char *str; int len; + rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community)); + p = strchr(arg, ' '); if (p) { len = p - arg; @@ -2072,13 +2104,18 @@ static void *route_set_community_delete_compile(const char *arg) } else str = NULL; - return str; + rcom->name = str; + rcom->name_hash = bgp_clist_hash_key(rcom->name); + return rcom; } /* Free function for set community. */ static void route_set_community_delete_free(void *rule) { - XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); + struct rmap_community *rcom = rule; + + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom); } /* Set community rule structure. */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 2a4421aa54..c6e48cc160 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -37,6 +37,7 @@ #include "frrstr.h" #include "bgpd/bgpd.h" +#include "bgpd/bgp_attr_evpn.h" #include "bgpd/bgp_advertise.h" #include "bgpd/bgp_attr.h" #include "bgpd/bgp_aspath.h" @@ -62,6 +63,7 @@ #include "bgpd/bgp_io.h" #include "bgpd/bgp_evpn.h" #include "bgpd/bgp_addpath.h" +#include "bgpd/bgp_mac.h" static struct peer_group *listen_range_exists(struct bgp *bgp, struct prefix *range, int exact); @@ -7244,13 +7246,15 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name, /* one clear bgp command to rule them all */ DEFUN (clear_ip_bgp_all, clear_ip_bgp_all_cmd, - "clear [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> [<soft [<in|out>]|in [prefix-filter]|out>]", + "clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> [<soft [<in|out>]|in [prefix-filter]|out>]", CLEAR_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR + "Address Family\n" BGP_SAFI_WITH_LABEL_HELP_STR + "Address Family modifier\n" "Clear all peers\n" "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" @@ -7574,6 +7578,18 @@ DEFUN (show_bgp_vrfs, return CMD_SUCCESS; } +DEFUN (show_bgp_mac_hash, + show_bgp_mac_hash_cmd, + "show bgp mac hash", + SHOW_STR + BGP_STR + "Mac Address\n" + "Mac Address database\n") +{ + bgp_mac_dump_table(vty); + + return CMD_SUCCESS; +} static void show_tip_entry(struct hash_backet *backet, void *args) { @@ -12999,6 +13015,8 @@ void bgp_vty_init(void) &neighbor_soft_reconfiguration_cmd); install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_soft_reconfiguration_cmd); + install_element(BGP_EVPN_NODE, &neighbor_soft_reconfiguration_cmd); + install_element(BGP_EVPN_NODE, &no_neighbor_soft_reconfiguration_cmd); /* "neighbor attribute-unchanged" commands. */ install_element(BGP_NODE, &neighbor_attr_unchanged_hidden_cmd); @@ -13832,6 +13850,8 @@ void bgp_vty_init(void) /* "show bgp martian next-hop" */ install_element(VIEW_NODE, &show_bgp_martian_nexthop_db_cmd); + install_element(VIEW_NODE, &show_bgp_mac_hash_cmd); + /* "show [ip] bgp views" commands. */ install_element(VIEW_NODE, &show_bgp_views_cmd); @@ -14309,7 +14329,7 @@ DEFUN (show_community_list_arg, vty_out(vty, "'show bgp community-list <(1-500)|WORD>'\n"); zlog_warn("Deprecated option: 'ip show community-list <(1-500)|WORD>' being used"); } - list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, + list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, 0, COMMUNITY_LIST_MASTER); if (!list) { vty_out(vty, "%% Can't find community-list\n"); @@ -14834,7 +14854,7 @@ DEFUN (show_lcommunity_list_arg, zlog_warn("Deprecated option: 'ip show large-community-list <(1-500)|WORD>' being used"); } - list = community_list_lookup(bgp_clist, argv[3]->arg, + list = community_list_lookup(bgp_clist, argv[3]->arg, 0, LARGE_COMMUNITY_LIST_MASTER); if (!list) { vty_out(vty, "%% Can't find extcommunity-list\n"); @@ -15235,7 +15255,7 @@ DEFUN (show_extcommunity_list_arg, vty_out(vty, "'show bgp extcommunity-list <(1-500)|WORD>'\n"); zlog_warn("Deprecated option: 'ip show extcommunity-list <(1-500)|WORD>' being used"); } - list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, + list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, 0, EXTCOMMUNITY_LIST_MASTER); if (!list) { vty_out(vty, "%% Can't find extcommunity-list\n"); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 66d3333739..3c4b219466 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -59,6 +59,7 @@ #include "bgpd/bgp_labelpool.h" #include "bgpd/bgp_pbr.h" #include "bgpd/bgp_evpn_private.h" +#include "bgpd/bgp_mac.h" /* All information about zebra. */ struct zclient *zclient = NULL; @@ -221,6 +222,8 @@ static int bgp_interface_add(int command, struct zclient *zclient, if (!bgp) return 0; + bgp_mac_add_mac_entry(ifp); + bgp_update_interface_nbrs(bgp, ifp, ifp); return 0; } @@ -245,6 +248,8 @@ static int bgp_interface_delete(int command, struct zclient *zclient, if (bgp) bgp_update_interface_nbrs(bgp, ifp, NULL); + bgp_mac_del_mac_entry(ifp); + if_set_index(ifp, IFINDEX_INTERNAL); return 0; } @@ -267,6 +272,8 @@ static int bgp_interface_up(int command, struct zclient *zclient, if (!ifp) return 0; + bgp_mac_add_mac_entry(ifp); + if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("Rx Intf up VRF %u IF %s", vrf_id, ifp->name); @@ -300,6 +307,8 @@ static int bgp_interface_down(int command, struct zclient *zclient, if (!ifp) return 0; + bgp_mac_del_mac_entry(ifp); + if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("Rx Intf down VRF %u IF %s", vrf_id, ifp->name); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 7a3afbd18d..5b8ceb0541 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -87,6 +87,7 @@ #include "bgpd/bgp_pbr.h" #include "bgpd/bgp_addpath.h" #include "bgpd/bgp_evpn_private.h" +#include "bgpd/bgp_mac.h" DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)"); DEFINE_MTYPE_STATIC(BGPD, BGP_EVPN_INFO, "BGP EVPN instance information"); @@ -7775,6 +7776,7 @@ void bgp_master_init(struct thread_master *master) bgp_process_queue_init(); + bgp_mac_init(); /* init the rd id space. assign 0th index in the bitfield, so that we start with id 1 @@ -7964,4 +7966,5 @@ void bgp_terminate(void) if (bm->t_rmap_update) BGP_TIMER_OFF(bm->t_rmap_update); + bgp_mac_finish(); } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index f28ca9fa0b..484fc105e8 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -122,6 +122,9 @@ struct bgp_master { /* Listener address */ char *address; + /* The Mac table */ + struct hash *self_mac_hash; + /* BGP start time. */ time_t start_time; diff --git a/bgpd/subdir.am b/bgpd/subdir.am index 7d7d3ca189..7dd1d73f69 100644 --- a/bgpd/subdir.am +++ b/bgpd/subdir.am @@ -72,6 +72,7 @@ bgpd_libbgp_a_SOURCES = \ bgpd/bgp_label.c \ bgpd/bgp_labelpool.c \ bgpd/bgp_lcommunity.c \ + bgpd/bgp_mac.c \ bgpd/bgp_memory.c \ bgpd/bgp_mpath.c \ bgpd/bgp_mplsvpn.c \ @@ -145,6 +146,7 @@ noinst_HEADERS += \ bgpd/bgp_label.h \ bgpd/bgp_labelpool.h \ bgpd/bgp_lcommunity.h \ + bgpd/bgp_mac.h \ bgpd/bgp_memory.h \ bgpd/bgp_mpath.h \ bgpd/bgp_mplsvpn.h \ diff --git a/doc/developer/building-frr-for-freebsd10.rst b/doc/developer/building-frr-for-freebsd10.rst index 5dde915f6a..a6539309a2 100644 --- a/doc/developer/building-frr-for-freebsd10.rst +++ b/doc/developer/building-frr-for-freebsd10.rst @@ -17,12 +17,14 @@ is first package install and asked) :: pkg install git autoconf automake libtool gmake gawk json-c pkgconf \ - bison flex py27-pytest c-ares python3 py-sphinx libyang + bison flex py27-pytest c-ares python3 py-sphinx Make sure there is no /usr/bin/flex preinstalled (and use the newly installed in /usr/local/bin): (FreeBSD frequently provides a older flex as part of the base OS which takes preference in path) +.. include:: building-libyang.rst + :: rm -f /usr/bin/flex diff --git a/doc/developer/building-frr-for-freebsd11.rst b/doc/developer/building-frr-for-freebsd11.rst index 9bef1fbfde..16d06e0a66 100644 --- a/doc/developer/building-frr-for-freebsd11.rst +++ b/doc/developer/building-frr-for-freebsd11.rst @@ -17,12 +17,14 @@ is first package install and asked) .. code-block:: shell pkg install git autoconf automake libtool gmake gawk json-c pkgconf \ - bison flex py27-pytest c-ares python3 py36-sphinx texinfo libyang + bison flex py27-pytest c-ares python3 py36-sphinx texinfo Make sure there is no /usr/bin/flex preinstalled (and use the newly installed in /usr/local/bin): (FreeBSD frequently provides a older flex as part of the base OS which takes preference in path) +.. include:: building-libyang.rst + .. code-block:: shell rm -f /usr/bin/flex diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index a27243ea77..5b453e75c3 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -968,6 +968,13 @@ Configuring Peers and will not be displayed as part of a `show run`. The no form of the command turns off this ability. +.. index:: [no] bgp default ipv4-unicast +.. clicmd:: [no] bgp default ipv4-unicast + + This command allows the user to specify that v4 peering is turned + on by default or not. This command defaults to on and is not displayed. + The `no bgp default ipv4-unicast` form of the command is displayed. + .. _bgp-peer-filtering: Peer Filtering diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 29bd23b514..a810e01468 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -425,7 +425,7 @@ void eigrp_zebra_route_delete(struct prefix *p) int eigrp_is_type_redistributed(int type) { return ((DEFAULT_ROUTE_TYPE(type)) - ? vrf_bitmap_check(zclient->default_information, + ? vrf_bitmap_check(zclient->default_information[AFI_IP], VRF_DEFAULT) : vrf_bitmap_check(zclient->redist[AFI_IP][type], VRF_DEFAULT)); diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 101bd57cc9..958f8c2281 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -390,7 +390,7 @@ void isis_zebra_redistribute_set(afi_t afi, int type) { if (type == DEFAULT_ROUTE) zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, - zclient, VRF_DEFAULT); + zclient, afi, VRF_DEFAULT); else zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, 0, VRF_DEFAULT); @@ -400,7 +400,7 @@ void isis_zebra_redistribute_unset(afi_t afi, int type) { if (type == DEFAULT_ROUTE) zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, - zclient, VRF_DEFAULT); + zclient, afi, VRF_DEFAULT); else zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type, 0, VRF_DEFAULT); diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c index a0223730b8..d5a2007c4d 100644 --- a/lib/frr_pthread.c +++ b/lib/frr_pthread.c @@ -84,6 +84,8 @@ struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr, fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name); if (os_name) snprintf(fpt->os_name, OS_THREAD_NAMELEN, "%s", os_name); + else + snprintf(fpt->os_name, OS_THREAD_NAMELEN, "%s", name); /* initialize startup synchronization primitives */ fpt->running_cond_mtx = XCALLOC( MTYPE_PTHREAD_PRIM, sizeof(pthread_mutex_t)); @@ -115,36 +117,19 @@ void frr_pthread_destroy(struct frr_pthread *fpt) XFREE(MTYPE_FRR_PTHREAD, fpt); } -int frr_pthread_set_name(struct frr_pthread *fpt, const char *name, - const char *os_name) +int frr_pthread_set_name(struct frr_pthread *fpt) { int ret = 0; - if (name) { - pthread_mutex_lock(&fpt->mtx); - { - if (fpt->name) - XFREE(MTYPE_FRR_PTHREAD, fpt->name); - fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name); - } - pthread_mutex_unlock(&fpt->mtx); - thread_master_set_name(fpt->master, name); - } - - if (os_name) { - pthread_mutex_lock(&fpt->mtx); - snprintf(fpt->os_name, OS_THREAD_NAMELEN, "%s", os_name); - pthread_mutex_unlock(&fpt->mtx); #ifdef HAVE_PTHREAD_SETNAME_NP # ifdef GNU_LINUX - ret = pthread_setname_np(fpt->thread, fpt->os_name); + ret = pthread_setname_np(fpt->thread, fpt->os_name); # else /* NetBSD */ - ret = pthread_setname_np(fpt->thread, fpt->os_name, NULL); + ret = pthread_setname_np(fpt->thread, fpt->os_name, NULL); # endif #elif defined(HAVE_PTHREAD_SET_NAME_NP) - pthread_set_name_np(fpt->thread, fpt->os_name); + pthread_set_name_np(fpt->thread, fpt->os_name); #endif - } return ret; } @@ -273,8 +258,7 @@ static void *fpt_run(void *arg) fpt->master->handle_signals = false; - if (fpt->os_name[0]) - frr_pthread_set_name(fpt, NULL, fpt->os_name); + frr_pthread_set_name(fpt); frr_pthread_notify_running(fpt); diff --git a/lib/frr_pthread.h b/lib/frr_pthread.h index b9e60511d5..e6b3f031b3 100644 --- a/lib/frr_pthread.h +++ b/lib/frr_pthread.h @@ -133,16 +133,13 @@ struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr, const char *name, const char *os_name); /* - * Changes the name of the frr_pthread. + * Changes the name of the frr_pthread as reported by the operating + * system. * * @param fpt - the frr_pthread to operate on - * @param name - Human-readable name - * @param os_name - 16 characters thread name , including the null - * terminator ('\0') to set in os. * @return - on success returns 0 otherwise nonzero error number. */ -int frr_pthread_set_name(struct frr_pthread *fpt, const char *name, - const char *os_name); +int frr_pthread_set_name(struct frr_pthread *fpt); /* * Destroys an frr_pthread. diff --git a/lib/lib_errors.c b/lib/lib_errors.c index 7e428f135c..5f6c25b770 100644 --- a/lib/lib_errors.c +++ b/lib/lib_errors.c @@ -102,7 +102,7 @@ static struct log_ref ferr_lib_warn[] = { .code = EC_LIB_NB_CB_UNNEEDED, .title = "Unneeded northbound callback", .description = "The northbound subsystem, during initialization, has detected a callback that doesn't need to be implemented", - .suggestion = "Check if the installed FRR YANG modules are in sync with the FRR binaries", + .suggestion = "This is a bug; please report it" }, { .code = EC_LIB_NB_CB_CONFIG_VALIDATE, @@ -270,19 +270,19 @@ static struct log_ref ferr_lib_err[] = { .code = EC_LIB_NB_CB_MISSING, .title = "Missing northbound callback", .description = "The northbound subsystem, during initialization, has detected a missing callback for one node of the loaded YANG modules", - .suggestion = "Check if the installed FRR YANG modules are in sync with the FRR binaries", + .suggestion = "This is a bug; please report it" }, { .code = EC_LIB_NB_CB_INVALID_PRIO, .title = "Norhtbound callback has an invalid priority", .description = "The northbound subsystem, during initialization, has detected a callback whose priority is invalid", - .suggestion = "Check if the installed FRR YANG modules are in sync with the FRR binaries", + .suggestion = "This is a bug; please report it" }, { .code = EC_LIB_NB_CBS_VALIDATION, .title = "Failure to validate the northbound callbacks", .description = "The northbound subsystem, during initialization, has detected one or more errors while loading the northbound callbacks", - .suggestion = "Check if the installed FRR YANG modules are in sync with the FRR binaries", + .suggestion = "This is a bug; please report it" }, { .code = EC_LIB_LIBYANG, diff --git a/lib/northbound.c b/lib/northbound.c index a7f9c8620e..6fe612d72a 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -719,7 +719,6 @@ static int nb_configuration_callback(const enum nb_event event, const struct lyd_node *dnode = change->cb.dnode; union nb_resource *resource; int ret = NB_ERR; - enum lib_log_refs ref; if (debug_northbound) { const char *value = "(none)"; @@ -753,6 +752,8 @@ static int nb_configuration_callback(const enum nb_event event, } if (ret != NB_OK) { + enum lib_log_refs ref = 0; + switch (event) { case NB_EV_VALIDATE: ref = EC_LIB_NB_CB_CONFIG_VALIDATE; @@ -1277,8 +1278,12 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator, n++; } list_keys.num = n; - assert(list_keys.num - == ((struct lys_node_list *)dn->schema)->keys_size); + if (list_keys.num + != ((struct lys_node_list *)dn->schema)->keys_size) { + list_delete(&list_dnodes); + yang_dnode_free(dnode); + return NB_ERR_NOT_FOUND; + } /* Find the list entry pointer. */ nn = dn->schema->priv; diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c index 2b024ace93..33035de31b 100644 --- a/lib/northbound_cli.c +++ b/lib/northbound_cli.c @@ -261,7 +261,7 @@ static int nb_cli_confirmed_commit_timeout(struct thread *thread) static int nb_cli_commit(struct vty *vty, bool force, unsigned int confirmed_timeout, char *comment) { - uint32_t transaction_id; + uint32_t transaction_id = 0; int ret; /* Check if there's a pending confirmed commit. */ diff --git a/lib/prefix.c b/lib/prefix.c index 858f860ee8..0203301562 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -451,7 +451,7 @@ int is_zero_mac(struct ethaddr *mac) return 1; } -unsigned int prefix_bit(const uint8_t *prefix, const uint8_t prefixlen) +unsigned int prefix_bit(const uint8_t *prefix, const uint16_t prefixlen) { unsigned int offset = prefixlen / 8; unsigned int shift = 7 - (prefixlen % 8); @@ -459,7 +459,7 @@ unsigned int prefix_bit(const uint8_t *prefix, const uint8_t prefixlen) return (prefix[offset] >> shift) & 1; } -unsigned int prefix6_bit(const struct in6_addr *prefix, const uint8_t prefixlen) +unsigned int prefix6_bit(const struct in6_addr *prefix, const uint16_t prefixlen) { return prefix_bit((const uint8_t *)&prefix->s6_addr, prefixlen); } @@ -966,18 +966,16 @@ void masklen2ip(const int masklen, struct in_addr *netmask) } /* Convert IP address's netmask into integer. We assume netmask is - sequential one. Argument netmask should be network byte order. */ + * sequential one. Argument netmask should be network byte order. */ uint8_t ip_masklen(struct in_addr netmask) { uint32_t tmp = ~ntohl(netmask.s_addr); - if (tmp) - /* clz: count leading zeroes. sadly, the behaviour of this - * builtin - * is undefined for a 0 argument, even though most CPUs give 32 - */ - return __builtin_clz(tmp); - else - return 32; + + /* + * clz: count leading zeroes. sadly, the behaviour of this builtin is + * undefined for a 0 argument, even though most CPUs give 32 + */ + return tmp ? __builtin_clz(tmp) : 32; } /* Apply mask to IPv4 prefix (network byte order). */ diff --git a/lib/prefix.h b/lib/prefix.h index 4247569137..aaffb1e0c5 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -151,7 +151,7 @@ struct flowspec_prefix { /* FRR generic prefix structure. */ struct prefix { uint8_t family; - uint8_t prefixlen; + uint16_t prefixlen; union { uint8_t prefix; struct in_addr prefix4; @@ -162,6 +162,7 @@ struct prefix { } lp; struct ethaddr prefix_eth; /* AF_ETHERNET */ uint8_t val[16]; + uint32_t val32[4]; uintptr_t ptr; struct evpn_addr prefix_evpn; /* AF_EVPN */ struct flowspec_prefix prefix_flowspec; /* AF_FLOWSPEC */ @@ -171,20 +172,20 @@ struct prefix { /* IPv4 prefix structure. */ struct prefix_ipv4 { uint8_t family; - uint8_t prefixlen; + uint16_t prefixlen; struct in_addr prefix __attribute__((aligned(8))); }; /* IPv6 prefix structure. */ struct prefix_ipv6 { uint8_t family; - uint8_t prefixlen; + uint16_t prefixlen; struct in6_addr prefix __attribute__((aligned(8))); }; struct prefix_ls { uint8_t family; - uint8_t prefixlen; + uint16_t prefixlen; struct in_addr id __attribute__((aligned(8))); struct in_addr adv_router; }; @@ -192,21 +193,21 @@ struct prefix_ls { /* Prefix for routing distinguisher. */ struct prefix_rd { uint8_t family; - uint8_t prefixlen; + uint16_t prefixlen; uint8_t val[8] __attribute__((aligned(8))); }; /* Prefix for ethernet. */ struct prefix_eth { uint8_t family; - uint8_t prefixlen; + uint16_t prefixlen; struct ethaddr eth_addr __attribute__((aligned(8))); /* AF_ETHERNET */ }; /* EVPN prefix structure. */ struct prefix_evpn { uint8_t family; - uint8_t prefixlen; + uint16_t prefixlen; struct evpn_addr prefix __attribute__((aligned(8))); }; @@ -252,20 +253,20 @@ static inline int is_evpn_prefix_ipaddr_v6(const struct prefix_evpn *evp) /* Prefix for a generic pointer */ struct prefix_ptr { uint8_t family; - uint8_t prefixlen; + uint16_t prefixlen; uintptr_t prefix __attribute__((aligned(8))); }; /* Prefix for a Flowspec entry */ struct prefix_fs { uint8_t family; - uint8_t prefixlen; /* unused */ + uint16_t prefixlen; /* unused */ struct flowspec_prefix prefix __attribute__((aligned(8))); }; struct prefix_sg { uint8_t family; - uint8_t prefixlen; + uint16_t prefixlen; struct in_addr src __attribute__((aligned(8))); struct in_addr grp; }; @@ -296,15 +297,16 @@ union prefixconstptr { #endif /* INET_ADDRSTRLEN */ #ifndef INET6_ADDRSTRLEN +/* dead:beef:dead:beef:dead:beef:dead:beef + \0 */ #define INET6_ADDRSTRLEN 46 #endif /* INET6_ADDRSTRLEN */ #ifndef INET6_BUFSIZ -#define INET6_BUFSIZ 51 +#define INET6_BUFSIZ 53 #endif /* INET6_BUFSIZ */ -/* Maximum prefix string length (IPv6) */ -#define PREFIX_STRLEN 51 +/* Maximum string length of the result of prefix2str */ +#define PREFIX_STRLEN 80 /* Max bit/byte length of IPv4 address. */ #define IPV4_MAX_BYTELEN 4 @@ -367,9 +369,9 @@ extern const char *safi2str(safi_t safi); extern const char *afi2str(afi_t afi); /* Check bit of the prefix. */ -extern unsigned int prefix_bit(const uint8_t *prefix, const uint8_t prefixlen); +extern unsigned int prefix_bit(const uint8_t *prefix, const uint16_t prefixlen); extern unsigned int prefix6_bit(const struct in6_addr *prefix, - const uint8_t prefixlen); + const uint16_t prefixlen); extern struct prefix *prefix_new(void); extern void prefix_free(struct prefix *); diff --git a/lib/table.c b/lib/table.c index 0026b7692b..edba7f1932 100644 --- a/lib/table.c +++ b/lib/table.c @@ -283,7 +283,7 @@ struct route_node *route_node_get(struct route_table *const table, struct route_node *node; struct route_node *match; struct route_node *inserted; - uint8_t prefixlen = p->prefixlen; + uint16_t prefixlen = p->prefixlen; const uint8_t *prefix = &p->u.prefix; apply_mask((struct prefix *)p); diff --git a/lib/thread.c b/lib/thread.c index 44c9e2b2f1..867ca2dc60 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -1572,8 +1572,13 @@ void thread_set_yield_time(struct thread *thread, unsigned long yield_time) void thread_getrusage(RUSAGE_T *r) { +#if defined RUSAGE_THREAD +#define FRR_RUSAGE RUSAGE_THREAD +#else +#define FRR_RUSAGE RUSAGE_SELF +#endif monotime(&r->real); - getrusage(RUSAGE_SELF, &(r->cpu)); + getrusage(FRR_RUSAGE, &(r->cpu)); } /* diff --git a/lib/zclient.c b/lib/zclient.c index 1c40750db0..cc936d47d7 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -173,10 +173,10 @@ void zclient_stop(struct zclient *zclient) redist_del_instance( &zclient->mi_redist[afi][zclient->redist_default], zclient->instance); - } - vrf_bitmap_free(zclient->default_information); - zclient->default_information = VRF_BITMAP_NULL; + vrf_bitmap_free(zclient->default_information[afi]); + zclient->default_information[afi] = VRF_BITMAP_NULL; + } } void zclient_reset(struct zclient *zclient) @@ -447,7 +447,7 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id) } /* Resend all redistribute request. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (i = 0; i < ZEBRA_ROUTE_MAX; i++) if (i != zclient->redist_default && vrf_bitmap_check(zclient->redist[afi][i], @@ -456,10 +456,13 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id) zclient, afi, i, 0, vrf_id); - /* If default information is needed. */ - if (vrf_bitmap_check(zclient->default_information, VRF_DEFAULT)) - zebra_message_send(zclient, ZEBRA_REDISTRIBUTE_DEFAULT_ADD, - vrf_id); + /* If default information is needed. */ + if (vrf_bitmap_check(zclient->default_information[afi], + VRF_DEFAULT)) + zebra_redistribute_default_send( + ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, afi, + vrf_id); + } } /* Send unregister requests to zebra daemon for the information in a VRF. */ @@ -512,7 +515,7 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id) } /* Flush all redistribute request. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (i = 0; i < ZEBRA_ROUTE_MAX; i++) if (i != zclient->redist_default && vrf_bitmap_check(zclient->redist[afi][i], @@ -521,10 +524,13 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id) ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, i, 0, vrf_id); - /* If default information is needed. */ - if (vrf_bitmap_check(zclient->default_information, VRF_DEFAULT)) - zebra_message_send(zclient, ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, - vrf_id); + /* If default information is needed. */ + if (vrf_bitmap_check(zclient->default_information[afi], + VRF_DEFAULT)) + zebra_redistribute_default_send( + ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, afi, + vrf_id); + } } /* Send request to zebra daemon to start or stop RA. */ @@ -620,12 +626,13 @@ void zclient_init(struct zclient *zclient, int redist_default, zclient->redist_default = redist_default; zclient->instance = instance; /* Pending: make afi(s) an arg. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (afi = AFI_IP; afi < AFI_MAX; afi++) { redist_add_instance(&zclient->mi_redist[afi][redist_default], instance); - /* Set default-information redistribute to zero. */ - zclient->default_information = vrf_bitmap_init(); + /* Set default-information redistribute to zero. */ + zclient->default_information[afi] = vrf_bitmap_init(); + } if (zclient_debug) zlog_debug("zclient_start is called"); @@ -1280,6 +1287,22 @@ int zebra_redistribute_send(int command, struct zclient *zclient, afi_t afi, return zclient_send_message(zclient); } +int zebra_redistribute_default_send(int command, struct zclient *zclient, + afi_t afi, vrf_id_t vrf_id) +{ + struct stream *s; + + s = zclient->obuf; + stream_reset(s); + + zclient_create_header(s, command, vrf_id); + stream_putc(s, afi); + + stream_putw_at(s, 0, stream_get_endp(s)); + + return zclient_send_message(zclient); +} + /* Get prefix in ZServ format; family should be filled in on prefix */ static void zclient_stream_get_prefix(struct stream *s, struct prefix *p) { @@ -2709,21 +2732,22 @@ void zclient_redistribute(int command, struct zclient *zclient, afi_t afi, void zclient_redistribute_default(int command, struct zclient *zclient, - vrf_id_t vrf_id) + afi_t afi, vrf_id_t vrf_id) { if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD) { - if (vrf_bitmap_check(zclient->default_information, vrf_id)) + if (vrf_bitmap_check(zclient->default_information[afi], vrf_id)) return; - vrf_bitmap_set(zclient->default_information, vrf_id); + vrf_bitmap_set(zclient->default_information[afi], vrf_id); } else { - if (!vrf_bitmap_check(zclient->default_information, vrf_id)) + if (!vrf_bitmap_check(zclient->default_information[afi], + vrf_id)) return; - vrf_bitmap_unset(zclient->default_information, vrf_id); + vrf_bitmap_unset(zclient->default_information[afi], vrf_id); } if (zclient->sock > 0) - zebra_message_send(zclient, command, vrf_id); + zebra_redistribute_default_send(command, zclient, afi, vrf_id); } static void zclient_event(enum event event, struct zclient *zclient) diff --git a/lib/zclient.h b/lib/zclient.h index 831cccfb7e..401d6c400a 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -216,7 +216,7 @@ struct zclient { vrf_bitmap_t redist[AFI_MAX][ZEBRA_ROUTE_MAX]; /* Redistribute defauilt. */ - vrf_bitmap_t default_information; + vrf_bitmap_t default_information[AFI_MAX]; /* Pointer to the callback functions. */ void (*zebra_connected)(struct zclient *); @@ -479,13 +479,16 @@ extern int zebra_redistribute_send(int command, struct zclient *, afi_t, int type, unsigned short instance, vrf_id_t vrf_id); +extern int zebra_redistribute_default_send(int command, struct zclient *zclient, + afi_t afi, vrf_id_t vrf_id); + /* If state has changed, update state and call zebra_redistribute_send. */ extern void zclient_redistribute(int command, struct zclient *, afi_t, int type, unsigned short instance, vrf_id_t vrf_id); /* If state has changed, update state and send the command to zebra. */ extern void zclient_redistribute_default(int command, struct zclient *, - vrf_id_t vrf_id); + afi_t, vrf_id_t vrf_id); /* Send the message in zclient->obuf to the zebra daemon (or enqueue it). Returns 0 for success or -1 on an I/O error. */ diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 5db9b529ef..54f1735e7a 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -269,7 +269,8 @@ DEFUN (show_zebra, vty_out(vty, "Zebra Infomation\n"); vty_out(vty, " fail: %d\n", zclient->fail); vty_out(vty, " redistribute default: %d\n", - vrf_bitmap_check(zclient->default_information, VRF_DEFAULT)); + vrf_bitmap_check(zclient->default_information[AFI_IP6], + VRF_DEFAULT)); vty_out(vty, " redistribute:"); for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { if (vrf_bitmap_check(zclient->redist[AFI_IP6][i], VRF_DEFAULT)) diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index 714c47b4e6..6d1e44996e 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -96,8 +96,9 @@ struct external_info *ospf_external_info_check(struct ospf *ospf, redist_on = is_prefix_default(&p) - ? vrf_bitmap_check(zclient->default_information, - ospf->vrf_id) + ? vrf_bitmap_check( + zclient->default_information[AFI_IP], + ospf->vrf_id) : (zclient->mi_redist[AFI_IP][type].enabled || vrf_bitmap_check( zclient->redist[AFI_IP][type], diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index c7bde55cd9..79ddb192c1 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -655,7 +655,7 @@ int ospf_is_type_redistributed(struct ospf *ospf, int type, unsigned short instance) { return (DEFAULT_ROUTE_TYPE(type) - ? vrf_bitmap_check(zclient->default_information, + ? vrf_bitmap_check(zclient->default_information[AFI_IP], ospf->vrf_id) : ((instance && redist_check_instance( @@ -793,8 +793,8 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype, * existance. */ zclient_redistribute_default( - ZEBRA_REDISTRIBUTE_DEFAULT_ADD, - zclient, ospf->vrf_id); + ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, AFI_IP, + ospf->vrf_id); } ospf_asbr_status_update(ospf, ++ospf->redistribute); @@ -820,7 +820,7 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype, zclient_redistribute_default( ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, - zclient, ospf->vrf_id); + zclient, AFI_IP, ospf->vrf_id); /* here , ex-info should be added since ex-info might * have not updated earlier if def route is not exist. * If ex-iinfo ex-info already exist , it will return @@ -845,7 +845,7 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype, zclient_redistribute_default( ZEBRA_REDISTRIBUTE_DEFAULT_ADD, - zclient, ospf->vrf_id); + zclient, AFI_IP, ospf->vrf_id); } } @@ -857,7 +857,7 @@ int ospf_redistribute_default_unset(struct ospf *ospf) if (!ospf_is_type_redistributed(ospf, DEFAULT_ROUTE, 0)) return CMD_SUCCESS; zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, - zclient, ospf->vrf_id); + zclient, AFI_IP, ospf->vrf_id); } ospf->default_originate = DEFAULT_ORIGINATE_NONE; diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index d0a34c0f93..86c8bfe1c2 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -90,11 +90,12 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd, DEFPY (install_routes, install_routes_cmd, - "sharp install routes A.B.C.D$start <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]", + "sharp install routes <A.B.C.D$start4|X:X::X:X$start6> <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]", "Sharp routing Protocol\n" "install some routes\n" "Routes to install\n" - "Address to start /32 generation at\n" + "v4 Address to start /32 generation at\n" + "v6 Address to start /32 generation at\n" "Nexthop to use(Can be an IPv4 or IPv6 address)\n" "V4 Nexthop address to use\n" "V6 Nexthop address to use\n" @@ -119,9 +120,15 @@ DEFPY (install_routes, memset(&nhop, 0, sizeof(nhop)); memset(&nhop_group, 0, sizeof(nhop_group)); - prefix.family = AF_INET; - prefix.prefixlen = 32; - prefix.u.prefix4 = start; + if (start4.s_addr != 0) { + prefix.family = AF_INET; + prefix.prefixlen = 32; + prefix.u.prefix4 = start4; + } else { + prefix.family = AF_INET6; + prefix.prefixlen = 128; + prefix.u.prefix6 = start6; + } orig_prefix = prefix; if (nexthop_group) { @@ -185,12 +192,13 @@ DEFPY(vrf_label, vrf_label_cmd, DEFPY (remove_routes, remove_routes_cmd, - "sharp remove routes A.B.C.D$start (1-1000000)$routes [instance (0-255)$instance]", + "sharp remove routes <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]", "Sharp Routing Protocol\n" "Remove some routes\n" "Routes to remove\n" - "Starting spot\n" - "Routes to uniinstall\n" + "v4 Starting spot\n" + "v6 Starting spot\n" + "Routes to uninstall\n" "instance to use\n" "Value of instance\n") { @@ -199,9 +207,15 @@ DEFPY (remove_routes, memset(&prefix, 0, sizeof(prefix)); - prefix.family = AF_INET; - prefix.prefixlen = 32; - prefix.u.prefix4 = start; + if (start4.s_addr != 0) { + prefix.family = AF_INET; + prefix.prefixlen = 32; + prefix.u.prefix4 = start4; + } else { + prefix.family = AF_INET6; + prefix.prefixlen = 128; + prefix.u.prefix6 = start6; + } inst = instance; rts = routes; diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 37591fa41f..c9f333e34b 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -129,6 +129,8 @@ static int interface_state_down(int command, struct zclient *zclient, return 0; } +static struct timeval t_start; +static struct timeval t_end; extern uint32_t total_routes; extern uint32_t installed_routes; extern uint32_t removed_routes; @@ -142,13 +144,23 @@ void sharp_install_routes_helper(struct prefix *p, uint8_t instance, uint32_t routes) { uint32_t temp, i; + bool v4 = false; zlog_debug("Inserting %u routes", routes); - temp = ntohl(p->u.prefix4.s_addr); + if (p->family == AF_INET) { + v4 = true; + temp = ntohl(p->u.prefix4.s_addr); + } else + temp = ntohl(p->u.val32[3]); + + monotime(&t_start); for (i = 0; i < routes; i++) { route_add(p, (uint8_t)instance, nhg); - p->u.prefix4.s_addr = htonl(++temp); + if (v4) + p->u.prefix4.s_addr = htonl(++temp); + else + p->u.val32[3] = htonl(++temp); } } @@ -156,13 +168,23 @@ void sharp_remove_routes_helper(struct prefix *p, uint8_t instance, uint32_t routes) { uint32_t temp, i; + bool v4 = false; zlog_debug("Removing %u routes", routes); - temp = ntohl(p->u.prefix4.s_addr); + if (p->family == AF_INET) { + v4 = true; + temp = ntohl(p->u.prefix4.s_addr); + } else + temp = ntohl(p->u.val32[3]); + + monotime(&t_start); for (i = 0; i < routes; i++) { route_delete(p, (uint8_t)instance); - p->u.prefix4.s_addr = htonl(++temp); + if (v4) + p->u.prefix4.s_addr = htonl(++temp); + else + p->u.val32[3] = htonl(++temp); } } @@ -189,6 +211,7 @@ static void handle_repeated(bool installed) static int route_notify_owner(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { + struct timeval r; struct prefix p; enum zapi_route_notify_owner note; uint32_t table; @@ -200,7 +223,10 @@ static int route_notify_owner(int command, struct zclient *zclient, case ZAPI_ROUTE_INSTALLED: installed_routes++; if (total_routes == installed_routes) { - zlog_debug("Installed All Items"); + monotime(&t_end); + timersub(&t_end, &t_start, &r); + zlog_debug("Installed All Items %ld.%ld", r.tv_sec, + r.tv_usec); handle_repeated(true); } break; @@ -213,7 +239,10 @@ static int route_notify_owner(int command, struct zclient *zclient, case ZAPI_ROUTE_REMOVED: removed_routes++; if (total_routes == removed_routes) { - zlog_debug("Removed all Items"); + monotime(&t_end); + timersub(&t_end, &t_start, &r); + zlog_debug("Removed all Items %ld.%ld", r.tv_sec, + r.tv_usec); handle_repeated(false); } break; diff --git a/staticd/static_nht.c b/staticd/static_nht.c index 44f7fb79da..38fd53a1f2 100644 --- a/staticd/static_nht.c +++ b/staticd/static_nht.c @@ -29,59 +29,68 @@ #include "static_zebra.h" #include "static_nht.h" -void static_nht_update(struct prefix *p, uint32_t nh_num, afi_t afi, - vrf_id_t nh_vrf_id) +static void static_nht_update_safi(struct prefix *p, uint32_t nh_num, + afi_t afi, safi_t safi, struct vrf *vrf, + vrf_id_t nh_vrf_id) { struct route_table *stable; struct static_route *si; struct static_vrf *svrf; struct route_node *rn; - struct vrf *vrf; bool orig; bool reinstall; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - svrf = vrf->info; - if (!svrf) - continue; + svrf = vrf->info; + if (!svrf) + return; - stable = static_vrf_static_table(afi, SAFI_UNICAST, svrf); - if (!stable) - continue; + stable = static_vrf_static_table(afi, safi, svrf); + if (!stable) + return; - for (rn = route_top(stable); rn; rn = route_next(rn)) { - reinstall = false; - for (si = rn->info; si; si = si->next) { - if (si->nh_vrf_id != nh_vrf_id) - continue; + for (rn = route_top(stable); rn; rn = route_next(rn)) { + reinstall = false; + for (si = rn->info; si; si = si->next) { + if (si->nh_vrf_id != nh_vrf_id) + return; - if (si->type != STATIC_IPV4_GATEWAY - && si->type != STATIC_IPV4_GATEWAY_IFNAME - && si->type != STATIC_IPV6_GATEWAY - && si->type != STATIC_IPV6_GATEWAY_IFNAME) - continue; + if (si->type != STATIC_IPV4_GATEWAY + && si->type != STATIC_IPV4_GATEWAY_IFNAME + && si->type != STATIC_IPV6_GATEWAY + && si->type != STATIC_IPV6_GATEWAY_IFNAME) + return; - orig = si->nh_valid; - if (p->family == AF_INET - && p->u.prefix4.s_addr - == si->addr.ipv4.s_addr) - si->nh_valid = !!nh_num; + orig = si->nh_valid; + if (p->family == AF_INET + && p->u.prefix4.s_addr == si->addr.ipv4.s_addr) + si->nh_valid = !!nh_num; - if (p->family == AF_INET6 - && memcmp(&p->u.prefix6, &si->addr.ipv6, 16) - == 0) - si->nh_valid = !!nh_num; + if (p->family == AF_INET6 + && memcmp(&p->u.prefix6, &si->addr.ipv6, 16) == 0) + si->nh_valid = !!nh_num; - if (orig != si->nh_valid) - reinstall = true; + if (orig != si->nh_valid) + reinstall = true; - if (reinstall) { - static_zebra_route_add( - rn, si, vrf->vrf_id, - SAFI_UNICAST, true); - reinstall = false; - } + if (reinstall) { + static_zebra_route_add(rn, si, vrf->vrf_id, + safi, true); + reinstall = false; } } } } + +void static_nht_update(struct prefix *p, uint32_t nh_num, afi_t afi, + vrf_id_t nh_vrf_id) +{ + + struct vrf *vrf; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + static_nht_update_safi(p, nh_num, afi, SAFI_UNICAST, + vrf, nh_vrf_id); + static_nht_update_safi(p, nh_num, afi, SAFI_MULTICAST, + vrf, nh_vrf_id); + } +} diff --git a/zebra/connected.c b/zebra/connected.c index 54f4394a56..ab66eb3324 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -275,7 +275,7 @@ void connected_up(struct interface *ifp, struct connected *ifc) /* Add connected IPv4 route to the interface. */ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr, - uint8_t prefixlen, struct in_addr *broad, + uint16_t prefixlen, struct in_addr *broad, const char *label) { struct prefix_ipv4 *p; @@ -473,7 +473,7 @@ static void connected_delete_helper(struct connected *ifc, struct prefix *p) /* Delete connected IPv4 route to the interface. */ void connected_delete_ipv4(struct interface *ifp, int flags, - struct in_addr *addr, uint8_t prefixlen, + struct in_addr *addr, uint16_t prefixlen, struct in_addr *broad) { struct prefix p, d; @@ -499,7 +499,7 @@ void connected_delete_ipv4(struct interface *ifp, int flags, /* Add connected IPv6 route to the interface. */ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr, - struct in6_addr *broad, uint8_t prefixlen, + struct in6_addr *broad, uint16_t prefixlen, const char *label) { struct prefix_ipv6 *p; @@ -556,7 +556,7 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr, } void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address, - struct in6_addr *broad, uint8_t prefixlen) + struct in6_addr *broad, uint16_t prefixlen) { struct prefix p, d; struct connected *ifc; diff --git a/zebra/connected.h b/zebra/connected.h index 75b6e05bda..415ecfd965 100644 --- a/zebra/connected.h +++ b/zebra/connected.h @@ -35,11 +35,11 @@ extern struct connected *connected_check_ptp(struct interface *ifp, union prefixconstptr d); extern void connected_add_ipv4(struct interface *ifp, int flags, - struct in_addr *addr, uint8_t prefixlen, + struct in_addr *addr, uint16_t prefixlen, struct in_addr *broad, const char *label); extern void connected_delete_ipv4(struct interface *ifp, int flags, - struct in_addr *addr, uint8_t prefixlen, + struct in_addr *addr, uint16_t prefixlen, struct in_addr *broad); extern void connected_delete_ipv4_unnumbered(struct connected *ifc); @@ -49,10 +49,10 @@ extern void connected_down(struct interface *ifp, struct connected *ifc); extern void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *address, struct in6_addr *broad, - uint8_t prefixlen, const char *label); + uint16_t prefixlen, const char *label); extern void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address, - struct in6_addr *broad, uint8_t prefixlen); + struct in6_addr *broad, uint16_t prefixlen); extern int connected_is_unnumbered(struct interface *); diff --git a/zebra/main.c b/zebra/main.c index 90d3dbc180..b54c36c109 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -407,10 +407,7 @@ int main(int argc, char **argv) /* * Initialize NS( and implicitly the VRF module), and make kernel * routing socket. */ - zebra_ns_init(); - if (vrf_default_name_configured) - vrf_set_default_name(vrf_default_name_configured, - true); + zebra_ns_init((const char *)vrf_default_name_configured); zebra_vty_init(); access_list_init(); prefix_list_init(); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index f48fc6addb..b9c1f0aefd 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -177,7 +177,8 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p, send_redistribute = 0; if (is_default_prefix(p) - && vrf_bitmap_check(client->redist_default, re->vrf_id)) + && vrf_bitmap_check(client->redist_default[afi], + re->vrf_id)) send_redistribute = 1; else if (vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id)) @@ -246,7 +247,8 @@ void redistribute_delete(const struct prefix *p, const struct prefix *src_p, for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { if ((is_default_prefix(p) - && vrf_bitmap_check(client->redist_default, re->vrf_id)) + && vrf_bitmap_check(client->redist_default[afi], + re->vrf_id)) || vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id) || (re->instance @@ -354,13 +356,41 @@ stream_failure: void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS) { - vrf_bitmap_set(client->redist_default, zvrf_id(zvrf)); + afi_t afi = 0; + + STREAM_GETC(msg, afi); + + if (afi == 0 || afi >= AFI_MAX) { + flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF, + "%s: Specified afi %u does not exist", + __PRETTY_FUNCTION__, afi); + return; + } + + vrf_bitmap_set(client->redist_default[afi], zvrf_id(zvrf)); zebra_redistribute_default(client, zvrf_id(zvrf)); + +stream_failure: + return; } void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS) { - vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf)); + afi_t afi = 0; + + STREAM_GETC(msg, afi); + + if (afi == 0 || afi >= AFI_MAX) { + flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF, + "%s: Specified afi %u does not exist", + __PRETTY_FUNCTION__, afi); + return; + } + + vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf)); + +stream_failure: + return; } /* Interface up information. */ diff --git a/zebra/rib.h b/zebra/rib.h index ae25a0e679..a478fffddb 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -81,12 +81,20 @@ struct route_entry { uint32_t flags; /* RIB internal status */ - uint8_t status; + uint32_t status; #define ROUTE_ENTRY_REMOVED 0x1 /* to simplify NHT logic when NHs change, instead of doing a NH by NH cmp */ #define ROUTE_ENTRY_NEXTHOPS_CHANGED 0x2 +/* The Route Entry has changed */ #define ROUTE_ENTRY_CHANGED 0x4 +/* The Label has changed on the Route entry */ #define ROUTE_ENTRY_LABELS_CHANGED 0x8 +/* Route is queued for Installation into the Data Plane */ +#define ROUTE_ENTRY_QUEUED 0x10 +/* Route is installed into the Data Plane */ +#define ROUTE_ENTRY_INSTALLED 0x20 +/* Route has Failed installation into the Data Plane in some manner */ +#define ROUTE_ENTRY_FAILED 0x40 /* Nexthop information. */ uint8_t nexthop_num; diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index faa0eb90e4..15f9da0cba 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1702,10 +1702,11 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS) int i; afi_t afi; - for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (i = 0; i < ZEBRA_ROUTE_MAX; i++) vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf)); - vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf)); + vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf)); + } vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf)); vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf)); } diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index ba0f1b41aa..feede21cd9 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -157,9 +157,9 @@ struct zebra_dplane_provider { /* Flags */ int dp_flags; - dplane_provider_process_fp dp_fp; + int (*dp_fp)(struct zebra_dplane_provider *prov); - dplane_provider_fini_fp dp_fini; + int (*dp_fini)(struct zebra_dplane_provider *prov, bool early_p); _Atomic uint32_t dp_in_counter; _Atomic uint32_t dp_in_queued; @@ -189,7 +189,7 @@ static struct zebra_dplane_globals { pthread_mutex_t dg_mutex; /* Results callback registered by zebra 'core' */ - dplane_results_fp dg_results_cb; + int (*dg_results_cb)(struct dplane_ctx_q *ctxlist); /* Sentinel for beginning of shutdown */ volatile bool dg_is_shutdown; @@ -988,12 +988,14 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed) int dplane_provider_register(const char *name, enum dplane_provider_prio prio, int flags, - dplane_provider_process_fp fp, - dplane_provider_fini_fp fini_fp, - void *data) + int (*fp)(struct zebra_dplane_provider *), + int (*fini_fp)(struct zebra_dplane_provider *, + bool early), + void *data, + struct zebra_dplane_provider **prov_p) { int ret = 0; - struct zebra_dplane_provider *p, *last; + struct zebra_dplane_provider *p = NULL, *last; /* Validate */ if (fp == NULL) { @@ -1054,6 +1056,9 @@ int dplane_provider_register(const char *name, p->dp_name, p->dp_id, p->dp_priority); done: + if (prov_p) + *prov_p = p; + return ret; } @@ -1210,15 +1215,6 @@ int dplane_provider_work_ready(void) } /* - * Zebra registers a results callback with the dataplane system - */ -int dplane_results_register(dplane_results_fp fp) -{ - zdplane_info.dg_results_cb = fp; - return AOK; -} - -/* * Kernel dataplane provider */ @@ -1357,7 +1353,7 @@ static void dplane_provider_init(void) DPLANE_PROV_FLAGS_DEFAULT, kernel_dplane_process_func, NULL, - NULL); + NULL, NULL); if (ret != AOK) zlog_err("Unable to register kernel dplane provider: %d", @@ -1370,7 +1366,7 @@ static void dplane_provider_init(void) DPLANE_PROV_FLAGS_DEFAULT, test_dplane_process_func, test_dplane_shutdown_func, - NULL /* data */); + NULL /* data */, NULL); if (ret != AOK) zlog_err("Unable to register test dplane provider: %d", @@ -1677,27 +1673,20 @@ static int dplane_thread_loop(struct thread *event) counter, error_counter); /* - * TODO -- I'd rather hand lists through the api to zebra main, + * Hand lists through the api to zebra main, * to reduce the number of lock/unlock cycles */ - for (ctx = TAILQ_FIRST(&error_list); ctx; ) { - TAILQ_REMOVE(&error_list, ctx, zd_q_entries); - - /* Call through to zebra main */ - (*zdplane_info.dg_results_cb)(ctx); - ctx = TAILQ_FIRST(&error_list); - } + /* Call through to zebra main */ + (zdplane_info.dg_results_cb)(&error_list); + TAILQ_INIT(&error_list); - for (ctx = TAILQ_FIRST(&work_list); ctx; ) { - TAILQ_REMOVE(&work_list, ctx, zd_q_entries); - /* Call through to zebra main */ - (*zdplane_info.dg_results_cb)(ctx); + /* Call through to zebra main */ + (zdplane_info.dg_results_cb)(&work_list); - ctx = TAILQ_FIRST(&work_list); - } + TAILQ_INIT(&work_list); done: return 0; @@ -1782,7 +1771,8 @@ void zebra_dplane_start(void) /* * Initialize the dataplane module at startup; called by zebra rib_init() */ -void zebra_dplane_init(void) +void zebra_dplane_init(int (*results_fp)(struct dplane_ctx_q *)) { zebra_dplane_init_internal(&zebrad); + zdplane_info.dg_results_cb = results_fp; } diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 1336850510..1c053b85bf 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -250,21 +250,6 @@ enum dplane_provider_prio { DPLANE_PRIO_LAST }; -/* Provider's entry-point for incoming work, called in the context of the - * dataplane pthread. The dataplane pthread enqueues any new work to the - * provider's 'inbound' queue, then calls the callback. The dataplane - * then checks the provider's outbound queue. - */ -typedef int (*dplane_provider_process_fp)(struct zebra_dplane_provider *prov); - -/* Provider's entry-point for shutdown and cleanup. Called with 'early' - * during shutdown, to indicate that the dataplane subsystem is allowing - * work to move through the providers and finish. When called without 'early', - * the provider should release all resources (if it has any allocated). - */ -typedef int (*dplane_provider_fini_fp)(struct zebra_dplane_provider *prov, - bool early); - /* Flags values used during provider registration. */ #define DPLANE_PROV_FLAGS_DEFAULT 0x0 @@ -273,14 +258,30 @@ typedef int (*dplane_provider_fini_fp)(struct zebra_dplane_provider *prov, /* Provider registration: ordering or priority value, callbacks, and optional - * opaque data value. + * opaque data value. If 'prov_p', return the newly-allocated provider object + * on success. + */ + +/* Providers offer an entry-point for incoming work, called in the context of + * the dataplane pthread. The dataplane pthread enqueues any new work to the + * provider's 'inbound' queue, then calls the callback. The dataplane + * then checks the provider's outbound queue for completed work. + */ + +/* Providers offer an entry-point for shutdown and cleanup. This is called + * with 'early' during shutdown, to indicate that the dataplane subsystem + * is allowing work to move through the providers and finish. + * When called without 'early', the provider should release + * all resources (if it has any allocated). */ int dplane_provider_register(const char *name, enum dplane_provider_prio prio, int flags, - dplane_provider_process_fp fp, - dplane_provider_fini_fp fini_fp, - void *data); + int (*fp)(struct zebra_dplane_provider *), + int (*fini_fp)(struct zebra_dplane_provider *, + bool early), + void *data, + struct zebra_dplane_provider **prov_p); /* Accessors for provider attributes */ const char *dplane_provider_get_name(const struct zebra_dplane_provider *prov); @@ -318,20 +319,13 @@ void dplane_provider_enqueue_out_ctx(struct zebra_dplane_provider *prov, struct zebra_dplane_ctx *ctx); /* - * Zebra registers a results callback with the dataplane. The callback is - * called in the dataplane pthread context, so the expectation is that the - * context is queued for the zebra main pthread or that processing - * is very limited. - */ -typedef int (*dplane_results_fp)(struct zebra_dplane_ctx *ctx); - -int dplane_results_register(dplane_results_fp fp); - -/* * Initialize the dataplane modules at zebra startup. This is currently called - * by the rib module. + * by the rib module. Zebra registers a results callback with the dataplane. + * The callback is called in the dataplane pthread context, + * so the expectation is that the contexts are queued for the zebra + * main pthread. */ -void zebra_dplane_init(void); +void zebra_dplane_init(int (*) (struct dplane_ctx_q *)); /* * Start the dataplane pthread. This step needs to be run later than the diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index a4e1022148..ef31fcf45d 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -215,6 +215,12 @@ static int zebra_ns_ready_read(struct thread *t) if (err < 0) return zebra_ns_continue_read(zns_info, stop_retry); + /* check default name is not already set */ + if (strmatch(VRF_DEFAULT_NAME, basename(netnspath))) { + zlog_warn("NS notify : NS %s is already default VRF." + "Cancel VRF Creation", basename(netnspath)); + return zebra_ns_continue_read(zns_info, 1); + } if (zebra_ns_notify_is_default_netns(basename(netnspath))) { zlog_warn( "NS notify : NS %s is default VRF." @@ -266,9 +272,10 @@ static int zebra_ns_notify_read(struct thread *t) break; } - if (event->mask & IN_DELETE) - return zebra_ns_delete(event->name); - + if (event->mask & IN_DELETE) { + zebra_ns_delete(event->name); + continue; + } netnspath = ns_netns_pathname(NULL, event->name); if (!netnspath) continue; @@ -311,6 +318,12 @@ void zebra_ns_notify_parse(void) dent->d_name); continue; } + /* check default name is not already set */ + if (strmatch(VRF_DEFAULT_NAME, basename(dent->d_name))) { + zlog_warn("NS notify : NS %s is already default VRF." + "Cancel VRF Creation", dent->d_name); + continue; + } if (zebra_ns_notify_is_default_netns(dent->d_name)) { zlog_warn( "NS notify : NS %s is default VRF." diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 03987fcb5b..0c743d8678 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -183,7 +183,7 @@ int zebra_ns_final_shutdown(struct ns *ns) return 0; } -int zebra_ns_init(void) +int zebra_ns_init(const char *optional_default_name) { ns_id_t ns_id; ns_id_t ns_id_external; @@ -207,6 +207,10 @@ int zebra_ns_init(void) /* Default NS is activated */ zebra_ns_enable(ns_id_external, (void **)&dzns); + if (optional_default_name) + vrf_set_default_name(optional_default_name, + true); + if (vrf_is_backend_netns()) { ns_add_hook(NS_NEW_HOOK, zebra_ns_new); ns_add_hook(NS_ENABLE_HOOK, zebra_ns_enabled); diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h index d3592f8f30..01af64c17b 100644 --- a/zebra/zebra_ns.h +++ b/zebra/zebra_ns.h @@ -60,7 +60,7 @@ struct zebra_ns { struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id); -int zebra_ns_init(void); +int zebra_ns_init(const char *optional_default_name); int zebra_ns_enable(ns_id_t ns_id, void **info); int zebra_ns_disabled(struct ns *ns); int zebra_ns_early_shutdown(struct ns *ns); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index b7f97ac612..7e4ac1ddd2 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1871,31 +1871,6 @@ static void rib_process_after(struct zebra_dplane_ctx *ctx) dplane_ctx_get_vrf(ctx), dest_str, ctx, dplane_op2str(op), dplane_res2str(status)); - if (op == DPLANE_OP_ROUTE_DELETE) { - /* - * In the delete case, the zebra core datastructs were - * updated (or removed) at the time the delete was issued, - * so we're just notifying the route owner. - */ - if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) { - zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_REMOVED); - - if (zvrf) - zvrf->removals++; - } else { - zsend_route_notify_owner_ctx(ctx, - ZAPI_ROUTE_REMOVE_FAIL); - - zlog_warn("%u:%s: Route Deletion failure", - dplane_ctx_get_vrf(ctx), - prefix2str(dest_pfx, - dest_str, sizeof(dest_str))); - } - - /* Nothing more to do in delete case */ - goto done; - } - /* * Update is a bit of a special case, where we may have both old and new * routes to post-process. @@ -1955,59 +1930,92 @@ static void rib_process_after(struct zebra_dplane_ctx *ctx) goto done; } - if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) { - /* Update zebra nexthop FIB flag for each - * nexthop that was installed. - */ - for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), ctx_nexthop)) { + switch (op) { + case DPLANE_OP_NONE: + break; + case DPLANE_OP_ROUTE_INSTALL: + case DPLANE_OP_ROUTE_UPDATE: + if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) { + /* Update zebra nexthop FIB flag for each + * nexthop that was installed. + */ + for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), + ctx_nexthop)) { - for (ALL_NEXTHOPS(re->ng, nexthop)) { - if (nexthop_same(ctx_nexthop, nexthop)) - break; + for (ALL_NEXTHOPS(re->ng, nexthop)) { + if (nexthop_same(ctx_nexthop, nexthop)) + break; + } + + if (nexthop == NULL) + continue; + + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_RECURSIVE)) + continue; + + if (CHECK_FLAG(ctx_nexthop->flags, + NEXTHOP_FLAG_FIB)) + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + else + UNSET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); } - if (nexthop == NULL) - continue; + if (zvrf) { + zvrf->installs++; + /* Set flag for nexthop tracking processing */ + zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED; + } - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; + /* Redistribute */ + /* + * TODO -- still calling the redist api using the + * route_entries, and there's a corner-case here: + * if there's no client for the 'new' route, a redist + * deleting the 'old' route will be sent. But if the + * 'old' context info was stale, 'old_re' will be + * NULL here and that delete will not be sent. + */ + redistribute_update(dest_pfx, src_pfx, re, old_re); - if (CHECK_FLAG(ctx_nexthop->flags, - NEXTHOP_FLAG_FIB)) - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); - else - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); - } + /* Notify route owner */ + zsend_route_notify_owner(re, dest_pfx, + ZAPI_ROUTE_INSTALLED); - if (zvrf) { - zvrf->installs++; - /* Set flag for nexthop tracking processing */ - zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED; - } + } else { + zsend_route_notify_owner(re, dest_pfx, + ZAPI_ROUTE_FAIL_INSTALL); - /* Redistribute */ - /* TODO -- still calling the redist api using the route_entries, - * and there's a corner-case here: if there's no client - * for the 'new' route, a redist deleting the 'old' route - * will be sent. But if the 'old' context info was stale, - * 'old_re' will be NULL here and that delete will not be sent. + zlog_warn("%u:%s: Route install failed", + dplane_ctx_get_vrf(ctx), + prefix2str(dest_pfx, + dest_str, sizeof(dest_str))); + } + break; + case DPLANE_OP_ROUTE_DELETE: + /* + * In the delete case, the zebra core datastructs were + * updated (or removed) at the time the delete was issued, + * so we're just notifying the route owner. */ - redistribute_update(dest_pfx, src_pfx, re, old_re); - - /* Notify route owner */ - zsend_route_notify_owner(re, - dest_pfx, ZAPI_ROUTE_INSTALLED); + if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) { + zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_REMOVED); - } else { - zsend_route_notify_owner(re, dest_pfx, - ZAPI_ROUTE_FAIL_INSTALL); + if (zvrf) + zvrf->removals++; + } else { + zsend_route_notify_owner_ctx(ctx, + ZAPI_ROUTE_REMOVE_FAIL); - zlog_warn("%u:%s: Route install failed", - dplane_ctx_get_vrf(ctx), - prefix2str(dest_pfx, - dest_str, sizeof(dest_str))); + zlog_warn("%u:%s: Route Deletion failure", + dplane_ctx_get_vrf(ctx), + prefix2str(dest_pfx, + dest_str, sizeof(dest_str))); + } + break; } - done: /* Return context to dataplane module */ @@ -2144,43 +2152,66 @@ static wq_item_status meta_queue_process(struct work_queue *dummy, void *data) return mq->size ? WQ_REQUEUE : WQ_SUCCESS; } -/* Look into the RN and queue it into one or more priority queues, - * increasing the size for each data push done. + +/* + * Look into the RN and queue it into the highest priority queue + * at this point in time for processing. + * + * We will enqueue a route node only once per invocation. + * + * There are two possibilities here that should be kept in mind. + * If the original invocation has not been pulled off for processing + * yet, A subsuquent invocation can have a route entry with a better + * meta queue index value and we can have a situation where + * we might have the same node enqueued 2 times. Not necessarily + * an optimal situation but it should be ok. + * + * The other possibility is that the original invocation has not + * been pulled off for processing yet, A subsusquent invocation + * doesn't have a route_entry with a better meta-queue and the + * original metaqueue index value will win and we'll end up with + * the route node enqueued once. */ static void rib_meta_queue_add(struct meta_queue *mq, struct route_node *rn) { - struct route_entry *re; + struct route_entry *re = NULL, *curr_re = NULL; + uint8_t qindex = MQ_SIZE, curr_qindex = MQ_SIZE; + struct zebra_vrf *zvrf; - RNODE_FOREACH_RE (rn, re) { - uint8_t qindex = route_info[re->type].meta_q_map; - struct zebra_vrf *zvrf; + RNODE_FOREACH_RE (rn, curr_re) { + curr_qindex = route_info[curr_re->type].meta_q_map; - /* Invariant: at this point we always have rn->info set. */ - if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags, - RIB_ROUTE_QUEUED(qindex))) { - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rnode_debug( - rn, re->vrf_id, - "rn %p is already queued in sub-queue %u", - (void *)rn, qindex); - continue; + if (curr_qindex <= qindex) { + re = curr_re; + qindex = curr_qindex; } + } - SET_FLAG(rib_dest_from_rnode(rn)->flags, - RIB_ROUTE_QUEUED(qindex)); - listnode_add(mq->subq[qindex], rn); - route_lock_node(rn); - mq->size++; + if (!re) + return; + /* Invariant: at this point we always have rn->info set. */ + if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags, + RIB_ROUTE_QUEUED(qindex))) { if (IS_ZEBRA_DEBUG_RIB_DETAILED) rnode_debug(rn, re->vrf_id, - "queued rn %p into sub-queue %u", + "rn %p is already queued in sub-queue %u", (void *)rn, qindex); - - zvrf = zebra_vrf_lookup_by_id(re->vrf_id); - if (zvrf) - zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED; + return; } + + SET_FLAG(rib_dest_from_rnode(rn)->flags, RIB_ROUTE_QUEUED(qindex)); + listnode_add(mq->subq[qindex], rn); + route_lock_node(rn); + mq->size++; + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + rnode_debug(rn, re->vrf_id, "queued rn %p into sub-queue %u", + (void *)rn, qindex); + + zvrf = zebra_vrf_lookup_by_id(re->vrf_id); + if (zvrf) + zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED; } /* Add route_node to work queue and schedule processing */ @@ -3165,21 +3196,34 @@ void rib_close_table(struct route_table *table) static int rib_process_dplane_results(struct thread *thread) { struct zebra_dplane_ctx *ctx; + struct dplane_ctx_q ctxlist; + + /* Dequeue a list of completed updates with one lock/unlock cycle */ do { + TAILQ_INIT(&ctxlist); + /* Take lock controlling queue of results */ pthread_mutex_lock(&dplane_mutex); { /* Dequeue context block */ - ctx = dplane_ctx_dequeue(&rib_dplane_q); + dplane_ctx_list_append(&ctxlist, &rib_dplane_q); } pthread_mutex_unlock(&dplane_mutex); - if (ctx) - rib_process_after(ctx); - else + /* Dequeue context block */ + ctx = dplane_ctx_dequeue(&ctxlist); + + /* If we've emptied the results queue, we're done */ + if (ctx == NULL) break; + while (ctx) { + rib_process_after(ctx); + + ctx = dplane_ctx_dequeue(&ctxlist); + } + } while (1); /* Check for nexthop tracking processing after finishing with results */ @@ -3193,17 +3237,17 @@ static int rib_process_dplane_results(struct thread *thread) * the dataplane pthread. We enqueue the results here for processing by * the main thread later. */ -static int rib_dplane_results(struct zebra_dplane_ctx *ctx) +static int rib_dplane_results(struct dplane_ctx_q *ctxlist) { /* Take lock controlling queue of results */ pthread_mutex_lock(&dplane_mutex); { - /* Enqueue context block */ - dplane_ctx_enqueue_tail(&rib_dplane_q, ctx); + /* Enqueue context blocks */ + dplane_ctx_list_append(&rib_dplane_q, ctxlist); } pthread_mutex_unlock(&dplane_mutex); - /* Ensure event is signalled to zebra main thread */ + /* Ensure event is signalled to zebra main pthread */ thread_add_event(zebrad.master, rib_process_dplane_results, NULL, 0, &t_dplane); @@ -3218,8 +3262,7 @@ void rib_init(void) /* Init dataplane, and register for results */ pthread_mutex_init(&dplane_mutex, NULL); TAILQ_INIT(&rib_dplane_q); - zebra_dplane_init(); - dplane_results_register(rib_dplane_results); + zebra_dplane_init(rib_dplane_results); } /* diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c index ae18a0d290..f0cc8d4fd7 100644 --- a/zebra/zebra_router.c +++ b/zebra/zebra_router.c @@ -106,7 +106,7 @@ struct route_table *zebra_router_get_table(struct zebra_vrf *zvrf, info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info)); info->zvrf = zvrf; info->afi = afi; - info->safi = SAFI_UNICAST; + info->safi = safi; route_table_set_info(zrt->table, info); zrt->table->cleanup = zebra_rtable_node_cleanup; @@ -127,6 +127,25 @@ unsigned long zebra_router_score_proto(uint8_t proto, unsigned short instance) return cnt; } +void zebra_router_show_table_summary(struct vty *vty) +{ + struct zebra_router_table *zrt; + + vty_out(vty, + "VRF NS ID VRF ID AFI SAFI Table Count\n"); + vty_out(vty, + "---------------------------------------------------------------------------\n"); + RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) { + rib_table_info_t *info = route_table_get_info(zrt->table); + + vty_out(vty, "%-16s%5d %9d %7s %15s %8d %10lu\n", info->zvrf->vrf->name, + zrt->ns_id, info->zvrf->vrf->vrf_id, + afi2str(zrt->afi), safi2str(zrt->safi), + zrt->tableid, + zrt->table->count); + } +} + void zebra_router_sweep_route(void) { struct zebra_router_table *zrt; diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h index d6b8b66087..1e0788d1ba 100644 --- a/zebra/zebra_router.h +++ b/zebra/zebra_router.h @@ -81,4 +81,6 @@ extern int zebra_router_config_write(struct vty *vty); extern unsigned long zebra_router_score_proto(uint8_t proto, unsigned short instance); extern void zebra_router_sweep_route(void); + +extern void zebra_router_show_table_summary(struct vty *vty); #endif diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 38b8b43d73..f1458cb138 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -370,22 +370,10 @@ static void zebra_rnhtable_node_cleanup(struct route_table *table, static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi, safi_t safi) { - rib_table_info_t *info; - struct route_table *table; - assert(!zvrf->table[afi][safi]); - table = zebra_router_get_table(zvrf, zvrf->table_id, afi, safi); - - table->cleanup = zebra_rtable_node_cleanup; - zvrf->table[afi][safi] = table; - - XFREE(MTYPE_RIB_TABLE_INFO, table->info); - info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info)); - info->zvrf = zvrf; - info->afi = afi; - info->safi = safi; - route_table_set_info(table, info); + zvrf->table[afi][safi] = + zebra_router_get_table(zvrf, zvrf->table_id, afi, safi); } /* Allocate new zebra VRF. */ diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 8b06d2ae11..b18f0e943c 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -2857,6 +2857,20 @@ DEFUN (no_zebra_dplane_queue_limit, return CMD_SUCCESS; } +DEFUN (zebra_show_routing_tables_summary, + zebra_show_routing_tables_summary_cmd, + "show zebra router table summary", + SHOW_STR + ZEBRA_STR + "The Zebra Router Information\n" + "Table Information about this Zebra Router\n" + "Summary Information\n") +{ + zebra_router_show_table_summary(vty); + + return CMD_SUCCESS; +} + /* Table configuration write function. */ static int config_write_table(struct vty *vty) { @@ -3000,4 +3014,6 @@ void zebra_vty_init(void) install_element(VIEW_NODE, &show_dataplane_providers_cmd); install_element(CONFIG_NODE, &zebra_dplane_queue_limit_cmd); install_element(CONFIG_NODE, &no_zebra_dplane_queue_limit_cmd); + + install_element(VIEW_NODE, &zebra_show_routing_tables_summary_cmd); } diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index b55ca60c00..86a7812780 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -687,10 +687,11 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json) struct zebra_vrf *zvrf = NULL; struct timeval detect_start_time = {0, 0}; - zvrf = zebra_vrf_lookup_by_id(n->zvni->vrf_id); + zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); if (!zvrf) return; + zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); ipaddr2str(&n->ip, buf2, sizeof(buf2)); prefix_mac2str(&n->emac, buf1, sizeof(buf1)); type_str = CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) ? @@ -1135,7 +1136,7 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json) struct zebra_vrf *zvrf; struct timeval detect_start_time = {0, 0}; - zvrf = zebra_vrf_lookup_by_id(mac->zvni->vrf_id); + zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); vty = (struct vty *)ctxt; prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)); @@ -2296,7 +2297,7 @@ static void zvni_process_neigh_on_local_mac_change(zebra_vni_t *zvni, struct zebra_vrf *zvrf = NULL; char buf[ETHER_ADDR_STRLEN]; - zvrf = vrf_info_lookup(zvni->vrf_id); + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug("Processing neighbors on local MAC %s %s, VNI %u", @@ -2891,7 +2892,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, } } - zvrf = vrf_info_lookup(zvni->vrf_id); + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); if (!zvrf) return -1; @@ -6907,8 +6908,8 @@ void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS) if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "%s: duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u", - __PRETTY_FUNCTION__, + "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u", + vrf_id_to_name(zvrf->vrf->vrf_id), zvrf->dup_addr_detect ? "enable" : "disable", zvrf->dad_max_moves, zvrf->dad_time, @@ -8904,16 +8905,16 @@ static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t) nbr = THREAD_ARG(t); /* since this is asynchronous we need sanity checks*/ - zvrf = vrf_info_lookup(nbr->zvni->vrf_id); - if (!zvrf) + nbr = zvni_neigh_lookup(zvni, &nbr->ip); + if (!nbr) return 0; zvni = zvni_lookup(nbr->zvni->vni); if (!zvni) return 0; - nbr = zvni_neigh_lookup(zvni, &nbr->ip); - if (!nbr) + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + if (!zvrf) return 0; if (IS_ZEBRA_DEBUG_VXLAN) @@ -8954,16 +8955,16 @@ static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t) mac = THREAD_ARG(t); /* since this is asynchronous we need sanity checks*/ - zvrf = vrf_info_lookup(mac->zvni->vrf_id); - if (!zvrf) + mac = zvni_mac_lookup(zvni, &mac->macaddr); + if (!mac) return 0; zvni = zvni_lookup(mac->zvni->vni); if (!zvni) return 0; - mac = zvni_mac_lookup(zvni, &mac->macaddr); - if (!mac) + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + if (!zvrf) return 0; if (IS_ZEBRA_DEBUG_VXLAN) diff --git a/zebra/zserv.c b/zebra/zserv.c index a48505a514..502186d226 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -616,11 +616,12 @@ static void zserv_client_free(struct zserv *client) pthread_mutex_destroy(&client->ibuf_mtx); /* Free bitmaps. */ - for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) + for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) { for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) vrf_bitmap_free(client->redist[afi][i]); - vrf_bitmap_free(client->redist_default); + vrf_bitmap_free(client->redist_default[afi]); + } vrf_bitmap_free(client->ifinfo); vrf_bitmap_free(client->ridinfo); @@ -700,10 +701,11 @@ static struct zserv *zserv_client_create(int sock) memory_order_relaxed); /* Initialize flags */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (i = 0; i < ZEBRA_ROUTE_MAX; i++) client->redist[afi][i] = vrf_bitmap_init(); - client->redist_default = vrf_bitmap_init(); + client->redist_default[afi] = vrf_bitmap_init(); + } client->ifinfo = vrf_bitmap_init(); client->ridinfo = vrf_bitmap_init(); diff --git a/zebra/zserv.h b/zebra/zserv.h index f0b8934ae1..041485cdc2 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -87,7 +87,7 @@ struct zserv { vrf_bitmap_t redist[AFI_MAX][ZEBRA_ROUTE_MAX]; /* Redistribute default route flag. */ - vrf_bitmap_t redist_default; + vrf_bitmap_t redist_default[AFI_MAX]; /* Interface information. */ vrf_bitmap_t ifinfo; |
