From 936ebf0a2dd70f59bf846bad9f1a0fe04c87e37e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 27 Jan 2017 13:33:08 -0500 Subject: [PATCH] zebra: Add knowledge of whether or not we are acting under startup conditions The reading if unicast routes from the kernel acts subtly differently between reading in the routes from the kernel on startup and reading a new route or getting a response for a route. Add startup flag(currently ignored) so that we can start consolidating the functionality. Signed-off-by: Donald Sharp --- zebra/if_netlink.c | 14 +++++----- zebra/if_netlink.h | 4 +-- zebra/kernel_netlink.c | 59 +++++++++++++++++++++++++++++------------- zebra/kernel_netlink.h | 11 ++++---- zebra/rt_netlink.c | 24 ++++++++--------- zebra/rt_netlink.h | 2 +- 6 files changed, 69 insertions(+), 45 deletions(-) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 660fad6530..65fc8789f9 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -302,7 +302,7 @@ netlink_vrf_change (struct nlmsghdr *h, struct rtattr *tb, const char *name) during bootstrap. */ static int netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) + ns_id_t ns_id, int startup) { int len; struct ifinfomsg *ifi; @@ -403,7 +403,7 @@ interface_lookup_netlink (struct zebra_ns *zns) ret = netlink_request (AF_PACKET, RTM_GETLINK, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0); + ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0, 1); if (ret < 0) return ret; @@ -411,7 +411,7 @@ interface_lookup_netlink (struct zebra_ns *zns) ret = netlink_request (AF_INET, RTM_GETADDR, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0); + ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1); if (ret < 0) return ret; @@ -419,7 +419,7 @@ interface_lookup_netlink (struct zebra_ns *zns) ret = netlink_request (AF_INET6, RTM_GETADDR, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0); + ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1); if (ret < 0) return ret; @@ -475,7 +475,7 @@ netlink_address (int cmd, int family, struct interface *ifp, addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label, strlen (ifc->label) + 1); - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns); + return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); } int @@ -492,7 +492,7 @@ kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc) int netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) + ns_id_t ns_id, int startup) { int len; struct ifaddrmsg *ifa; @@ -630,7 +630,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, int netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) + ns_id_t ns_id, int startup) { int len; struct ifinfomsg *ifi; diff --git a/zebra/if_netlink.h b/zebra/if_netlink.h index aac67916c0..6fa39ccab2 100644 --- a/zebra/if_netlink.h +++ b/zebra/if_netlink.h @@ -25,9 +25,9 @@ #ifdef HAVE_NETLINK extern int netlink_interface_addr (struct sockaddr_nl *snl, - struct nlmsghdr *h, ns_id_t ns_id); + struct nlmsghdr *h, ns_id_t ns_id, int startup); extern int netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id); + ns_id_t ns_id, int startup); extern int interface_lookup_netlink (struct zebra_ns *zns); #endif /* HAVE_NETLINK */ diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 058d14481e..c9c2d90eac 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -125,7 +125,7 @@ extern struct zebra_privs_t zserv_privs; int netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) + ns_id_t ns_id, int startup) { zlog_warn ("netlink_talk: ignoring message type 0x%04x NS %u", h->nlmsg_type, ns_id); @@ -239,7 +239,7 @@ netlink_socket (struct nlsock *nl, unsigned long groups, ns_id_t ns_id) static int netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) + ns_id_t ns_id, int startup) { /* JF: Ignore messages that aren't from the kernel */ if ( snl->nl_pid != 0 ) @@ -251,22 +251,22 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h, switch (h->nlmsg_type) { case RTM_NEWROUTE: - return netlink_route_change (snl, h, ns_id); + return netlink_route_change (snl, h, ns_id, startup); break; case RTM_DELROUTE: - return netlink_route_change (snl, h, ns_id); + return netlink_route_change (snl, h, ns_id, startup); break; case RTM_NEWLINK: - return netlink_link_change (snl, h, ns_id); + return netlink_link_change (snl, h, ns_id, startup); break; case RTM_DELLINK: - return netlink_link_change (snl, h, ns_id); + return netlink_link_change (snl, h, ns_id, startup); break; case RTM_NEWADDR: - return netlink_interface_addr (snl, h, ns_id); + return netlink_interface_addr (snl, h, ns_id, startup); break; case RTM_DELADDR: - return netlink_interface_addr (snl, h, ns_id); + return netlink_interface_addr (snl, h, ns_id, startup); break; default: zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type, @@ -280,7 +280,7 @@ static int kernel_read (struct thread *thread) { struct zebra_ns *zns = (struct zebra_ns *)THREAD_ARG (thread); - netlink_parse_info (netlink_information_fetch, &zns->netlink, zns, 5); + netlink_parse_info (netlink_information_fetch, &zns->netlink, zns, 5, 0); zns->t_netlink = thread_add_read (zebrad.master, kernel_read, zns, zns->netlink.sock); @@ -444,12 +444,23 @@ nl_rttype_to_str (u_char rttype) return lookup (rttype_str, rttype); } -/* Receive message from netlink interface and pass those information - to the given function. */ +/* + * netlink_parse_info + * + * Receive message from netlink interface and pass those information + * to the given function. + * + * filter -> Function to call to read the results + * nl -> netlink socket information + * zns -> The zebra namespace data + * count -> How many we should read in, 0 means as much as possible + * startup -> Are we reading in under startup conditions? passed to + * the filter. + */ int netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, - ns_id_t), - struct nlsock *nl, struct zebra_ns *zns, int count) + ns_id_t, int), + struct nlsock *nl, struct zebra_ns *zns, int count, int startup) { int status; int ret = 0; @@ -613,7 +624,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, continue; } - error = (*filter) (&snl, h, zns->ns_id); + error = (*filter) (&snl, h, zns->ns_id, startup); if (error < 0) { zlog (NULL, LOG_ERR, "%s filter function error", nl->name); @@ -637,11 +648,23 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, return ret; } -/* sendmsg() to netlink socket then recvmsg(). */ +/* + * netlink_talk + * + * sendmsg() to netlink socket then recvmsg(). + * Calls netlink_parse_info to parse returned data + * + * filter -> The filter to read final results from kernel + * nlmsghdr -> The data to send to the kernel + * nl -> The netlink socket information + * zns -> The zebra namespace information + * startup -> Are we reading in under startup conditions + * This is passed through eventually to filter. + */ int netlink_talk (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, - ns_id_t), - struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns) + ns_id_t, int startup), + struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns, int startup) { int status; struct sockaddr_nl snl; @@ -697,7 +720,7 @@ netlink_talk (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, * Get reply from netlink socket. * The reply should either be an acknowlegement or an error. */ - return netlink_parse_info (filter, nl, zns, 0); + return netlink_parse_info (filter, nl, zns, 0, startup); } /* Get type specified information from netlink. */ diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index f17f1380c2..adbcf71f63 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -44,14 +44,15 @@ extern const char * nl_family_to_str (u_char family); extern const char * nl_rttype_to_str (u_char rttype); extern int netlink_parse_info (int (*filter) (struct sockaddr_nl *, - struct nlmsghdr *, ns_id_t), struct nlsock *nl, - struct zebra_ns *zns, int count); + struct nlmsghdr *, ns_id_t, int), + struct nlsock *nl, struct zebra_ns *zns, + int count, int startup); extern int netlink_talk_filter (struct sockaddr_nl *, struct nlmsghdr *, - ns_id_t); + ns_id_t, int startup); extern int netlink_talk (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, - ns_id_t), + ns_id_t, int startup), struct nlmsghdr *n, struct nlsock *nl, - struct zebra_ns *zns); + struct zebra_ns *zns, int startup); extern int netlink_request (int family, int type, struct nlsock *nl); #endif /* HAVE_NETLINK */ diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index d88dc05b28..7eacec6958 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -127,7 +127,7 @@ vrf_lookup_by_table (u_int32_t table_id) /* Looking up routing table by netlink interface. */ static int netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) + ns_id_t ns_id, int startup) { int len; struct rtmsg *rtm; @@ -321,7 +321,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, /* Routing information change from the kernel. */ static int netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) + ns_id_t ns_id, int startup) { int len; struct rtmsg *rtm; @@ -545,7 +545,7 @@ static struct mcast_route_data *mroute = NULL; static int netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) + ns_id_t ns_id, int startup) { int len; struct rtmsg *rtm; @@ -629,7 +629,7 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) + ns_id_t ns_id, int startup) { int len; vrf_id_t vrf_id = ns_id; @@ -665,10 +665,10 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, switch (rtm->rtm_type) { case RTN_UNICAST: - netlink_route_change_read_unicast (snl, h, ns_id); + netlink_route_change_read_unicast (snl, h, ns_id, startup); break; case RTN_MULTICAST: - netlink_route_change_read_multicast (snl, h, ns_id); + netlink_route_change_read_multicast (snl, h, ns_id, startup); break; default: return 0; @@ -689,7 +689,7 @@ netlink_route_read (struct zebra_ns *zns) ret = netlink_request (AF_INET, RTM_GETROUTE, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_routing_table, &zns->netlink_cmd, zns, 0); + ret = netlink_parse_info (netlink_routing_table, &zns->netlink_cmd, zns, 0, 1); if (ret < 0) return ret; @@ -697,7 +697,7 @@ netlink_route_read (struct zebra_ns *zns) ret = netlink_request (AF_INET6, RTM_GETROUTE, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_routing_table, &zns->netlink_cmd, zns, 0); + ret = netlink_parse_info (netlink_routing_table, &zns->netlink_cmd, zns, 0, 1); if (ret < 0) return ret; @@ -1244,7 +1244,7 @@ netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns); + return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); } /* Routing table change via netlink interface. */ @@ -1542,7 +1542,7 @@ skip: snl.nl_family = AF_NETLINK; /* Talk to netlink socket. */ - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns); + return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); } int @@ -1572,7 +1572,7 @@ kernel_get_ipmr_sg_stats (void *in) addattr_l (&req.n, sizeof (req), RTA_SRC, &mroute->sg.src.s_addr, 4); addattr_l (&req.n, sizeof (req), RTA_DST, &mroute->sg.grp.s_addr, 4); - suc = netlink_talk (netlink_route_change_read_multicast, &req.n, &zns->netlink_cmd, zns); + suc = netlink_talk (netlink_route_change_read_multicast, &req.n, &zns->netlink_cmd, zns, 0); mroute = NULL; return suc; @@ -1766,7 +1766,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp) } /* Talk to netlink socket. */ - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns); + return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); } /* diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 7183525fba..93ee622e35 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -34,7 +34,7 @@ extern int netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp); extern int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id); + ns_id_t ns_id, int startup); extern int netlink_route_read (struct zebra_ns *zns); #endif /* HAVE_NETLINK */