diff options
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/ioctl.c | 25 | ||||
| -rw-r--r-- | zebra/kernel_netlink.c | 125 | ||||
| -rw-r--r-- | zebra/kernel_socket.c | 14 | ||||
| -rw-r--r-- | zebra/rt.h | 4 | ||||
| -rw-r--r-- | zebra/zebra_fpm_netlink.c | 5 | ||||
| -rw-r--r-- | zebra/zebra_router.c | 6 |
6 files changed, 124 insertions, 55 deletions
diff --git a/zebra/ioctl.c b/zebra/ioctl.c index 8b30eea9f1..9b6aaf1d85 100644 --- a/zebra/ioctl.c +++ b/zebra/ioctl.c @@ -410,11 +410,14 @@ int if_unset_prefix_ctx(const struct zebra_dplane_ctx *ctx) void if_get_flags(struct interface *ifp) { int ret; - struct ifreq ifreq; + struct ifreq ifreqflags; + struct ifreq ifreqdata; - ifreq_set_name(&ifreq, ifp); + ifreq_set_name(&ifreqflags, ifp); + ifreq_set_name(&ifreqdata, ifp); - ret = vrf_if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreq, ifp->vrf->vrf_id); + ret = vrf_if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreqflags, + ifp->vrf->vrf_id); if (ret < 0) { flog_err_sys(EC_LIB_SYSTEM_CALL, "vrf_if_ioctl(SIOCGIFFLAGS %s) failed: %s", @@ -448,8 +451,8 @@ void if_get_flags(struct interface *ifp) struct if_data ifd = {.ifi_link_state = 0}; struct if_data *ifdata = &ifd; - ifreq.ifr_data = (caddr_t)ifdata; - ret = vrf_if_ioctl(SIOCGIFDATA, (caddr_t)&ifreq, ifp->vrf->vrf_id); + ifreqdata.ifr_data = (caddr_t)ifdata; + ret = vrf_if_ioctl(SIOCGIFDATA, (caddr_t)&ifreqdata, ifp->vrf->vrf_id); #endif if (ret == -1) @@ -459,12 +462,12 @@ void if_get_flags(struct interface *ifp) safe_strerror(errno)); else { if (ifdata->ifi_link_state >= LINK_STATE_UP) - SET_FLAG(ifreq.ifr_flags, IFF_RUNNING); + SET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING); else if (ifdata->ifi_link_state == LINK_STATE_UNKNOWN) /* BSD traditionally treats UNKNOWN as UP */ - SET_FLAG(ifreq.ifr_flags, IFF_RUNNING); + SET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING); else - UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING); + UNSET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING); } #elif defined(HAVE_BSD_LINK_DETECT) @@ -489,14 +492,14 @@ void if_get_flags(struct interface *ifp) ifp->name, safe_strerror(errno)); } else if (ifmr.ifm_status & IFM_AVALID) { /* media state is valid */ if (ifmr.ifm_status & IFM_ACTIVE) /* media is active */ - SET_FLAG(ifreq.ifr_flags, IFF_RUNNING); + SET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING); else - UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING); + UNSET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING); } #endif /* HAVE_BSD_LINK_DETECT */ out: - if_flags_update(ifp, (ifreq.ifr_flags & 0x0000ffff)); + if_flags_update(ifp, (ifreqflags.ifr_flags & 0x0000ffff)); } /* Set interface flags */ diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index ca83a42685..84c15a2a92 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -159,7 +159,17 @@ extern struct zebra_privs_t zserv_privs; DEFINE_MTYPE_STATIC(ZEBRA, NL_BUF, "Zebra Netlink buffers"); -struct hash *nlsock_hash; +/* Hashtable and mutex to allow lookup of nlsock structs by socket/fd value. + * We have both the main and dplane pthreads using these structs, so we have + * to protect the hash with a lock. + */ +static struct hash *nlsock_hash; +pthread_mutex_t nlsock_mutex; + +/* Lock and unlock wrappers for nlsock hash */ +#define NLSOCK_LOCK() pthread_mutex_lock(&nlsock_mutex) +#define NLSOCK_UNLOCK() pthread_mutex_unlock(&nlsock_mutex) + size_t nl_batch_tx_bufsize; char *nl_batch_tx_buf; @@ -1513,11 +1523,31 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list) struct nlsock *kernel_netlink_nlsock_lookup(int sock) { - struct nlsock lookup; + struct nlsock lookup, *retval; lookup.sock = sock; - return hash_lookup(nlsock_hash, &lookup); + NLSOCK_LOCK(); + retval = hash_lookup(nlsock_hash, &lookup); + NLSOCK_UNLOCK(); + + return retval; +} + +/* Insert nlsock entry into hash */ +static void kernel_netlink_nlsock_insert(struct nlsock *nls) +{ + NLSOCK_LOCK(); + (void)hash_get(nlsock_hash, nls, hash_alloc_intern); + NLSOCK_UNLOCK(); +} + +/* Remove nlsock entry from hash */ +static void kernel_netlink_nlsock_remove(struct nlsock *nls) +{ + NLSOCK_LOCK(); + (void)hash_release(nlsock_hash, nls); + NLSOCK_UNLOCK(); } static uint32_t kernel_netlink_nlsock_key(const void *arg) @@ -1547,11 +1577,6 @@ void kernel_init(struct zebra_ns *zns) int one, ret; #endif - if (!nlsock_hash) - nlsock_hash = hash_create_size(8, kernel_netlink_nlsock_key, - kernel_netlink_nlsock_hash_equal, - "Netlink Socket Hash"); - /* * Initialize netlink sockets * @@ -1584,7 +1609,8 @@ void kernel_init(struct zebra_ns *zns) zns->netlink.name); exit(-1); } - (void)hash_get(nlsock_hash, &zns->netlink, hash_alloc_intern); + + kernel_netlink_nlsock_insert(&zns->netlink); snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name), "netlink-cmd (NS %u)", zns->ns_id); @@ -1594,7 +1620,8 @@ void kernel_init(struct zebra_ns *zns) zns->netlink_cmd.name); exit(-1); } - (void)hash_get(nlsock_hash, &zns->netlink_cmd, hash_alloc_intern); + + kernel_netlink_nlsock_insert(&zns->netlink_cmd); /* Outbound socket for dplane programming of the host OS. */ snprintf(zns->netlink_dplane_out.name, @@ -1606,8 +1633,8 @@ void kernel_init(struct zebra_ns *zns) zns->netlink_dplane_out.name); exit(-1); } - (void)hash_get(nlsock_hash, &zns->netlink_dplane_out, - hash_alloc_intern); + + kernel_netlink_nlsock_insert(&zns->netlink_dplane_out); /* Inbound socket for OS events coming to the dplane. */ snprintf(zns->netlink_dplane_in.name, @@ -1620,7 +1647,8 @@ void kernel_init(struct zebra_ns *zns) zns->netlink_dplane_in.name); exit(-1); } - (void)hash_get(nlsock_hash, &zns->netlink_dplane_in, hash_alloc_intern); + + kernel_netlink_nlsock_insert(&zns->netlink_dplane_in); /* * SOL_NETLINK is not available on all platforms yet @@ -1706,47 +1734,56 @@ void kernel_init(struct zebra_ns *zns) rt_netlink_init(); } +/* Helper to clean up an nlsock */ +static void kernel_nlsock_fini(struct nlsock *nls) +{ + if (nls && nls->sock >= 0) { + kernel_netlink_nlsock_remove(nls); + close(nls->sock); + nls->sock = -1; + XFREE(MTYPE_NL_BUF, nls->buf); + nls->buflen = 0; + } +} + void kernel_terminate(struct zebra_ns *zns, bool complete) { thread_cancel(&zns->t_netlink); - if (zns->netlink.sock >= 0) { - hash_release(nlsock_hash, &zns->netlink); - close(zns->netlink.sock); - zns->netlink.sock = -1; - XFREE(MTYPE_NL_BUF, zns->netlink.buf); - zns->netlink.buflen = 0; - } + kernel_nlsock_fini(&zns->netlink); - if (zns->netlink_cmd.sock >= 0) { - hash_release(nlsock_hash, &zns->netlink_cmd); - close(zns->netlink_cmd.sock); - zns->netlink_cmd.sock = -1; - XFREE(MTYPE_NL_BUF, zns->netlink_cmd.buf); - zns->netlink_cmd.buflen = 0; - } + kernel_nlsock_fini(&zns->netlink_cmd); - if (zns->netlink_dplane_in.sock >= 0) { - hash_release(nlsock_hash, &zns->netlink_dplane_in); - close(zns->netlink_dplane_in.sock); - zns->netlink_dplane_in.sock = -1; - XFREE(MTYPE_NL_BUF, zns->netlink_dplane_in.buf); - zns->netlink_dplane_in.buflen = 0; - } + kernel_nlsock_fini(&zns->netlink_dplane_in); /* During zebra shutdown, we need to leave the dataplane socket * around until all work is done. */ - if (complete) { - if (zns->netlink_dplane_out.sock >= 0) { - hash_release(nlsock_hash, &zns->netlink_dplane_out); - close(zns->netlink_dplane_out.sock); - zns->netlink_dplane_out.sock = -1; - XFREE(MTYPE_NL_BUF, zns->netlink_dplane_out.buf); - zns->netlink_dplane_out.buflen = 0; - } + if (complete) + kernel_nlsock_fini(&zns->netlink_dplane_out); +} - hash_free(nlsock_hash); - } +/* + * Global init for platform-/OS-specific things + */ +void kernel_router_init(void) +{ + /* Init nlsock hash and lock */ + pthread_mutex_init(&nlsock_mutex, NULL); + nlsock_hash = hash_create_size(8, kernel_netlink_nlsock_key, + kernel_netlink_nlsock_hash_equal, + "Netlink Socket Hash"); +} + +/* + * Global deinit for platform-/OS-specific things + */ +void kernel_router_terminate(void) +{ + pthread_mutex_destroy(&nlsock_mutex); + + hash_free(nlsock_hash); + nlsock_hash = NULL; } + #endif /* HAVE_NETLINK */ diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 3c9d203a0b..b9228072e5 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -1460,6 +1460,20 @@ void kernel_terminate(struct zebra_ns *zns, bool complete) } /* + * Global init for platform-/OS-specific things + */ +void kernel_router_init(void) +{ +} + +/* + * Global deinit for platform-/OS-specific things + */ +void kernel_router_terminate(void) +{ +} + +/* * Called by the dplane pthread to read incoming OS messages and dispatch them. */ int kernel_dplane_read(struct zebra_dplane_info *info) diff --git a/zebra/rt.h b/zebra/rt.h index 90148d2c0d..5e626928d9 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -78,6 +78,10 @@ extern int kernel_interface_set_master(struct interface *master, extern int mpls_kernel_init(void); +/* Global init and deinit for platform-/OS-specific things */ +void kernel_router_init(void); +void kernel_router_terminate(void); + extern uint32_t kernel_get_speed(struct interface *ifp, int *error); extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute); diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index 168e36ac9b..ec22c5dd48 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -116,6 +116,8 @@ struct fpm_nh_encap_info_t { * data structures for convenience. */ struct netlink_nh_info { + /* Weight of the nexthop ( for unequal cost ECMP ) */ + uint8_t weight; uint32_t if_index; union g_addr *gateway; @@ -179,6 +181,7 @@ static int netlink_route_info_add_nh(struct netlink_route_info *ri, nhi.recursive = nexthop->rparent ? 1 : 0; nhi.type = nexthop->type; nhi.if_index = nexthop->ifindex; + nhi.weight = nexthop->weight; if (nexthop->type == NEXTHOP_TYPE_IPV4 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { @@ -480,6 +483,8 @@ static int netlink_route_info_encode(struct netlink_route_info *ri, rtnh->rtnh_ifindex = nhi->if_index; } + rtnh->rtnh_hops = nhi->weight; + encap = nhi->encap_info.encap_type; switch (encap) { case FPM_NH_ENCAP_NONE: diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c index 92a3b9424b..6b4a7543cd 100644 --- a/zebra/zebra_router.c +++ b/zebra/zebra_router.c @@ -262,6 +262,9 @@ void zebra_router_terminate(void) #ifdef HAVE_SCRIPTING zebra_script_destroy(); #endif + + /* OS-specific deinit */ + kernel_router_terminate(); } bool zebra_router_notify_on_ack(void) @@ -307,4 +310,7 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack) #ifdef HAVE_SCRIPTING zebra_script_init(); #endif + + /* OS-specific init */ + kernel_router_init(); } |
