summaryrefslogtreecommitdiff
path: root/zebra/rt_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/rt_netlink.c')
-rw-r--r--zebra/rt_netlink.c4093
1 files changed, 2029 insertions, 2064 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index e017eb78e3..c02774ca64 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -119,11 +119,10 @@
static vlanid_t filter_vlan = 0;
-struct gw_family_t
-{
- u_int16_t filler;
- u_int16_t family;
- union g_addr gate;
+struct gw_family_t {
+ u_int16_t filler;
+ u_int16_t family;
+ union g_addr gate;
};
char ipv4_ll_buf[16] = "169.254.0.1";
@@ -135,592 +134,582 @@ struct in_addr ipv4_ll;
* correct value one time instead for every
* install/remove of a 5549 type route
*/
-void
-rt_netlink_init (void)
+void rt_netlink_init(void)
{
- inet_pton (AF_INET, ipv4_ll_buf, &ipv4_ll);
+ inet_pton(AF_INET, ipv4_ll_buf, &ipv4_ll);
}
static inline int is_selfroute(int proto)
{
- if ((proto == RTPROT_BGP) || (proto == RTPROT_OSPF) ||
- (proto == RTPROT_STATIC) || (proto == RTPROT_ZEBRA) ||
- (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG) ||
- (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP) ||
- (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)) {
- return 1;
- }
-
- return 0;
+ if ((proto == RTPROT_BGP) || (proto == RTPROT_OSPF)
+ || (proto == RTPROT_STATIC) || (proto == RTPROT_ZEBRA)
+ || (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG)
+ || (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP)
+ || (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)) {
+ return 1;
+ }
+
+ return 0;
}
static inline int get_rt_proto(int proto)
{
- switch (proto) {
- case ZEBRA_ROUTE_BABEL:
- proto = RTPROT_BABEL;
- break;
- case ZEBRA_ROUTE_BGP:
- proto = RTPROT_BGP;
- break;
- case ZEBRA_ROUTE_OSPF:
- case ZEBRA_ROUTE_OSPF6:
- proto = RTPROT_OSPF;
- break;
- case ZEBRA_ROUTE_STATIC:
- proto = RTPROT_STATIC;
- break;
- case ZEBRA_ROUTE_ISIS:
- proto = RTPROT_ISIS;
- break;
- case ZEBRA_ROUTE_RIP:
- proto = RTPROT_RIP;
- break;
- case ZEBRA_ROUTE_RIPNG:
- proto = RTPROT_RIPNG;
- break;
- case ZEBRA_ROUTE_NHRP:
- proto = RTPROT_NHRP;
- break;
- case ZEBRA_ROUTE_EIGRP:
- proto = RTPROT_EIGRP;
- break;
- case ZEBRA_ROUTE_LDP:
- proto = RTPROT_LDP;
- break;
- default:
- proto = RTPROT_ZEBRA;
- break;
- }
-
- return proto;
+ switch (proto) {
+ case ZEBRA_ROUTE_BABEL:
+ proto = RTPROT_BABEL;
+ break;
+ case ZEBRA_ROUTE_BGP:
+ proto = RTPROT_BGP;
+ break;
+ case ZEBRA_ROUTE_OSPF:
+ case ZEBRA_ROUTE_OSPF6:
+ proto = RTPROT_OSPF;
+ break;
+ case ZEBRA_ROUTE_STATIC:
+ proto = RTPROT_STATIC;
+ break;
+ case ZEBRA_ROUTE_ISIS:
+ proto = RTPROT_ISIS;
+ break;
+ case ZEBRA_ROUTE_RIP:
+ proto = RTPROT_RIP;
+ break;
+ case ZEBRA_ROUTE_RIPNG:
+ proto = RTPROT_RIPNG;
+ break;
+ case ZEBRA_ROUTE_NHRP:
+ proto = RTPROT_NHRP;
+ break;
+ case ZEBRA_ROUTE_EIGRP:
+ proto = RTPROT_EIGRP;
+ break;
+ case ZEBRA_ROUTE_LDP:
+ proto = RTPROT_LDP;
+ break;
+ default:
+ proto = RTPROT_ZEBRA;
+ break;
+ }
+
+ return proto;
}
/*
Pending: create an efficient table_id (in a tree/hash) based lookup)
*/
-static vrf_id_t
-vrf_lookup_by_table (u_int32_t table_id)
+static vrf_id_t vrf_lookup_by_table(u_int32_t table_id)
{
- struct vrf *vrf;
- struct zebra_vrf *zvrf;
+ struct vrf *vrf;
+ struct zebra_vrf *zvrf;
- RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
- {
- if ((zvrf = vrf->info) == NULL ||
- (zvrf->table_id != table_id))
- continue;
+ RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id)
+ {
+ if ((zvrf = vrf->info) == NULL || (zvrf->table_id != table_id))
+ continue;
- return zvrf_id (zvrf);
- }
+ return zvrf_id(zvrf);
+ }
- return VRF_DEFAULT;
+ return VRF_DEFAULT;
}
/* Looking up routing table by netlink interface. */
-static int
-netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
- ns_id_t ns_id, int startup)
+static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
+ struct nlmsghdr *h, ns_id_t ns_id,
+ int startup)
{
- int len;
- struct rtmsg *rtm;
- struct rtattr *tb[RTA_MAX + 1];
- u_char flags = 0;
- struct prefix p;
- struct prefix_ipv6 src_p;
- vrf_id_t vrf_id = VRF_DEFAULT;
-
- char anyaddr[16] = { 0 };
-
- int index = 0;
- int table;
- int metric = 0;
- u_int32_t mtu = 0;
-
- void *dest = NULL;
- void *gate = NULL;
- void *prefsrc = NULL; /* IPv4 preferred source host address */
- void *src = NULL; /* IPv6 srcdest source prefix */
-
- rtm = NLMSG_DATA (h);
-
- if (startup && h->nlmsg_type != RTM_NEWROUTE)
- return 0;
- if (startup && rtm->rtm_type != RTN_UNICAST)
- return 0;
-
- len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
- if (len < 0)
- return -1;
-
- memset (tb, 0, sizeof tb);
- netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
-
- if (rtm->rtm_flags & RTM_F_CLONED)
- return 0;
- if (rtm->rtm_protocol == RTPROT_REDIRECT)
- return 0;
- if (rtm->rtm_protocol == RTPROT_KERNEL)
- return 0;
-
- if (!startup &&
- is_selfroute (rtm->rtm_protocol) &&
- h->nlmsg_type == RTM_NEWROUTE)
- return 0;
-
- /* We don't care about change notifications for the MPLS table. */
- /* TODO: Revisit this. */
- if (rtm->rtm_family == AF_MPLS)
- return 0;
-
- /* Table corresponding to route. */
- if (tb[RTA_TABLE])
- table = *(int *) RTA_DATA (tb[RTA_TABLE]);
- else
- table = rtm->rtm_table;
-
- /* Map to VRF */
- vrf_id = vrf_lookup_by_table(table);
- if (vrf_id == VRF_DEFAULT)
- {
- if (!is_zebra_valid_kernel_table(table) &&
- !is_zebra_main_routing_table(table))
- return 0;
- }
-
- /* Route which inserted by Zebra. */
- if (is_selfroute(rtm->rtm_protocol))
- flags |= ZEBRA_FLAG_SELFROUTE;
-
- if (tb[RTA_OIF])
- index = *(int *) RTA_DATA (tb[RTA_OIF]);
-
- if (tb[RTA_DST])
- dest = RTA_DATA (tb[RTA_DST]);
- else
- dest = anyaddr;
-
- if (tb[RTA_SRC])
- src = RTA_DATA (tb[RTA_SRC]);
- else
- src = anyaddr;
-
- if (tb[RTA_PREFSRC])
- prefsrc = RTA_DATA (tb[RTA_PREFSRC]);
-
- if (tb[RTA_GATEWAY])
- gate = RTA_DATA (tb[RTA_GATEWAY]);
-
- if (h->nlmsg_type == RTM_NEWROUTE)
- {
- if (tb[RTA_PRIORITY])
- metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
-
- if (tb[RTA_METRICS])
- {
- struct rtattr *mxrta[RTAX_MAX+1];
-
- memset (mxrta, 0, sizeof mxrta);
- netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
- RTA_PAYLOAD(tb[RTA_METRICS]));
-
- if (mxrta[RTAX_MTU])
- mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
- }
- }
-
- if (rtm->rtm_family == AF_INET)
- {
- p.family = AF_INET;
- memcpy (&p.u.prefix4, dest, 4);
- p.prefixlen = rtm->rtm_dst_len;
-
- src_p.prefixlen = 0; // Forces debug below to not display anything
- }
- else if (rtm->rtm_family == AF_INET6)
- {
- p.family = AF_INET6;
- memcpy (&p.u.prefix6, dest, 16);
- p.prefixlen = rtm->rtm_dst_len;
-
- src_p.family = AF_INET6;
- memcpy (&src_p.prefix, src, 16);
- src_p.prefixlen = rtm->rtm_src_len;
- }
-
- if (rtm->rtm_src_len != 0)
- {
- char buf[PREFIX_STRLEN];
- zlog_warn ("unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
- prefix2str (&p, buf, sizeof(buf)), vrf_id);
- return 0;
- }
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- {
- char buf[PREFIX_STRLEN];
- char buf2[PREFIX_STRLEN];
- zlog_debug ("%s %s%s%s vrf %u",
- nl_msg_type_to_str (h->nlmsg_type),
- prefix2str (&p, buf, sizeof(buf)),
- src_p.prefixlen ? " from " : "",
- src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "",
- vrf_id);
- }
-
- afi_t afi = AFI_IP;
- if (rtm->rtm_family == AF_INET6)
- afi = AFI_IP6;
-
- if (h->nlmsg_type == RTM_NEWROUTE)
- {
- if (!tb[RTA_MULTIPATH])
- rib_add (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
- 0, flags, &p, NULL, gate, prefsrc, index,
- table, metric, mtu, 0);
- else
- {
- /* This is a multipath route */
-
- struct route_entry *re;
- struct rtnexthop *rtnh =
- (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
-
- len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
-
- re = XCALLOC (MTYPE_RE, sizeof (struct route_entry));
- re->type = ZEBRA_ROUTE_KERNEL;
- re->distance = 0;
- re->flags = flags;
- re->metric = metric;
- re->mtu = mtu;
- re->vrf_id = vrf_id;
- re->table = table;
- re->nexthop_num = 0;
- re->uptime = time (NULL);
-
- for (;;)
- {
- if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
- break;
-
- index = rtnh->rtnh_ifindex;
- gate = 0;
- if (rtnh->rtnh_len > sizeof (*rtnh))
- {
- memset (tb, 0, sizeof (tb));
- netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
- rtnh->rtnh_len - sizeof (*rtnh));
- if (tb[RTA_GATEWAY])
- gate = RTA_DATA (tb[RTA_GATEWAY]);
- }
-
- if (gate)
- {
- if (rtm->rtm_family == AF_INET)
- {
- if (index)
- route_entry_nexthop_ipv4_ifindex_add (re, gate, prefsrc, index);
- else
- route_entry_nexthop_ipv4_add (re, gate, prefsrc);
- }
- else if (rtm->rtm_family == AF_INET6)
- {
- if (index)
- route_entry_nexthop_ipv6_ifindex_add (re, gate, index);
- else
- route_entry_nexthop_ipv6_add (re,gate);
- }
- }
- else
- route_entry_nexthop_ifindex_add (re, index);
-
- len -= NLMSG_ALIGN(rtnh->rtnh_len);
- rtnh = RTNH_NEXT(rtnh);
- }
-
- zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
- re->nexthop_num);
- if (re->nexthop_num == 0)
- XFREE (MTYPE_RE, re);
- else
- rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, re);
- }
- }
- else
- {
- if (!tb[RTA_MULTIPATH])
- rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags,
- &p, NULL, gate, index, table);
- else
- {
- struct rtnexthop *rtnh =
- (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
-
- len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
-
- for (;;)
- {
- if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
- break;
-
- gate = NULL;
- if (rtnh->rtnh_len > sizeof (*rtnh))
- {
- memset (tb, 0, sizeof (tb));
- netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
- rtnh->rtnh_len - sizeof (*rtnh));
- if (tb[RTA_GATEWAY])
- gate = RTA_DATA (tb[RTA_GATEWAY]);
- }
-
- if (gate)
- rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags,
- &p, NULL, gate, index, table);
-
- len -= NLMSG_ALIGN(rtnh->rtnh_len);
- rtnh = RTNH_NEXT(rtnh);
- }
- }
- }
-
- return 0;
+ int len;
+ struct rtmsg *rtm;
+ struct rtattr *tb[RTA_MAX + 1];
+ u_char flags = 0;
+ struct prefix p;
+ struct prefix_ipv6 src_p;
+ vrf_id_t vrf_id = VRF_DEFAULT;
+
+ char anyaddr[16] = {0};
+
+ int index = 0;
+ int table;
+ int metric = 0;
+ u_int32_t mtu = 0;
+
+ void *dest = NULL;
+ void *gate = NULL;
+ void *prefsrc = NULL; /* IPv4 preferred source host address */
+ void *src = NULL; /* IPv6 srcdest source prefix */
+
+ rtm = NLMSG_DATA(h);
+
+ if (startup && h->nlmsg_type != RTM_NEWROUTE)
+ return 0;
+ if (startup && rtm->rtm_type != RTN_UNICAST)
+ return 0;
+
+ len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
+ if (len < 0)
+ return -1;
+
+ memset(tb, 0, sizeof tb);
+ netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len);
+
+ if (rtm->rtm_flags & RTM_F_CLONED)
+ return 0;
+ if (rtm->rtm_protocol == RTPROT_REDIRECT)
+ return 0;
+ if (rtm->rtm_protocol == RTPROT_KERNEL)
+ return 0;
+
+ if (!startup && is_selfroute(rtm->rtm_protocol)
+ && h->nlmsg_type == RTM_NEWROUTE)
+ return 0;
+
+ /* We don't care about change notifications for the MPLS table. */
+ /* TODO: Revisit this. */
+ if (rtm->rtm_family == AF_MPLS)
+ return 0;
+
+ /* Table corresponding to route. */
+ if (tb[RTA_TABLE])
+ table = *(int *)RTA_DATA(tb[RTA_TABLE]);
+ else
+ table = rtm->rtm_table;
+
+ /* Map to VRF */
+ vrf_id = vrf_lookup_by_table(table);
+ if (vrf_id == VRF_DEFAULT) {
+ if (!is_zebra_valid_kernel_table(table)
+ && !is_zebra_main_routing_table(table))
+ return 0;
+ }
+
+ /* Route which inserted by Zebra. */
+ if (is_selfroute(rtm->rtm_protocol))
+ flags |= ZEBRA_FLAG_SELFROUTE;
+
+ if (tb[RTA_OIF])
+ index = *(int *)RTA_DATA(tb[RTA_OIF]);
+
+ if (tb[RTA_DST])
+ dest = RTA_DATA(tb[RTA_DST]);
+ else
+ dest = anyaddr;
+
+ if (tb[RTA_SRC])
+ src = RTA_DATA(tb[RTA_SRC]);
+ else
+ src = anyaddr;
+
+ if (tb[RTA_PREFSRC])
+ prefsrc = RTA_DATA(tb[RTA_PREFSRC]);
+
+ if (tb[RTA_GATEWAY])
+ gate = RTA_DATA(tb[RTA_GATEWAY]);
+
+ if (h->nlmsg_type == RTM_NEWROUTE) {
+ if (tb[RTA_PRIORITY])
+ metric = *(int *)RTA_DATA(tb[RTA_PRIORITY]);
+
+ if (tb[RTA_METRICS]) {
+ struct rtattr *mxrta[RTAX_MAX + 1];
+
+ memset(mxrta, 0, sizeof mxrta);
+ netlink_parse_rtattr(mxrta, RTAX_MAX,
+ RTA_DATA(tb[RTA_METRICS]),
+ RTA_PAYLOAD(tb[RTA_METRICS]));
+
+ if (mxrta[RTAX_MTU])
+ mtu = *(u_int32_t *)RTA_DATA(mxrta[RTAX_MTU]);
+ }
+ }
+
+ if (rtm->rtm_family == AF_INET) {
+ p.family = AF_INET;
+ memcpy(&p.u.prefix4, dest, 4);
+ p.prefixlen = rtm->rtm_dst_len;
+
+ src_p.prefixlen =
+ 0; // Forces debug below to not display anything
+ } else if (rtm->rtm_family == AF_INET6) {
+ p.family = AF_INET6;
+ memcpy(&p.u.prefix6, dest, 16);
+ p.prefixlen = rtm->rtm_dst_len;
+
+ src_p.family = AF_INET6;
+ memcpy(&src_p.prefix, src, 16);
+ src_p.prefixlen = rtm->rtm_src_len;
+ }
+
+ if (rtm->rtm_src_len != 0) {
+ char buf[PREFIX_STRLEN];
+ zlog_warn(
+ "unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
+ prefix2str(&p, buf, sizeof(buf)), vrf_id);
+ return 0;
+ }
+
+ if (IS_ZEBRA_DEBUG_KERNEL) {
+ char buf[PREFIX_STRLEN];
+ char buf2[PREFIX_STRLEN];
+ zlog_debug(
+ "%s %s%s%s vrf %u", nl_msg_type_to_str(h->nlmsg_type),
+ prefix2str(&p, buf, sizeof(buf)),
+ src_p.prefixlen ? " from " : "",
+ src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2))
+ : "",
+ vrf_id);
+ }
+
+ afi_t afi = AFI_IP;
+ if (rtm->rtm_family == AF_INET6)
+ afi = AFI_IP6;
+
+ if (h->nlmsg_type == RTM_NEWROUTE) {
+ if (!tb[RTA_MULTIPATH])
+ rib_add(afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
+ 0, flags, &p, NULL, gate, prefsrc, index, table,
+ metric, mtu, 0);
+ else {
+ /* This is a multipath route */
+
+ struct route_entry *re;
+ struct rtnexthop *rtnh =
+ (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
+
+ len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
+
+ re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
+ re->type = ZEBRA_ROUTE_KERNEL;
+ re->distance = 0;
+ re->flags = flags;
+ re->metric = metric;
+ re->mtu = mtu;
+ re->vrf_id = vrf_id;
+ re->table = table;
+ re->nexthop_num = 0;
+ re->uptime = time(NULL);
+
+ for (;;) {
+ if (len < (int)sizeof(*rtnh)
+ || rtnh->rtnh_len > len)
+ break;
+
+ index = rtnh->rtnh_ifindex;
+ gate = 0;
+ if (rtnh->rtnh_len > sizeof(*rtnh)) {
+ memset(tb, 0, sizeof(tb));
+ netlink_parse_rtattr(
+ tb, RTA_MAX, RTNH_DATA(rtnh),
+ rtnh->rtnh_len - sizeof(*rtnh));
+ if (tb[RTA_GATEWAY])
+ gate = RTA_DATA(
+ tb[RTA_GATEWAY]);
+ }
+
+ if (gate) {
+ if (rtm->rtm_family == AF_INET) {
+ if (index)
+ route_entry_nexthop_ipv4_ifindex_add(
+ re, gate,
+ prefsrc, index);
+ else
+ route_entry_nexthop_ipv4_add(
+ re, gate,
+ prefsrc);
+ } else if (rtm->rtm_family
+ == AF_INET6) {
+ if (index)
+ route_entry_nexthop_ipv6_ifindex_add(
+ re, gate,
+ index);
+ else
+ route_entry_nexthop_ipv6_add(
+ re, gate);
+ }
+ } else
+ route_entry_nexthop_ifindex_add(re,
+ index);
+
+ len -= NLMSG_ALIGN(rtnh->rtnh_len);
+ rtnh = RTNH_NEXT(rtnh);
+ }
+
+ zserv_nexthop_num_warn(__func__,
+ (const struct prefix *)&p,
+ re->nexthop_num);
+ if (re->nexthop_num == 0)
+ XFREE(MTYPE_RE, re);
+ else
+ rib_add_multipath(AFI_IP, SAFI_UNICAST, &p,
+ NULL, re);
+ }
+ } else {
+ if (!tb[RTA_MULTIPATH])
+ rib_delete(afi, SAFI_UNICAST, vrf_id,
+ ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, gate,
+ index, table);
+ else {
+ struct rtnexthop *rtnh =
+ (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
+
+ len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
+
+ for (;;) {
+ if (len < (int)sizeof(*rtnh)
+ || rtnh->rtnh_len > len)
+ break;
+
+ gate = NULL;
+ if (rtnh->rtnh_len > sizeof(*rtnh)) {
+ memset(tb, 0, sizeof(tb));
+ netlink_parse_rtattr(
+ tb, RTA_MAX, RTNH_DATA(rtnh),
+ rtnh->rtnh_len - sizeof(*rtnh));
+ if (tb[RTA_GATEWAY])
+ gate = RTA_DATA(
+ tb[RTA_GATEWAY]);
+ }
+
+ if (gate)
+ rib_delete(afi, SAFI_UNICAST, vrf_id,
+ ZEBRA_ROUTE_KERNEL, 0, flags,
+ &p, NULL, gate, index,
+ table);
+
+ len -= NLMSG_ALIGN(rtnh->rtnh_len);
+ rtnh = RTNH_NEXT(rtnh);
+ }
+ }
+ }
+
+ return 0;
}
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, int startup)
+static int netlink_route_change_read_multicast(struct sockaddr_nl *snl,
+ struct nlmsghdr *h,
+ ns_id_t ns_id, int startup)
{
- int len;
- struct rtmsg *rtm;
- struct rtattr *tb[RTA_MAX + 1];
- struct mcast_route_data *m;
- struct mcast_route_data mr;
- int iif = 0;
- int count;
- int oif[256];
- int oif_count = 0;
- char sbuf[40];
- char gbuf[40];
- char oif_list[256] = "\0";
- vrf_id_t vrf = ns_id;
-
- if (mroute)
- m = mroute;
- else
- {
- memset (&mr, 0, sizeof (mr));
- m = &mr;
- }
-
- rtm = NLMSG_DATA (h);
-
- len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
-
- memset (tb, 0, sizeof tb);
- netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
-
- if (tb[RTA_IIF])
- iif = *(int *)RTA_DATA (tb[RTA_IIF]);
-
- if (tb[RTA_SRC])
- m->sg.src = *(struct in_addr *)RTA_DATA (tb[RTA_SRC]);
-
- if (tb[RTA_DST])
- m->sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]);
-
- if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES])
- m->lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]);
-
- if (tb[RTA_MULTIPATH])
- {
- struct rtnexthop *rtnh =
- (struct rtnexthop *)RTA_DATA (tb[RTA_MULTIPATH]);
-
- len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
- for (;;)
- {
- if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
- break;
-
- oif[oif_count] = rtnh->rtnh_ifindex;
- oif_count++;
-
- len -= NLMSG_ALIGN (rtnh->rtnh_len);
- rtnh = RTNH_NEXT (rtnh);
- }
- }
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- {
- struct interface *ifp;
- strcpy (sbuf, inet_ntoa (m->sg.src));
- strcpy (gbuf, inet_ntoa (m->sg.grp));
- for (count = 0; count < oif_count; count++)
- {
- ifp = if_lookup_by_index (oif[count], vrf);
- char temp[256];
+ int len;
+ struct rtmsg *rtm;
+ struct rtattr *tb[RTA_MAX + 1];
+ struct mcast_route_data *m;
+ struct mcast_route_data mr;
+ int iif = 0;
+ int count;
+ int oif[256];
+ int oif_count = 0;
+ char sbuf[40];
+ char gbuf[40];
+ char oif_list[256] = "\0";
+ vrf_id_t vrf = ns_id;
+
+ if (mroute)
+ m = mroute;
+ else {
+ memset(&mr, 0, sizeof(mr));
+ m = &mr;
+ }
+
+ rtm = NLMSG_DATA(h);
+
+ len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
+
+ memset(tb, 0, sizeof tb);
+ netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len);
- sprintf (temp, "%s ", ifp->name);
- strcat (oif_list, temp);
+ if (tb[RTA_IIF])
+ iif = *(int *)RTA_DATA(tb[RTA_IIF]);
+
+ if (tb[RTA_SRC])
+ m->sg.src = *(struct in_addr *)RTA_DATA(tb[RTA_SRC]);
+
+ if (tb[RTA_DST])
+ m->sg.grp = *(struct in_addr *)RTA_DATA(tb[RTA_DST]);
+
+ if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES])
+ m->lastused = *(unsigned long long *)RTA_DATA(tb[RTA_EXPIRES]);
+
+ if (tb[RTA_MULTIPATH]) {
+ struct rtnexthop *rtnh =
+ (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
+
+ len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
+ for (;;) {
+ if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len)
+ break;
+
+ oif[oif_count] = rtnh->rtnh_ifindex;
+ oif_count++;
+
+ len -= NLMSG_ALIGN(rtnh->rtnh_len);
+ rtnh = RTNH_NEXT(rtnh);
+ }
+ }
+
+ if (IS_ZEBRA_DEBUG_KERNEL) {
+ struct interface *ifp;
+ strcpy(sbuf, inet_ntoa(m->sg.src));
+ strcpy(gbuf, inet_ntoa(m->sg.grp));
+ for (count = 0; count < oif_count; count++) {
+ ifp = if_lookup_by_index(oif[count], vrf);
+ char temp[256];
+
+ sprintf(temp, "%s ", ifp->name);
+ strcat(oif_list, temp);
+ }
+ ifp = if_lookup_by_index(iif, vrf);
+ zlog_debug("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
+ nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf,
+ ifp->name, oif_list, m->lastused);
}
- ifp = if_lookup_by_index (iif, vrf);
- zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
- nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf, ifp->name, oif_list, m->lastused);
- }
- return 0;
+ return 0;
}
-int
-netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
- ns_id_t ns_id, int startup)
+int netlink_route_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
+ ns_id_t ns_id, int startup)
{
- int len;
- vrf_id_t vrf_id = ns_id;
- struct rtmsg *rtm;
-
- rtm = NLMSG_DATA (h);
-
- if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
- {
- /* If this is not route add/delete message print warning. */
- zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id);
- return 0;
- }
-
- /* Connected route. */
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("%s %s %s proto %s vrf %u",
- nl_msg_type_to_str (h->nlmsg_type),
- nl_family_to_str (rtm->rtm_family),
- nl_rttype_to_str (rtm->rtm_type),
- nl_rtproto_to_str (rtm->rtm_protocol),
- vrf_id);
-
- /* We don't care about change notifications for the MPLS table. */
- /* TODO: Revisit this. */
- if (rtm->rtm_family == AF_MPLS)
- return 0;
-
- len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
- if (len < 0)
- return -1;
-
- switch (rtm->rtm_type)
- {
- case RTN_UNICAST:
- netlink_route_change_read_unicast (snl, h, ns_id, startup);
- break;
- case RTN_MULTICAST:
- netlink_route_change_read_multicast (snl, h, ns_id, startup);
- break;
- default:
- return 0;
- break;
- }
-
- return 0;
+ int len;
+ vrf_id_t vrf_id = ns_id;
+ struct rtmsg *rtm;
+
+ rtm = NLMSG_DATA(h);
+
+ if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) {
+ /* If this is not route add/delete message print warning. */
+ zlog_warn("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id);
+ return 0;
+ }
+
+ /* Connected route. */
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s %s %s proto %s vrf %u",
+ nl_msg_type_to_str(h->nlmsg_type),
+ nl_family_to_str(rtm->rtm_family),
+ nl_rttype_to_str(rtm->rtm_type),
+ nl_rtproto_to_str(rtm->rtm_protocol), vrf_id);
+
+ /* We don't care about change notifications for the MPLS table. */
+ /* TODO: Revisit this. */
+ if (rtm->rtm_family == AF_MPLS)
+ return 0;
+
+ len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
+ if (len < 0)
+ return -1;
+
+ switch (rtm->rtm_type) {
+ case RTN_UNICAST:
+ netlink_route_change_read_unicast(snl, h, ns_id, startup);
+ break;
+ case RTN_MULTICAST:
+ netlink_route_change_read_multicast(snl, h, ns_id, startup);
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ return 0;
}
/* Request for specific route information from the kernel */
-static int
-netlink_request_route (struct zebra_ns *zns, int family, int type)
+static int netlink_request_route(struct zebra_ns *zns, int family, int type)
{
- struct
- {
- struct nlmsghdr n;
- struct rtmsg rtm;
- } req;
-
- /* Form the request, specifying filter (rtattr) if needed. */
- memset (&req, 0, sizeof (req));
- req.n.nlmsg_type = type;
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- req.rtm.rtm_family = family;
-
- return netlink_request (&zns->netlink_cmd, &req.n);
+ struct {
+ struct nlmsghdr n;
+ struct rtmsg rtm;
+ } req;
+
+ /* Form the request, specifying filter (rtattr) if needed. */
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_type = type;
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ req.rtm.rtm_family = family;
+
+ return netlink_request(&zns->netlink_cmd, &req.n);
}
/* Routing table read function using netlink interface. Only called
bootstrap time. */
-int
-netlink_route_read (struct zebra_ns *zns)
+int netlink_route_read(struct zebra_ns *zns)
{
- int ret;
-
- /* Get IPv4 routing table. */
- ret = netlink_request_route (zns, AF_INET, RTM_GETROUTE);
- if (ret < 0)
- return ret;
- ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1);
- if (ret < 0)
- return ret;
-
- /* Get IPv6 routing table. */
- ret = netlink_request_route (zns, AF_INET6, RTM_GETROUTE);
- if (ret < 0)
- return ret;
- ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1);
- if (ret < 0)
- return ret;
-
- return 0;
+ int ret;
+
+ /* Get IPv4 routing table. */
+ ret = netlink_request_route(zns, AF_INET, RTM_GETROUTE);
+ if (ret < 0)
+ return ret;
+ ret = netlink_parse_info(netlink_route_change_read_unicast,
+ &zns->netlink_cmd, zns, 0, 1);
+ if (ret < 0)
+ return ret;
+
+ /* Get IPv6 routing table. */
+ ret = netlink_request_route(zns, AF_INET6, RTM_GETROUTE);
+ if (ret < 0)
+ return ret;
+ ret = netlink_parse_info(netlink_route_change_read_unicast,
+ &zns->netlink_cmd, zns, 0, 1);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
-static void
-_netlink_route_nl_add_gateway_info (u_char route_family, u_char gw_family,
- struct nlmsghdr *nlmsg,
- size_t req_size, int bytelen,
- struct nexthop *nexthop)
+static void _netlink_route_nl_add_gateway_info(u_char route_family,
+ u_char gw_family,
+ struct nlmsghdr *nlmsg,
+ size_t req_size, int bytelen,
+ struct nexthop *nexthop)
{
- if (route_family == AF_MPLS)
- {
- struct gw_family_t gw_fam;
-
- gw_fam.family = gw_family;
- if (gw_family == AF_INET)
- memcpy (&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
- else
- memcpy (&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
- addattr_l (nlmsg, req_size, RTA_VIA, &gw_fam.family, bytelen+2);
- }
- else
- {
- if (gw_family == AF_INET)
- addattr_l (nlmsg, req_size, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen);
- else
- addattr_l (nlmsg, req_size, RTA_GATEWAY, &nexthop->gate.ipv6, bytelen);
- }
+ if (route_family == AF_MPLS) {
+ struct gw_family_t gw_fam;
+
+ gw_fam.family = gw_family;
+ if (gw_family == AF_INET)
+ memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
+ else
+ memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
+ addattr_l(nlmsg, req_size, RTA_VIA, &gw_fam.family,
+ bytelen + 2);
+ } else {
+ if (gw_family == AF_INET)
+ addattr_l(nlmsg, req_size, RTA_GATEWAY,
+ &nexthop->gate.ipv4, bytelen);
+ else
+ addattr_l(nlmsg, req_size, RTA_GATEWAY,
+ &nexthop->gate.ipv6, bytelen);
+ }
}
-static void
-_netlink_route_rta_add_gateway_info (u_char route_family, u_char gw_family,
- struct rtattr *rta, struct rtnexthop *rtnh,
- size_t req_size, int bytelen,
- struct nexthop *nexthop)
+static void _netlink_route_rta_add_gateway_info(u_char route_family,
+ u_char gw_family,
+ struct rtattr *rta,
+ struct rtnexthop *rtnh,
+ size_t req_size, int bytelen,
+ struct nexthop *nexthop)
{
- if (route_family == AF_MPLS)
- {
- struct gw_family_t gw_fam;
-
- gw_fam.family = gw_family;
- if (gw_family == AF_INET)
- memcpy (&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
- else
- memcpy (&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
- rta_addattr_l (rta, req_size, RTA_VIA, &gw_fam.family, bytelen+2);
- rtnh->rtnh_len += RTA_LENGTH (bytelen + 2);
- }
- else
- {
- if (gw_family == AF_INET)
- rta_addattr_l (rta, req_size, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen);
- else
- rta_addattr_l (rta, req_size, RTA_GATEWAY, &nexthop->gate.ipv6, bytelen);
- rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
- }
+ if (route_family == AF_MPLS) {
+ struct gw_family_t gw_fam;
+
+ gw_fam.family = gw_family;
+ if (gw_family == AF_INET)
+ memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
+ else
+ memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
+ rta_addattr_l(rta, req_size, RTA_VIA, &gw_fam.family,
+ bytelen + 2);
+ rtnh->rtnh_len += RTA_LENGTH(bytelen + 2);
+ } else {
+ if (gw_family == AF_INET)
+ rta_addattr_l(rta, req_size, RTA_GATEWAY,
+ &nexthop->gate.ipv4, bytelen);
+ else
+ rta_addattr_l(rta, req_size, RTA_GATEWAY,
+ &nexthop->gate.ipv6, bytelen);
+ rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
+ }
}
/* This function takes a nexthop as argument and adds
@@ -734,194 +723,186 @@ _netlink_route_rta_add_gateway_info (u_char route_family, u_char gw_family,
* @param nlmsg: nlmsghdr structure to fill in.
* @param req_size: The size allocated for the message.
*/
-static void
-_netlink_route_build_singlepath(
- const char *routedesc,
- int bytelen,
- struct nexthop *nexthop,
- struct nlmsghdr *nlmsg,
- struct rtmsg *rtmsg,
- size_t req_size,
- int cmd)
+static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
+ struct nexthop *nexthop,
+ struct nlmsghdr *nlmsg,
+ struct rtmsg *rtmsg,
+ size_t req_size, int cmd)
{
- struct nexthop_label *nh_label;
- mpls_lse_t out_lse[MPLS_MAX_LABELS];
- char label_buf[100];
-
- /*
- * label_buf is *only* currently used within debugging.
- * As such when we assign it we are guarding it inside
- * a debug test. If you want to change this make sure
- * you fix this assumption
- */
- label_buf[0] = '\0';
- /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
- * (in the case of LER)
- */
- nh_label = nexthop->nh_label;
- if (rtmsg->rtm_family == AF_MPLS)
- {
- assert (nh_label);
- assert (nh_label->num_labels == 1);
- }
-
- if (nh_label && nh_label->num_labels)
- {
- int i, num_labels = 0;
- u_int32_t bos;
- char label_buf1[20];
-
- for (i = 0; i < nh_label->num_labels; i++)
- {
- if (nh_label->label[i] != MPLS_IMP_NULL_LABEL)
- {
- bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0);
- out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos);
- if (IS_ZEBRA_DEBUG_KERNEL)
- {
- if (!num_labels)
- sprintf (label_buf, "label %d", nh_label->label[i]);
- else
- {
- sprintf (label_buf1, "/%d", nh_label->label[i]);
- strcat (label_buf, label_buf1);
- }
+ struct nexthop_label *nh_label;
+ mpls_lse_t out_lse[MPLS_MAX_LABELS];
+ char label_buf[100];
+
+ /*
+ * label_buf is *only* currently used within debugging.
+ * As such when we assign it we are guarding it inside
+ * a debug test. If you want to change this make sure
+ * you fix this assumption
+ */
+ label_buf[0] = '\0';
+ /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
+ * (in the case of LER)
+ */
+ nh_label = nexthop->nh_label;
+ if (rtmsg->rtm_family == AF_MPLS) {
+ assert(nh_label);
+ assert(nh_label->num_labels == 1);
+ }
+
+ if (nh_label && nh_label->num_labels) {
+ int i, num_labels = 0;
+ u_int32_t bos;
+ char label_buf1[20];
+
+ for (i = 0; i < nh_label->num_labels; i++) {
+ if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) {
+ bos = ((i == (nh_label->num_labels - 1)) ? 1
+ : 0);
+ out_lse[i] = mpls_lse_encode(nh_label->label[i],
+ 0, 0, bos);
+ if (IS_ZEBRA_DEBUG_KERNEL) {
+ if (!num_labels)
+ sprintf(label_buf, "label %d",
+ nh_label->label[i]);
+ else {
+ sprintf(label_buf1, "/%d",
+ nh_label->label[i]);
+ strcat(label_buf, label_buf1);
+ }
+ }
+ num_labels++;
+ }
+ }
+ if (num_labels) {
+ if (rtmsg->rtm_family == AF_MPLS)
+ addattr_l(nlmsg, req_size, RTA_NEWDST, &out_lse,
+ num_labels * sizeof(mpls_lse_t));
+ else {
+ struct rtattr *nest;
+ u_int16_t encap = LWTUNNEL_ENCAP_MPLS;
+
+ addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE,
+ &encap, sizeof(u_int16_t));
+ nest = addattr_nest(nlmsg, req_size, RTA_ENCAP);
+ addattr_l(nlmsg, req_size, MPLS_IPTUNNEL_DST,
+ &out_lse,
+ num_labels * sizeof(mpls_lse_t));
+ addattr_nest_end(nlmsg, nest);
+ }
}
- num_labels++;
- }
- }
- if (num_labels)
- {
- if (rtmsg->rtm_family == AF_MPLS)
- addattr_l (nlmsg, req_size, RTA_NEWDST,
- &out_lse, num_labels * sizeof(mpls_lse_t));
- else
- {
- struct rtattr *nest;
- u_int16_t encap = LWTUNNEL_ENCAP_MPLS;
-
- addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE,
- &encap, sizeof (u_int16_t));
- nest = addattr_nest(nlmsg, req_size, RTA_ENCAP);
- addattr_l (nlmsg, req_size, MPLS_IPTUNNEL_DST,
- &out_lse, num_labels * sizeof(mpls_lse_t));
- addattr_nest_end(nlmsg, nest);
- }
- }
- }
-
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
- rtmsg->rtm_flags |= RTNH_F_ONLINK;
-
- if (rtmsg->rtm_family == AF_INET &&
- (nexthop->type == NEXTHOP_TYPE_IPV6
- || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX))
- {
- rtmsg->rtm_flags |= RTNH_F_ONLINK;
- addattr_l (nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4);
- addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
-
- if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
- addattr_l (nlmsg, req_size, RTA_PREFSRC,
- &nexthop->rmap_src.ipv4, bytelen);
- else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
- addattr_l (nlmsg, req_size, RTA_PREFSRC,
- &nexthop->src.ipv4, bytelen);
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): "
- "nexthop via %s %s if %u",
- routedesc, ipv4_ll_buf, label_buf, nexthop->ifindex);
- return;
- }
-
- if (nexthop->type == NEXTHOP_TYPE_IPV4
- || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
- {
- /* Send deletes to the kernel without specifying the next-hop */
- if (cmd != RTM_DELROUTE)
- _netlink_route_nl_add_gateway_info (rtmsg->rtm_family, AF_INET, nlmsg,
- req_size, bytelen, nexthop);
-
- if (cmd == RTM_NEWROUTE)
- {
- if (nexthop->rmap_src.ipv4.s_addr)
- addattr_l (nlmsg, req_size, RTA_PREFSRC,
- &nexthop->rmap_src.ipv4, bytelen);
- else if (nexthop->src.ipv4.s_addr)
- addattr_l (nlmsg, req_size, RTA_PREFSRC,
- &nexthop->src.ipv4, bytelen);
}
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("netlink_route_multipath() (%s): "
- "nexthop via %s %s if %u",
- routedesc,
- inet_ntoa (nexthop->gate.ipv4),
- label_buf, nexthop->ifindex);
- }
-
- if (nexthop->type == NEXTHOP_TYPE_IPV6
- || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
- {
- _netlink_route_nl_add_gateway_info (rtmsg->rtm_family, AF_INET6, nlmsg,
- req_size, bytelen, nexthop);
-
- if (cmd == RTM_NEWROUTE)
- {
- if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
- addattr_l (nlmsg, req_size, RTA_PREFSRC,
- &nexthop->rmap_src.ipv6, bytelen);
- else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
- addattr_l (nlmsg, req_size, RTA_PREFSRC,
- &nexthop->src.ipv6, bytelen);
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
+ rtmsg->rtm_flags |= RTNH_F_ONLINK;
+
+ if (rtmsg->rtm_family == AF_INET
+ && (nexthop->type == NEXTHOP_TYPE_IPV6
+ || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) {
+ rtmsg->rtm_flags |= RTNH_F_ONLINK;
+ addattr_l(nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4);
+ addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
+
+ if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
+ addattr_l(nlmsg, req_size, RTA_PREFSRC,
+ &nexthop->rmap_src.ipv4, bytelen);
+ else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
+ addattr_l(nlmsg, req_size, RTA_PREFSRC,
+ &nexthop->src.ipv4, bytelen);
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ " 5549: _netlink_route_build_singlepath() (%s): "
+ "nexthop via %s %s if %u",
+ routedesc, ipv4_ll_buf, label_buf,
+ nexthop->ifindex);
+ return;
}
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("netlink_route_multipath() (%s): "
- "nexthop via %s %s if %u",
- routedesc,
- inet6_ntoa (nexthop->gate.ipv6),
- label_buf, nexthop->ifindex);
- }
- if (nexthop->type == NEXTHOP_TYPE_IFINDEX
- || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
- {
- addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
-
- if (cmd == RTM_NEWROUTE)
- {
- if (nexthop->rmap_src.ipv4.s_addr)
- addattr_l (nlmsg, req_size, RTA_PREFSRC,
- &nexthop->rmap_src.ipv4, bytelen);
- else if (nexthop->src.ipv4.s_addr)
- addattr_l (nlmsg, req_size, RTA_PREFSRC,
- &nexthop->src.ipv4, bytelen);
+ if (nexthop->type == NEXTHOP_TYPE_IPV4
+ || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
+ /* Send deletes to the kernel without specifying the next-hop */
+ if (cmd != RTM_DELROUTE)
+ _netlink_route_nl_add_gateway_info(
+ rtmsg->rtm_family, AF_INET, nlmsg, req_size,
+ bytelen, nexthop);
+
+ if (cmd == RTM_NEWROUTE) {
+ if (nexthop->rmap_src.ipv4.s_addr)
+ addattr_l(nlmsg, req_size, RTA_PREFSRC,
+ &nexthop->rmap_src.ipv4, bytelen);
+ else if (nexthop->src.ipv4.s_addr)
+ addattr_l(nlmsg, req_size, RTA_PREFSRC,
+ &nexthop->src.ipv4, bytelen);
+ }
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "netlink_route_multipath() (%s): "
+ "nexthop via %s %s if %u",
+ routedesc, inet_ntoa(nexthop->gate.ipv4),
+ label_buf, nexthop->ifindex);
}
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("netlink_route_multipath() (%s): "
- "nexthop via if %u", routedesc, nexthop->ifindex);
- }
+ if (nexthop->type == NEXTHOP_TYPE_IPV6
+ || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
+ _netlink_route_nl_add_gateway_info(rtmsg->rtm_family, AF_INET6,
+ nlmsg, req_size, bytelen,
+ nexthop);
+
+ if (cmd == RTM_NEWROUTE) {
+ if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
+ addattr_l(nlmsg, req_size, RTA_PREFSRC,
+ &nexthop->rmap_src.ipv6, bytelen);
+ else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
+ addattr_l(nlmsg, req_size, RTA_PREFSRC,
+ &nexthop->src.ipv6, bytelen);
+ }
- if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
- {
- addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "netlink_route_multipath() (%s): "
+ "nexthop via %s %s if %u",
+ routedesc, inet6_ntoa(nexthop->gate.ipv6),
+ label_buf, nexthop->ifindex);
+ }
+ if (nexthop->type == NEXTHOP_TYPE_IFINDEX
+ || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
+ addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
+
+ if (cmd == RTM_NEWROUTE) {
+ if (nexthop->rmap_src.ipv4.s_addr)
+ addattr_l(nlmsg, req_size, RTA_PREFSRC,
+ &nexthop->rmap_src.ipv4, bytelen);
+ else if (nexthop->src.ipv4.s_addr)
+ addattr_l(nlmsg, req_size, RTA_PREFSRC,
+ &nexthop->src.ipv4, bytelen);
+ }
- if (cmd == RTM_NEWROUTE)
- {
- if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
- addattr_l (nlmsg, req_size, RTA_PREFSRC,
- &nexthop->rmap_src.ipv6, bytelen);
- else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
- addattr_l (nlmsg, req_size, RTA_PREFSRC,
- &nexthop->src.ipv6, bytelen);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "netlink_route_multipath() (%s): "
+ "nexthop via if %u",
+ routedesc, nexthop->ifindex);
}
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("netlink_route_multipath() (%s): "
- "nexthop via if %u", routedesc, nexthop->ifindex);
- }
+ if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
+ addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
+
+ if (cmd == RTM_NEWROUTE) {
+ if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
+ addattr_l(nlmsg, req_size, RTA_PREFSRC,
+ &nexthop->rmap_src.ipv6, bytelen);
+ else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
+ addattr_l(nlmsg, req_size, RTA_PREFSRC,
+ &nexthop->src.ipv6, bytelen);
+ }
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "netlink_route_multipath() (%s): "
+ "nexthop via if %u",
+ routedesc, nexthop->ifindex);
+ }
}
/* This function takes a nexthop as argument and
@@ -940,217 +921,206 @@ _netlink_route_build_singlepath(
* @param src: pointer pointing to a location where
* the prefsrc should be stored.
*/
-static void
-_netlink_route_build_multipath(
- const char *routedesc,
- int bytelen,
- struct nexthop *nexthop,
- struct rtattr *rta,
- struct rtnexthop *rtnh,
- struct rtmsg *rtmsg,
- union g_addr **src)
+static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
+ struct nexthop *nexthop,
+ struct rtattr *rta,
+ struct rtnexthop *rtnh,
+ struct rtmsg *rtmsg,
+ union g_addr **src)
{
- struct nexthop_label *nh_label;
- mpls_lse_t out_lse[MPLS_MAX_LABELS];
- char label_buf[100];
-
- rtnh->rtnh_len = sizeof (*rtnh);
- rtnh->rtnh_flags = 0;
- rtnh->rtnh_hops = 0;
- rta->rta_len += rtnh->rtnh_len;
-
- /*
- * label_buf is *only* currently used within debugging.
- * As such when we assign it we are guarding it inside
- * a debug test. If you want to change this make sure
- * you fix this assumption
- */
- label_buf[0] = '\0';
- /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
- * (in the case of LER)
- */
- nh_label = nexthop->nh_label;
- if (rtmsg->rtm_family == AF_MPLS)
- {
- assert (nh_label);
- assert (nh_label->num_labels == 1);
- }
-
- if (nh_label && nh_label->num_labels)
- {
- int i, num_labels = 0;
- u_int32_t bos;
- char label_buf1[20];
-
- for (i = 0; i < nh_label->num_labels; i++)
- {
- if (nh_label->label[i] != MPLS_IMP_NULL_LABEL)
- {
- bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0);
- out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos);
- if (IS_ZEBRA_DEBUG_KERNEL)
- {
- if (!num_labels)
- sprintf (label_buf, "label %d", nh_label->label[i]);
- else
- {
- sprintf (label_buf1, "/%d", nh_label->label[i]);
- strcat (label_buf, label_buf1);
- }
+ struct nexthop_label *nh_label;
+ mpls_lse_t out_lse[MPLS_MAX_LABELS];
+ char label_buf[100];
+
+ rtnh->rtnh_len = sizeof(*rtnh);
+ rtnh->rtnh_flags = 0;
+ rtnh->rtnh_hops = 0;
+ rta->rta_len += rtnh->rtnh_len;
+
+ /*
+ * label_buf is *only* currently used within debugging.
+ * As such when we assign it we are guarding it inside
+ * a debug test. If you want to change this make sure
+ * you fix this assumption
+ */
+ label_buf[0] = '\0';
+ /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
+ * (in the case of LER)
+ */
+ nh_label = nexthop->nh_label;
+ if (rtmsg->rtm_family == AF_MPLS) {
+ assert(nh_label);
+ assert(nh_label->num_labels == 1);
+ }
+
+ if (nh_label && nh_label->num_labels) {
+ int i, num_labels = 0;
+ u_int32_t bos;
+ char label_buf1[20];
+
+ for (i = 0; i < nh_label->num_labels; i++) {
+ if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) {
+ bos = ((i == (nh_label->num_labels - 1)) ? 1
+ : 0);
+ out_lse[i] = mpls_lse_encode(nh_label->label[i],
+ 0, 0, bos);
+ if (IS_ZEBRA_DEBUG_KERNEL) {
+ if (!num_labels)
+ sprintf(label_buf, "label %d",
+ nh_label->label[i]);
+ else {
+ sprintf(label_buf1, "/%d",
+ nh_label->label[i]);
+ strcat(label_buf, label_buf1);
+ }
+ }
+ num_labels++;
+ }
+ }
+ if (num_labels) {
+ if (rtmsg->rtm_family == AF_MPLS) {
+ rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_NEWDST,
+ &out_lse,
+ num_labels * sizeof(mpls_lse_t));
+ rtnh->rtnh_len += RTA_LENGTH(
+ num_labels * sizeof(mpls_lse_t));
+ } else {
+ struct rtattr *nest;
+ u_int16_t encap = LWTUNNEL_ENCAP_MPLS;
+ int len = rta->rta_len;
+
+ rta_addattr_l(rta, NL_PKT_BUF_SIZE,
+ RTA_ENCAP_TYPE, &encap,
+ sizeof(u_int16_t));
+ nest = rta_nest(rta, NL_PKT_BUF_SIZE,
+ RTA_ENCAP);
+ rta_addattr_l(rta, NL_PKT_BUF_SIZE,
+ MPLS_IPTUNNEL_DST, &out_lse,
+ num_labels * sizeof(mpls_lse_t));
+ rta_nest_end(rta, nest);
+ rtnh->rtnh_len += rta->rta_len - len;
+ }
}
- num_labels++;
- }
- }
- if (num_labels)
- {
- if (rtmsg->rtm_family == AF_MPLS)
- {
- rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_NEWDST,
- &out_lse, num_labels * sizeof(mpls_lse_t));
- rtnh->rtnh_len += RTA_LENGTH (num_labels * sizeof(mpls_lse_t));
- }
- else
- {
- struct rtattr *nest;
- u_int16_t encap = LWTUNNEL_ENCAP_MPLS;
- int len = rta->rta_len;
-
- rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_ENCAP_TYPE,
- &encap, sizeof (u_int16_t));
- nest = rta_nest(rta, NL_PKT_BUF_SIZE, RTA_ENCAP);
- rta_addattr_l (rta, NL_PKT_BUF_SIZE, MPLS_IPTUNNEL_DST,
- &out_lse, num_labels * sizeof(mpls_lse_t));
- rta_nest_end(rta, nest);
- rtnh->rtnh_len += rta->rta_len - len;
- }
- }
- }
-
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
- rtnh->rtnh_flags |= RTNH_F_ONLINK;
-
- if (rtmsg->rtm_family == AF_INET &&
- (nexthop->type == NEXTHOP_TYPE_IPV6
- || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX))
- {
- bytelen = 4;
- rtnh->rtnh_flags |= RTNH_F_ONLINK;
- rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
- &ipv4_ll, bytelen);
- rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
- rtnh->rtnh_ifindex = nexthop->ifindex;
-
- if (nexthop->rmap_src.ipv4.s_addr)
- *src = &nexthop->rmap_src;
- else if (nexthop->src.ipv4.s_addr)
- *src = &nexthop->src;
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(" 5549: netlink_route_build_multipath() (%s): "
- "nexthop via %s %s if %u",
- routedesc, ipv4_ll_buf, label_buf, nexthop->ifindex);
- return;
- }
-
- if (nexthop->type == NEXTHOP_TYPE_IPV4
- || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
- {
- _netlink_route_rta_add_gateway_info (rtmsg->rtm_family, AF_INET, rta,
- rtnh, NL_PKT_BUF_SIZE, bytelen, nexthop);
- if (nexthop->rmap_src.ipv4.s_addr)
- *src = &nexthop->rmap_src;
- else if (nexthop->src.ipv4.s_addr)
- *src = &nexthop->src;
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("netlink_route_multipath() (%s): "
- "nexthop via %s %s if %u",
- routedesc,
- inet_ntoa (nexthop->gate.ipv4),
- label_buf, nexthop->ifindex);
- }
- if (nexthop->type == NEXTHOP_TYPE_IPV6
- || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
- {
- _netlink_route_rta_add_gateway_info (rtmsg->rtm_family, AF_INET6, rta,
- rtnh, NL_PKT_BUF_SIZE, bytelen, nexthop);
-
- if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
- *src = &nexthop->rmap_src;
- else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
- *src = &nexthop->src;
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("netlink_route_multipath() (%s): "
- "nexthop via %s %s if %u",
- routedesc,
- inet6_ntoa (nexthop->gate.ipv6),
- label_buf, nexthop->ifindex);
- }
- /* ifindex */
- if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
- || nexthop->type == NEXTHOP_TYPE_IFINDEX)
- {
- rtnh->rtnh_ifindex = nexthop->ifindex;
-
- if (nexthop->rmap_src.ipv4.s_addr)
- *src = &nexthop->rmap_src;
- else if (nexthop->src.ipv4.s_addr)
- *src = &nexthop->src;
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("netlink_route_multipath() (%s): "
- "nexthop via if %u", routedesc, nexthop->ifindex);
- }
- else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
- {
- rtnh->rtnh_ifindex = nexthop->ifindex;
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("netlink_route_multipath() (%s): "
- "nexthop via if %u", routedesc, nexthop->ifindex);
- }
- else
- {
- rtnh->rtnh_ifindex = 0;
- }
+ }
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
+ rtnh->rtnh_flags |= RTNH_F_ONLINK;
+
+ if (rtmsg->rtm_family == AF_INET
+ && (nexthop->type == NEXTHOP_TYPE_IPV6
+ || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) {
+ bytelen = 4;
+ rtnh->rtnh_flags |= RTNH_F_ONLINK;
+ rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_GATEWAY, &ipv4_ll,
+ bytelen);
+ rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
+ rtnh->rtnh_ifindex = nexthop->ifindex;
+
+ if (nexthop->rmap_src.ipv4.s_addr)
+ *src = &nexthop->rmap_src;
+ else if (nexthop->src.ipv4.s_addr)
+ *src = &nexthop->src;
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ " 5549: netlink_route_build_multipath() (%s): "
+ "nexthop via %s %s if %u",
+ routedesc, ipv4_ll_buf, label_buf,
+ nexthop->ifindex);
+ return;
+ }
+
+ if (nexthop->type == NEXTHOP_TYPE_IPV4
+ || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
+ _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET,
+ rta, rtnh, NL_PKT_BUF_SIZE,
+ bytelen, nexthop);
+ if (nexthop->rmap_src.ipv4.s_addr)
+ *src = &nexthop->rmap_src;
+ else if (nexthop->src.ipv4.s_addr)
+ *src = &nexthop->src;
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "netlink_route_multipath() (%s): "
+ "nexthop via %s %s if %u",
+ routedesc, inet_ntoa(nexthop->gate.ipv4),
+ label_buf, nexthop->ifindex);
+ }
+ if (nexthop->type == NEXTHOP_TYPE_IPV6
+ || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
+ _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET6,
+ rta, rtnh, NL_PKT_BUF_SIZE,
+ bytelen, nexthop);
+
+ if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
+ *src = &nexthop->rmap_src;
+ else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
+ *src = &nexthop->src;
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "netlink_route_multipath() (%s): "
+ "nexthop via %s %s if %u",
+ routedesc, inet6_ntoa(nexthop->gate.ipv6),
+ label_buf, nexthop->ifindex);
+ }
+ /* ifindex */
+ if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
+ || nexthop->type == NEXTHOP_TYPE_IFINDEX) {
+ rtnh->rtnh_ifindex = nexthop->ifindex;
+
+ if (nexthop->rmap_src.ipv4.s_addr)
+ *src = &nexthop->rmap_src;
+ else if (nexthop->src.ipv4.s_addr)
+ *src = &nexthop->src;
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "netlink_route_multipath() (%s): "
+ "nexthop via if %u",
+ routedesc, nexthop->ifindex);
+ } else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
+ rtnh->rtnh_ifindex = nexthop->ifindex;
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "netlink_route_multipath() (%s): "
+ "nexthop via if %u",
+ routedesc, nexthop->ifindex);
+ } else {
+ rtnh->rtnh_ifindex = 0;
+ }
}
-static inline void
-_netlink_mpls_build_singlepath(
- const char *routedesc,
- zebra_nhlfe_t *nhlfe,
- struct nlmsghdr *nlmsg,
- struct rtmsg *rtmsg,
- size_t req_size,
- int cmd)
+static inline void _netlink_mpls_build_singlepath(const char *routedesc,
+ zebra_nhlfe_t *nhlfe,
+ struct nlmsghdr *nlmsg,
+ struct rtmsg *rtmsg,
+ size_t req_size, int cmd)
{
- int bytelen;
- u_char family;
+ int bytelen;
+ u_char family;
- family = NHLFE_FAMILY (nhlfe);
- bytelen = (family == AF_INET ? 4 : 16);
- _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop,
- nlmsg, rtmsg, req_size, cmd);
+ family = NHLFE_FAMILY(nhlfe);
+ bytelen = (family == AF_INET ? 4 : 16);
+ _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop,
+ nlmsg, rtmsg, req_size, cmd);
}
static inline void
-_netlink_mpls_build_multipath(
- const char *routedesc,
- zebra_nhlfe_t *nhlfe,
- struct rtattr *rta,
- struct rtnexthop *rtnh,
- struct rtmsg *rtmsg,
- union g_addr **src)
+_netlink_mpls_build_multipath(const char *routedesc, zebra_nhlfe_t *nhlfe,
+ struct rtattr *rta, struct rtnexthop *rtnh,
+ struct rtmsg *rtmsg, union g_addr **src)
{
- int bytelen;
- u_char family;
+ int bytelen;
+ u_char family;
- family = NHLFE_FAMILY (nhlfe);
- bytelen = (family == AF_INET ? 4 : 16);
- _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop,
- rta, rtnh, rtmsg, src);
+ family = NHLFE_FAMILY(nhlfe);
+ bytelen = (family == AF_INET ? 4 : 16);
+ _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop, rta,
+ rtnh, rtmsg, src);
}
@@ -1164,1316 +1134,1311 @@ _netlink_mpls_build_multipath(
* (recursive, multipath, etc.)
* @param family: Address family which the change concerns
*/
-static void
-_netlink_route_debug(
- int cmd,
- struct prefix *p,
- struct nexthop *nexthop,
- const char *routedesc,
- int family,
- struct zebra_vrf *zvrf)
+static void _netlink_route_debug(int cmd, struct prefix *p,
+ struct nexthop *nexthop, const char *routedesc,
+ int family, struct zebra_vrf *zvrf)
{
- if (IS_ZEBRA_DEBUG_KERNEL)
- {
- char buf[PREFIX_STRLEN];
- zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
- routedesc,
- nl_msg_type_to_str (cmd),
- prefix2str (p, buf, sizeof(buf)), zvrf_id (zvrf),
- (nexthop) ? nexthop_type_to_str (nexthop->type) : "UNK");
- }
- }
-
-static void
-_netlink_mpls_debug(
- int cmd,
- u_int32_t label,
- const char *routedesc)
+ if (IS_ZEBRA_DEBUG_KERNEL) {
+ char buf[PREFIX_STRLEN];
+ zlog_debug(
+ "netlink_route_multipath() (%s): %s %s vrf %u type %s",
+ routedesc, nl_msg_type_to_str(cmd),
+ prefix2str(p, buf, sizeof(buf)), zvrf_id(zvrf),
+ (nexthop) ? nexthop_type_to_str(nexthop->type) : "UNK");
+ }
+}
+
+static void _netlink_mpls_debug(int cmd, u_int32_t label, const char *routedesc)
{
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("netlink_mpls_multipath() (%s): %s %u/20",
- routedesc, nl_msg_type_to_str (cmd), label);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("netlink_mpls_multipath() (%s): %s %u/20", routedesc,
+ nl_msg_type_to_str(cmd), label);
}
-static int
-netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen)
+static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
+ int llalen)
{
- struct {
- struct nlmsghdr n;
- struct ndmsg ndm;
- char buf[256];
- } req;
+ struct {
+ struct nlmsghdr n;
+ struct ndmsg ndm;
+ char buf[256];
+ } req;
- struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
- memset(&req.n, 0, sizeof(req.n));
- memset(&req.ndm, 0, sizeof(req.ndm));
+ memset(&req.n, 0, sizeof(req.n));
+ memset(&req.ndm, 0, sizeof(req.ndm));
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
- req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
- req.n.nlmsg_type = cmd; //RTM_NEWNEIGH or RTM_DELNEIGH
- req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
+ req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
+ req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
+ req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
- req.ndm.ndm_family = AF_INET;
- req.ndm.ndm_state = NUD_PERMANENT;
- req.ndm.ndm_ifindex = ifindex;
- req.ndm.ndm_type = RTN_UNICAST;
+ req.ndm.ndm_family = AF_INET;
+ req.ndm.ndm_state = NUD_PERMANENT;
+ req.ndm.ndm_ifindex = ifindex;
+ req.ndm.ndm_type = RTN_UNICAST;
- addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
- addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, 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, 0);
+ return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
+ 0);
}
/* Routing table change via netlink interface. */
/* Update flag indicates whether this is a "replace" or not. */
-static int
-netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
- struct route_entry *re, int update)
+static int netlink_route_multipath(int cmd, struct prefix *p,
+ struct prefix *src_p, struct route_entry *re,
+ int update)
{
- int bytelen;
- struct sockaddr_nl snl;
- struct nexthop *nexthop = NULL;
- unsigned int nexthop_num;
- int discard;
- int family = PREFIX_FAMILY(p);
- const char *routedesc;
- int setsrc = 0;
- union g_addr src;
-
- struct
- {
- struct nlmsghdr n;
- struct rtmsg r;
- char buf[NL_PKT_BUF_SIZE];
- } req;
-
- struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
- struct zebra_vrf *zvrf = vrf_info_lookup (re->vrf_id);
-
- memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
-
- bytelen = (family == AF_INET ? 4 : 16);
-
- req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
- req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
- if ((cmd == RTM_NEWROUTE) && update)
- req.n.nlmsg_flags |= NLM_F_REPLACE;
- req.n.nlmsg_type = cmd;
- req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
-
- req.r.rtm_family = family;
- req.r.rtm_dst_len = p->prefixlen;
- req.r.rtm_src_len = src_p ? src_p->prefixlen : 0;
- req.r.rtm_protocol = get_rt_proto(re->type);
- req.r.rtm_scope = RT_SCOPE_UNIVERSE;
-
- if ((re->flags & ZEBRA_FLAG_BLACKHOLE) || (re->flags & ZEBRA_FLAG_REJECT))
- discard = 1;
- else
- discard = 0;
-
- if (cmd == RTM_NEWROUTE)
- {
- if (discard)
- {
- if (re->flags & ZEBRA_FLAG_BLACKHOLE)
- req.r.rtm_type = RTN_BLACKHOLE;
- else if (re->flags & ZEBRA_FLAG_REJECT)
- req.r.rtm_type = RTN_UNREACHABLE;
- else
- assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
- }
- else
- req.r.rtm_type = RTN_UNICAST;
- }
-
- addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
- if (src_p)
- addattr_l (&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, bytelen);
-
- /* Metric. */
- /* Hardcode the metric for all routes coming from zebra. Metric isn't used
- * either by the kernel or by zebra. Its purely for calculating best path(s)
- * by the routing protocol and for communicating with protocol peers.
- */
- addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
-
- /* Table corresponding to this route. */
- if (re->table < 256)
- req.r.rtm_table = re->table;
- else
- {
- req.r.rtm_table = RT_TABLE_UNSPEC;
- addattr32(&req.n, sizeof req, RTA_TABLE, re->table);
- }
-
- if (re->mtu || re->nexthop_mtu)
- {
- char buf[NL_PKT_BUF_SIZE];
- struct rtattr *rta = (void *) buf;
- u_int32_t mtu = re->mtu;
- if (!mtu || (re->nexthop_mtu && re->nexthop_mtu < mtu))
- mtu = re->nexthop_mtu;
- rta->rta_type = RTA_METRICS;
- rta->rta_len = RTA_LENGTH(0);
- rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu);
- addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta),
- RTA_PAYLOAD (rta));
- }
-
- if (discard)
- {
- if (cmd == RTM_NEWROUTE)
- for (ALL_NEXTHOPS(re->nexthop, nexthop))
- {
- /* We shouldn't encounter recursive nexthops on discard routes,
- * but it is probably better to handle that case correctly anyway.
- */
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- continue;
- }
- goto skip;
- }
-
- /* Count overall nexthops so we can decide whether to use singlepath
- * or multipath case. */
- nexthop_num = 0;
- for (ALL_NEXTHOPS(re->nexthop, nexthop))
- {
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- continue;
- if (cmd == RTM_NEWROUTE && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- continue;
- if (cmd == RTM_DELROUTE && !CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
- continue;
-
- nexthop_num++;
- }
-
- /* Singlepath case. */
- if (nexthop_num == 1 || multipath_num == 1)
- {
- nexthop_num = 0;
- for (ALL_NEXTHOPS(re->nexthop, nexthop))
- {
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- {
- if (!setsrc)
- {
- if (family == AF_INET)
- {
- if (nexthop->rmap_src.ipv4.s_addr != 0)
- {
- src.ipv4 = nexthop->rmap_src.ipv4;
- setsrc = 1;
- }
- else if (nexthop->src.ipv4.s_addr != 0)
- {
- src.ipv4 = nexthop->src.ipv4;
- setsrc = 1;
- }
- }
- else if (family == AF_INET6)
- {
- if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
- {
- src.ipv6 = nexthop->rmap_src.ipv6;
- setsrc = 1;
- }
- else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
- {
- src.ipv6 = nexthop->src.ipv6;
- setsrc = 1;
- }
- }
- }
- continue;
- }
-
- if ((cmd == RTM_NEWROUTE
- && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- || (cmd == RTM_DELROUTE
- && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
- {
- routedesc = nexthop->rparent ? "recursive, 1 hop" : "single hop";
-
- _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf);
- _netlink_route_build_singlepath(routedesc, bytelen,
- nexthop, &req.n, &req.r,
- sizeof req, cmd);
- nexthop_num++;
- break;
- }
- }
- if (setsrc && (cmd == RTM_NEWROUTE))
- {
- if (family == AF_INET)
- addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen);
- else if (family == AF_INET6)
- addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen);
+ int bytelen;
+ struct sockaddr_nl snl;
+ struct nexthop *nexthop = NULL;
+ unsigned int nexthop_num;
+ int discard;
+ int family = PREFIX_FAMILY(p);
+ const char *routedesc;
+ int setsrc = 0;
+ union g_addr src;
+
+ struct {
+ struct nlmsghdr n;
+ struct rtmsg r;
+ char buf[NL_PKT_BUF_SIZE];
+ } req;
+
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+ struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
+
+ memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE);
+
+ bytelen = (family == AF_INET ? 4 : 16);
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
+ if ((cmd == RTM_NEWROUTE) && update)
+ req.n.nlmsg_flags |= NLM_F_REPLACE;
+ req.n.nlmsg_type = cmd;
+ req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
+
+ req.r.rtm_family = family;
+ req.r.rtm_dst_len = p->prefixlen;
+ req.r.rtm_src_len = src_p ? src_p->prefixlen : 0;
+ req.r.rtm_protocol = get_rt_proto(re->type);
+ req.r.rtm_scope = RT_SCOPE_UNIVERSE;
+
+ if ((re->flags & ZEBRA_FLAG_BLACKHOLE)
+ || (re->flags & ZEBRA_FLAG_REJECT))
+ discard = 1;
+ else
+ discard = 0;
+
+ if (cmd == RTM_NEWROUTE) {
+ if (discard) {
+ if (re->flags & ZEBRA_FLAG_BLACKHOLE)
+ req.r.rtm_type = RTN_BLACKHOLE;
+ else if (re->flags & ZEBRA_FLAG_REJECT)
+ req.r.rtm_type = RTN_UNREACHABLE;
+ else
+ assert(RTN_BLACKHOLE
+ != RTN_UNREACHABLE); /* false */
+ } else
+ req.r.rtm_type = RTN_UNICAST;
}
- }
- else
- {
- char buf[NL_PKT_BUF_SIZE];
- struct rtattr *rta = (void *) buf;
- struct rtnexthop *rtnh;
- union g_addr *src1 = NULL;
-
- rta->rta_type = RTA_MULTIPATH;
- rta->rta_len = RTA_LENGTH (0);
- rtnh = RTA_DATA (rta);
-
- nexthop_num = 0;
- for (ALL_NEXTHOPS(re->nexthop, nexthop))
- {
- if (nexthop_num >= multipath_num)
- break;
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- {
- /* This only works for IPv4 now */
- if (!setsrc)
- {
- if (family == AF_INET)
- {
- if (nexthop->rmap_src.ipv4.s_addr != 0)
- {
- src.ipv4 = nexthop->rmap_src.ipv4;
- setsrc = 1;
- }
- else if (nexthop->src.ipv4.s_addr != 0)
- {
- src.ipv4 = nexthop->src.ipv4;
- setsrc = 1;
- }
- }
- else if (family == AF_INET6)
- {
- if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
- {
- src.ipv6 = nexthop->rmap_src.ipv6;
- setsrc = 1;
- }
- else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
- {
- src.ipv6 = nexthop->src.ipv6;
- setsrc = 1;
- }
- }
- }
- continue;
- }
-
- if ((cmd == RTM_NEWROUTE
- && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- || (cmd == RTM_DELROUTE
- && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
- {
- routedesc = nexthop->rparent ? "recursive, multihop" : "multihop";
- nexthop_num++;
-
- _netlink_route_debug(cmd, p, nexthop,
- routedesc, family, zvrf);
- _netlink_route_build_multipath(routedesc, bytelen,
- nexthop, rta, rtnh, &req.r, &src1);
- rtnh = RTNH_NEXT (rtnh);
-
- if (!setsrc && src1)
- {
- if (family == AF_INET)
- src.ipv4 = src1->ipv4;
- else if (family == AF_INET6)
- src.ipv6 = src1->ipv6;
- setsrc = 1;
- }
- }
- }
- if (setsrc && (cmd == RTM_NEWROUTE))
- {
- if (family == AF_INET)
- addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen);
- else if (family == AF_INET6)
- addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen);
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Setting source");
+ addattr_l(&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
+ if (src_p)
+ addattr_l(&req.n, sizeof req, RTA_SRC, &src_p->u.prefix,
+ bytelen);
+
+ /* Metric. */
+ /* Hardcode the metric for all routes coming from zebra. Metric isn't
+ * used
+ * either by the kernel or by zebra. Its purely for calculating best
+ * path(s)
+ * by the routing protocol and for communicating with protocol peers.
+ */
+ addattr32(&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
+
+ /* Table corresponding to this route. */
+ if (re->table < 256)
+ req.r.rtm_table = re->table;
+ else {
+ req.r.rtm_table = RT_TABLE_UNSPEC;
+ addattr32(&req.n, sizeof req, RTA_TABLE, re->table);
}
- if (rta->rta_len > RTA_LENGTH (0))
- addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
- RTA_PAYLOAD (rta));
- }
+ if (re->mtu || re->nexthop_mtu) {
+ char buf[NL_PKT_BUF_SIZE];
+ struct rtattr *rta = (void *)buf;
+ u_int32_t mtu = re->mtu;
+ if (!mtu || (re->nexthop_mtu && re->nexthop_mtu < mtu))
+ mtu = re->nexthop_mtu;
+ rta->rta_type = RTA_METRICS;
+ rta->rta_len = RTA_LENGTH(0);
+ rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu);
+ addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA(rta),
+ RTA_PAYLOAD(rta));
+ }
+
+ if (discard) {
+ if (cmd == RTM_NEWROUTE)
+ for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
+ /* We shouldn't encounter recursive nexthops on
+ * discard routes,
+ * but it is probably better to handle that case
+ * correctly anyway.
+ */
+ if (CHECK_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_RECURSIVE))
+ continue;
+ }
+ goto skip;
+ }
+
+ /* Count overall nexthops so we can decide whether to use singlepath
+ * or multipath case. */
+ nexthop_num = 0;
+ for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ continue;
+ if (cmd == RTM_NEWROUTE
+ && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ continue;
+ if (cmd == RTM_DELROUTE
+ && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
+ continue;
+
+ nexthop_num++;
+ }
+
+ /* Singlepath case. */
+ if (nexthop_num == 1 || multipath_num == 1) {
+ nexthop_num = 0;
+ for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
+ if (CHECK_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_RECURSIVE)) {
+ if (!setsrc) {
+ if (family == AF_INET) {
+ if (nexthop->rmap_src.ipv4
+ .s_addr
+ != 0) {
+ src.ipv4 =
+ nexthop->rmap_src
+ .ipv4;
+ setsrc = 1;
+ } else if (nexthop->src.ipv4
+ .s_addr
+ != 0) {
+ src.ipv4 =
+ nexthop->src
+ .ipv4;
+ setsrc = 1;
+ }
+ } else if (family == AF_INET6) {
+ if (!IN6_IS_ADDR_UNSPECIFIED(
+ &nexthop->rmap_src
+ .ipv6)) {
+ src.ipv6 =
+ nexthop->rmap_src
+ .ipv6;
+ setsrc = 1;
+ } else if (
+ !IN6_IS_ADDR_UNSPECIFIED(
+ &nexthop->src
+ .ipv6)) {
+ src.ipv6 =
+ nexthop->src
+ .ipv6;
+ setsrc = 1;
+ }
+ }
+ }
+ continue;
+ }
+
+ if ((cmd == RTM_NEWROUTE
+ && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ || (cmd == RTM_DELROUTE
+ && CHECK_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_FIB))) {
+ routedesc = nexthop->rparent
+ ? "recursive, 1 hop"
+ : "single hop";
+
+ _netlink_route_debug(cmd, p, nexthop, routedesc,
+ family, zvrf);
+ _netlink_route_build_singlepath(
+ routedesc, bytelen, nexthop, &req.n,
+ &req.r, sizeof req, cmd);
+ nexthop_num++;
+ break;
+ }
+ }
+ if (setsrc && (cmd == RTM_NEWROUTE)) {
+ if (family == AF_INET)
+ addattr_l(&req.n, sizeof req, RTA_PREFSRC,
+ &src.ipv4, bytelen);
+ else if (family == AF_INET6)
+ addattr_l(&req.n, sizeof req, RTA_PREFSRC,
+ &src.ipv6, bytelen);
+ }
+ } else {
+ char buf[NL_PKT_BUF_SIZE];
+ struct rtattr *rta = (void *)buf;
+ struct rtnexthop *rtnh;
+ union g_addr *src1 = NULL;
+
+ rta->rta_type = RTA_MULTIPATH;
+ rta->rta_len = RTA_LENGTH(0);
+ rtnh = RTA_DATA(rta);
+
+ nexthop_num = 0;
+ for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
+ if (nexthop_num >= multipath_num)
+ break;
+
+ if (CHECK_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_RECURSIVE)) {
+ /* This only works for IPv4 now */
+ if (!setsrc) {
+ if (family == AF_INET) {
+ if (nexthop->rmap_src.ipv4
+ .s_addr
+ != 0) {
+ src.ipv4 =
+ nexthop->rmap_src
+ .ipv4;
+ setsrc = 1;
+ } else if (nexthop->src.ipv4
+ .s_addr
+ != 0) {
+ src.ipv4 =
+ nexthop->src
+ .ipv4;
+ setsrc = 1;
+ }
+ } else if (family == AF_INET6) {
+ if (!IN6_IS_ADDR_UNSPECIFIED(
+ &nexthop->rmap_src
+ .ipv6)) {
+ src.ipv6 =
+ nexthop->rmap_src
+ .ipv6;
+ setsrc = 1;
+ } else if (
+ !IN6_IS_ADDR_UNSPECIFIED(
+ &nexthop->src
+ .ipv6)) {
+ src.ipv6 =
+ nexthop->src
+ .ipv6;
+ setsrc = 1;
+ }
+ }
+ }
+ continue;
+ }
+
+ if ((cmd == RTM_NEWROUTE
+ && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ || (cmd == RTM_DELROUTE
+ && CHECK_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_FIB))) {
+ routedesc = nexthop->rparent
+ ? "recursive, multihop"
+ : "multihop";
+ nexthop_num++;
+
+ _netlink_route_debug(cmd, p, nexthop, routedesc,
+ family, zvrf);
+ _netlink_route_build_multipath(
+ routedesc, bytelen, nexthop, rta, rtnh,
+ &req.r, &src1);
+ rtnh = RTNH_NEXT(rtnh);
+
+ if (!setsrc && src1) {
+ if (family == AF_INET)
+ src.ipv4 = src1->ipv4;
+ else if (family == AF_INET6)
+ src.ipv6 = src1->ipv6;
+
+ setsrc = 1;
+ }
+ }
+ }
+ if (setsrc && (cmd == RTM_NEWROUTE)) {
+ if (family == AF_INET)
+ addattr_l(&req.n, sizeof req, RTA_PREFSRC,
+ &src.ipv4, bytelen);
+ else if (family == AF_INET6)
+ addattr_l(&req.n, sizeof req, RTA_PREFSRC,
+ &src.ipv6, bytelen);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("Setting source");
+ }
+
+ if (rta->rta_len > RTA_LENGTH(0))
+ addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH,
+ RTA_DATA(rta), RTA_PAYLOAD(rta));
+ }
- /* If there is no useful nexthop then return. */
- if (nexthop_num == 0)
- {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("netlink_route_multipath(): No useful nexthop.");
- return 0;
- }
+ /* If there is no useful nexthop then return. */
+ if (nexthop_num == 0) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "netlink_route_multipath(): No useful nexthop.");
+ return 0;
+ }
skip:
- /* Destination netlink address. */
- memset (&snl, 0, sizeof snl);
- snl.nl_family = AF_NETLINK;
+ /* Destination netlink address. */
+ memset(&snl, 0, sizeof snl);
+ snl.nl_family = AF_NETLINK;
- /* Talk to netlink socket. */
- return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
+ /* Talk to netlink socket. */
+ return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
+ 0);
}
-int
-kernel_get_ipmr_sg_stats (void *in)
+int kernel_get_ipmr_sg_stats(void *in)
{
- int suc = 0;
- struct mcast_route_data *mr = (struct mcast_route_data *)in;
- struct {
- struct nlmsghdr n;
- struct ndmsg ndm;
- char buf[256];
- } req;
+ int suc = 0;
+ struct mcast_route_data *mr = (struct mcast_route_data *)in;
+ struct {
+ struct nlmsghdr n;
+ struct ndmsg ndm;
+ char buf[256];
+ } req;
- mroute = mr;
- struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
+ mroute = mr;
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
- memset(&req.n, 0, sizeof(req.n));
- memset(&req.ndm, 0, sizeof(req.ndm));
+ memset(&req.n, 0, sizeof(req.n));
+ memset(&req.ndm, 0, sizeof(req.ndm));
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
- req.n.nlmsg_flags = NLM_F_REQUEST;
- req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
- req.ndm.ndm_family = AF_INET;
- req.n.nlmsg_type = RTM_GETROUTE;
+ req.ndm.ndm_family = AF_INET;
+ req.n.nlmsg_type = RTM_GETROUTE;
- addattr_l (&req.n, sizeof (req), RTA_IIF, &mroute->ifindex, 4);
- addattr_l (&req.n, sizeof (req), RTA_OIF, &mroute->ifindex, 4);
- 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);
+ addattr_l(&req.n, sizeof(req), RTA_IIF, &mroute->ifindex, 4);
+ addattr_l(&req.n, sizeof(req), RTA_OIF, &mroute->ifindex, 4);
+ 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, 0);
+ suc = netlink_talk(netlink_route_change_read_multicast, &req.n,
+ &zns->netlink_cmd, zns, 0);
- mroute = NULL;
- return suc;
+ mroute = NULL;
+ return suc;
}
-int
-kernel_route_rib (struct prefix *p, struct prefix *src_p,
- struct route_entry *old, struct route_entry *new)
+int kernel_route_rib(struct prefix *p, struct prefix *src_p,
+ struct route_entry *old, struct route_entry *new)
{
- if (!old && new)
- return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 0);
- if (old && !new)
- return netlink_route_multipath (RTM_DELROUTE, p, src_p, old, 0);
+ if (!old && new)
+ return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 0);
+ if (old && !new)
+ return netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0);
- return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 1);
+ return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 1);
}
-int
-kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen)
+int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
+ int llalen)
{
- return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex, addr,
- lla, llalen);
+ return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex,
+ addr, lla, llalen);
}
/*
* Add remote VTEP to the flood list for this VxLAN interface (VNI). This
* is done by adding an FDB entry with a MAC of 00:00:00:00:00:00.
*/
-static int
-netlink_vxlan_flood_list_update (struct interface *ifp,
- struct in_addr *vtep_ip,
- int cmd)
+static int netlink_vxlan_flood_list_update(struct interface *ifp,
+ struct in_addr *vtep_ip, int cmd)
{
- struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
- struct
- {
- struct nlmsghdr n;
- struct ndmsg ndm;
- char buf[256];
- } req;
- u_char dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
-
- memset(&req.n, 0, sizeof(req.n));
- memset(&req.ndm, 0, sizeof(req.ndm));
-
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
- req.n.nlmsg_flags = NLM_F_REQUEST;
- if (cmd == RTM_NEWNEIGH)
- req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_APPEND);
- req.n.nlmsg_type = cmd;
- req.ndm.ndm_family = PF_BRIDGE;
- req.ndm.ndm_state = NUD_NOARP | NUD_PERMANENT;
- req.ndm.ndm_flags |= NTF_SELF; // Handle by "self", not "master"
-
-
- addattr_l (&req.n, sizeof (req), NDA_LLADDR, &dst_mac, 6);
- req.ndm.ndm_ifindex = ifp->ifindex;
- addattr_l (&req.n, sizeof (req), NDA_DST, &vtep_ip->s_addr, 4);
-
- return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+ struct {
+ struct nlmsghdr n;
+ struct ndmsg ndm;
+ char buf[256];
+ } req;
+ u_char dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+
+ memset(&req.n, 0, sizeof(req.n));
+ memset(&req.ndm, 0, sizeof(req.ndm));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ if (cmd == RTM_NEWNEIGH)
+ req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_APPEND);
+ req.n.nlmsg_type = cmd;
+ req.ndm.ndm_family = PF_BRIDGE;
+ req.ndm.ndm_state = NUD_NOARP | NUD_PERMANENT;
+ req.ndm.ndm_flags |= NTF_SELF; // Handle by "self", not "master"
+
+
+ addattr_l(&req.n, sizeof(req), NDA_LLADDR, &dst_mac, 6);
+ req.ndm.ndm_ifindex = ifp->ifindex;
+ addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip->s_addr, 4);
+
+ return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
+ 0);
}
/*
- * Add remote VTEP for this VxLAN interface (VNI). In Linux, this involves adding
+ * Add remote VTEP for this VxLAN interface (VNI). In Linux, this involves
+ * adding
* a "flood" MAC FDB entry.
*/
-int
-kernel_add_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
+int kernel_add_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
{
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug ("Install %s into flood list for VNI %u intf %s(%u)",
- inet_ntoa (*vtep_ip), vni, ifp->name, ifp->ifindex);
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Install %s into flood list for VNI %u intf %s(%u)",
+ inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex);
- return netlink_vxlan_flood_list_update (ifp, vtep_ip, RTM_NEWNEIGH);
+ return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_NEWNEIGH);
}
/*
* Remove remote VTEP for this VxLAN interface (VNI). In Linux, this involves
* deleting the "flood" MAC FDB entry.
*/
-int
-kernel_del_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
+int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
{
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug ("Uninstall %s from flood list for VNI %u intf %s(%u)",
- inet_ntoa (*vtep_ip), vni, ifp->name, ifp->ifindex);
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "Uninstall %s from flood list for VNI %u intf %s(%u)",
+ inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex);
- return netlink_vxlan_flood_list_update (ifp, vtep_ip, RTM_DELNEIGH);
+ return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_DELNEIGH);
}
#ifndef NDA_RTA
-#define NDA_RTA(r) \
- ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
+#define NDA_RTA(r) \
+ ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
#endif
-static int
-netlink_macfdb_change (struct sockaddr_nl *snl, struct nlmsghdr *h, int len)
+static int netlink_macfdb_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
+ int len)
{
- struct ndmsg *ndm;
- struct interface *ifp;
- struct zebra_if *zif;
- struct zebra_vrf *zvrf;
- struct rtattr *tb[NDA_MAX + 1];
- struct interface *br_if;
- struct ethaddr mac;
- vlanid_t vid = 0;
- struct prefix vtep_ip;
- int vid_present = 0, dst_present = 0;
- char buf[ETHER_ADDR_STRLEN];
- char vid_buf[20];
- char dst_buf[30];
- u_char sticky = 0;
-
- ndm = NLMSG_DATA (h);
-
- /* The interface should exist. */
- ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ndm->ndm_ifindex);
- if (!ifp)
- return 0;
-
- /* Locate VRF corresponding to interface. We only process MAC notifications
- * if EVPN is enabled on this VRF.
- */
- zvrf = vrf_info_lookup(ifp->vrf_id);
- if (!zvrf || !EVPN_ENABLED(zvrf))
- return 0;
- if (!ifp->info)
- return 0;
-
- /* The interface should be something we're interested in. */
- if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
- return 0;
-
- /* Drop "permanent" entries. */
- if (ndm->ndm_state & NUD_PERMANENT)
- return 0;
-
- zif = (struct zebra_if *)ifp->info;
- if ((br_if = zif->brslave_info.br_if) == NULL)
- {
- zlog_warn ("%s family %s IF %s(%u) brIF %u - no bridge master",
- nl_msg_type_to_str (h->nlmsg_type),
- nl_family_to_str (ndm->ndm_family),
- ifp->name, ndm->ndm_ifindex,
- zif->brslave_info.bridge_ifindex);
- return 0;
- }
-
- /* Parse attributes and extract fields of interest. */
- memset (tb, 0, sizeof tb);
- netlink_parse_rtattr (tb, NDA_MAX, NDA_RTA (ndm), len);
-
- if (!tb[NDA_LLADDR])
- {
- zlog_warn ("%s family %s IF %s(%u) brIF %u - no LLADDR",
- nl_msg_type_to_str (h->nlmsg_type),
- nl_family_to_str (ndm->ndm_family),
- ifp->name, ndm->ndm_ifindex,
- zif->brslave_info.bridge_ifindex);
- return 0;
- }
-
- if (RTA_PAYLOAD (tb[NDA_LLADDR]) != ETHER_ADDR_LEN)
- {
- zlog_warn ("%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %ld",
- nl_msg_type_to_str (h->nlmsg_type),
- nl_family_to_str (ndm->ndm_family),
- ifp->name, ndm->ndm_ifindex,
- zif->brslave_info.bridge_ifindex,
- RTA_PAYLOAD (tb[NDA_LLADDR]));
- return 0;
- }
-
- memcpy (&mac, RTA_DATA (tb[NDA_LLADDR]), ETHER_ADDR_LEN);
-
- if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN])
- {
- vid_present = 1;
- vid = *(u_int16_t *) RTA_DATA(tb[NDA_VLAN]);
- sprintf (vid_buf, " VLAN %u", vid);
- }
-
- if (tb[NDA_DST])
- {
- /* TODO: Only IPv4 supported now. */
- dst_present = 1;
- vtep_ip.family = AF_INET;
- vtep_ip.prefixlen = IPV4_MAX_BITLEN;
- memcpy (&(vtep_ip.u.prefix4.s_addr), RTA_DATA (tb[NDA_DST]), IPV4_MAX_BYTELEN);
- sprintf (dst_buf, " dst %s", inet_ntoa (vtep_ip.u.prefix4));
- }
-
- sticky = (ndm->ndm_state & NUD_NOARP) ? 1 : 0;
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("Rx %s family %s IF %s(%u)%s %sMAC %s%s",
- nl_msg_type_to_str (h->nlmsg_type),
- nl_family_to_str (ndm->ndm_family),
- ifp->name, ndm->ndm_ifindex,
- vid_present ? vid_buf : "",
- sticky ? "sticky " : "",
- prefix_mac2str (&mac, buf, sizeof (buf)),
- dst_present ? dst_buf: "");
-
- if (filter_vlan && vid != filter_vlan)
- return 0;
-
- /* If add or update, do accordingly if learnt on a "local" interface; if
- * the notification is over VxLAN, this has to be related to multi-homing,
- * so perform an implicit delete of any local entry (if it exists).
- */
- if (h->nlmsg_type == RTM_NEWNEIGH)
- {
- /* Drop "permanent" entries. */
- if (ndm->ndm_state & NUD_PERMANENT)
- return 0;
-
- if (IS_ZEBRA_IF_VXLAN(ifp))
- return zebra_vxlan_check_del_local_mac (ifp, br_if, &mac, vid);
-
- return zebra_vxlan_local_mac_add_update (ifp, br_if, &mac, vid, sticky);
- }
-
- /* This is a delete notification.
- * 1. For a MAC over VxLan, check if it needs to be refreshed(readded)
- * 2. For a MAC over "local" interface, delete the mac
- * Note: We will get notifications from both bridge driver and VxLAN driver.
- * Ignore the notification from VxLan driver as it is also generated
- * when mac moves from remote to local.
- */
- if (dst_present)
- return 0;
-
- if (IS_ZEBRA_IF_VXLAN(ifp))
- return zebra_vxlan_check_readd_remote_mac (ifp, br_if, &mac, vid);
-
- return zebra_vxlan_local_mac_del (ifp, br_if, &mac, vid);
+ struct ndmsg *ndm;
+ struct interface *ifp;
+ struct zebra_if *zif;
+ struct zebra_vrf *zvrf;
+ struct rtattr *tb[NDA_MAX + 1];
+ struct interface *br_if;
+ struct ethaddr mac;
+ vlanid_t vid = 0;
+ struct prefix vtep_ip;
+ int vid_present = 0, dst_present = 0;
+ char buf[ETHER_ADDR_STRLEN];
+ char vid_buf[20];
+ char dst_buf[30];
+ u_char sticky = 0;
+
+ ndm = NLMSG_DATA(h);
+
+ /* The interface should exist. */
+ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+ ndm->ndm_ifindex);
+ if (!ifp)
+ return 0;
+
+ /* Locate VRF corresponding to interface. We only process MAC
+ * notifications
+ * if EVPN is enabled on this VRF.
+ */
+ zvrf = vrf_info_lookup(ifp->vrf_id);
+ if (!zvrf || !EVPN_ENABLED(zvrf))
+ return 0;
+ if (!ifp->info)
+ return 0;
+
+ /* The interface should be something we're interested in. */
+ if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
+ return 0;
+
+ /* Drop "permanent" entries. */
+ if (ndm->ndm_state & NUD_PERMANENT)
+ return 0;
+
+ zif = (struct zebra_if *)ifp->info;
+ if ((br_if = zif->brslave_info.br_if) == NULL) {
+ zlog_warn("%s family %s IF %s(%u) brIF %u - no bridge master",
+ nl_msg_type_to_str(h->nlmsg_type),
+ nl_family_to_str(ndm->ndm_family), ifp->name,
+ ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex);
+ return 0;
+ }
+
+ /* Parse attributes and extract fields of interest. */
+ memset(tb, 0, sizeof tb);
+ netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
+
+ if (!tb[NDA_LLADDR]) {
+ zlog_warn("%s family %s IF %s(%u) brIF %u - no LLADDR",
+ nl_msg_type_to_str(h->nlmsg_type),
+ nl_family_to_str(ndm->ndm_family), ifp->name,
+ ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex);
+ return 0;
+ }
+
+ if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETHER_ADDR_LEN) {
+ zlog_warn(
+ "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %ld",
+ nl_msg_type_to_str(h->nlmsg_type),
+ nl_family_to_str(ndm->ndm_family), ifp->name,
+ ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex,
+ RTA_PAYLOAD(tb[NDA_LLADDR]));
+ return 0;
+ }
+
+ memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETHER_ADDR_LEN);
+
+ if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN]) {
+ vid_present = 1;
+ vid = *(u_int16_t *)RTA_DATA(tb[NDA_VLAN]);
+ sprintf(vid_buf, " VLAN %u", vid);
+ }
+
+ if (tb[NDA_DST]) {
+ /* TODO: Only IPv4 supported now. */
+ dst_present = 1;
+ vtep_ip.family = AF_INET;
+ vtep_ip.prefixlen = IPV4_MAX_BITLEN;
+ memcpy(&(vtep_ip.u.prefix4.s_addr), RTA_DATA(tb[NDA_DST]),
+ IPV4_MAX_BYTELEN);
+ sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip.u.prefix4));
+ }
+
+ sticky = (ndm->ndm_state & NUD_NOARP) ? 1 : 0;
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("Rx %s family %s IF %s(%u)%s %sMAC %s%s",
+ nl_msg_type_to_str(h->nlmsg_type),
+ nl_family_to_str(ndm->ndm_family), ifp->name,
+ ndm->ndm_ifindex, vid_present ? vid_buf : "",
+ sticky ? "sticky " : "",
+ prefix_mac2str(&mac, buf, sizeof(buf)),
+ dst_present ? dst_buf : "");
+
+ if (filter_vlan && vid != filter_vlan)
+ return 0;
+
+ /* If add or update, do accordingly if learnt on a "local" interface; if
+ * the notification is over VxLAN, this has to be related to
+ * multi-homing,
+ * so perform an implicit delete of any local entry (if it exists).
+ */
+ if (h->nlmsg_type == RTM_NEWNEIGH) {
+ /* Drop "permanent" entries. */
+ if (ndm->ndm_state & NUD_PERMANENT)
+ return 0;
+
+ if (IS_ZEBRA_IF_VXLAN(ifp))
+ return zebra_vxlan_check_del_local_mac(ifp, br_if, &mac,
+ vid);
+
+ return zebra_vxlan_local_mac_add_update(ifp, br_if, &mac, vid,
+ sticky);
+ }
+
+ /* This is a delete notification.
+ * 1. For a MAC over VxLan, check if it needs to be refreshed(readded)
+ * 2. For a MAC over "local" interface, delete the mac
+ * Note: We will get notifications from both bridge driver and VxLAN
+ * driver.
+ * Ignore the notification from VxLan driver as it is also generated
+ * when mac moves from remote to local.
+ */
+ if (dst_present)
+ return 0;
+
+ if (IS_ZEBRA_IF_VXLAN(ifp))
+ return zebra_vxlan_check_readd_remote_mac(ifp, br_if, &mac,
+ vid);
+
+ return zebra_vxlan_local_mac_del(ifp, br_if, &mac, vid);
}
-static int
-netlink_macfdb_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
- ns_id_t ns_id, int startup)
+static int netlink_macfdb_table(struct sockaddr_nl *snl, struct nlmsghdr *h,
+ ns_id_t ns_id, int startup)
{
- int len;
- struct ndmsg *ndm;
+ int len;
+ struct ndmsg *ndm;
- if (h->nlmsg_type != RTM_NEWNEIGH)
- return 0;
+ if (h->nlmsg_type != RTM_NEWNEIGH)
+ return 0;
- /* Length validity. */
- len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg));
- if (len < 0)
- return -1;
+ /* Length validity. */
+ len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
+ if (len < 0)
+ return -1;
- /* We are interested only in AF_BRIDGE notifications. */
- ndm = NLMSG_DATA (h);
- if (ndm->ndm_family != AF_BRIDGE)
- return 0;
+ /* We are interested only in AF_BRIDGE notifications. */
+ ndm = NLMSG_DATA(h);
+ if (ndm->ndm_family != AF_BRIDGE)
+ return 0;
- return netlink_macfdb_change (snl, h, len);
+ return netlink_macfdb_change(snl, h, len);
}
/* Request for MAC FDB information from the kernel */
-static int
-netlink_request_macs (struct zebra_ns *zns, int family, int type,
- ifindex_t master_ifindex)
+static int netlink_request_macs(struct zebra_ns *zns, int family, int type,
+ ifindex_t master_ifindex)
{
- struct
- {
- struct nlmsghdr n;
- struct ifinfomsg ifm;
- char buf[256];
- } req;
-
- /* Form the request, specifying filter (rtattr) if needed. */
- memset (&req, 0, sizeof (req));
- req.n.nlmsg_type = type;
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
- req.ifm.ifi_family = family;
- if (master_ifindex)
- addattr32 (&req.n, sizeof(req), IFLA_MASTER, master_ifindex);
-
- return netlink_request (&zns->netlink_cmd, &req.n);
+ struct {
+ struct nlmsghdr n;
+ struct ifinfomsg ifm;
+ char buf[256];
+ } req;
+
+ /* Form the request, specifying filter (rtattr) if needed. */
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_type = type;
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.ifm.ifi_family = family;
+ if (master_ifindex)
+ addattr32(&req.n, sizeof(req), IFLA_MASTER, master_ifindex);
+
+ return netlink_request(&zns->netlink_cmd, &req.n);
}
/*
* MAC forwarding database read using netlink interface. This is invoked
* at startup.
*/
-int
-netlink_macfdb_read (struct zebra_ns *zns)
+int netlink_macfdb_read(struct zebra_ns *zns)
{
- int ret;
-
- /* Get bridge FDB table. */
- ret = netlink_request_macs (zns, AF_BRIDGE, RTM_GETNEIGH, 0);
- if (ret < 0)
- return ret;
- /* We are reading entire table. */
- filter_vlan = 0;
- ret = netlink_parse_info (netlink_macfdb_table, &zns->netlink_cmd, zns, 0, 1);
-
- return ret;
+ int ret;
+
+ /* Get bridge FDB table. */
+ ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH, 0);
+ if (ret < 0)
+ return ret;
+ /* We are reading entire table. */
+ filter_vlan = 0;
+ ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns,
+ 0, 1);
+
+ return ret;
}
/*
* MAC forwarding database read using netlink interface. This is for a
* specific bridge and matching specific access VLAN (if VLAN-aware bridge).
*/
-int
-netlink_macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp,
- struct interface *br_if)
+int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
+ struct interface *br_if)
{
- struct zebra_if *br_zif;
- struct zebra_if *zif;
- struct zebra_l2info_vxlan *vxl;
- int ret = 0;
-
-
- /* Save VLAN we're filtering on, if needed. */
- br_zif = (struct zebra_if *) br_if->info;
- zif = (struct zebra_if *) ifp->info;
- vxl = &zif->l2info.vxl;
- if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
- filter_vlan = vxl->access_vlan;
-
- /* Get bridge FDB table for specific bridge - we do the VLAN filtering. */
- ret = netlink_request_macs (zns, AF_BRIDGE, RTM_GETNEIGH, br_if->ifindex);
- if (ret < 0)
- return ret;
- ret = netlink_parse_info (netlink_macfdb_table, &zns->netlink_cmd, zns, 0, 0);
-
- /* Reset VLAN filter. */
- filter_vlan = 0;
- return ret;
+ struct zebra_if *br_zif;
+ struct zebra_if *zif;
+ struct zebra_l2info_vxlan *vxl;
+ int ret = 0;
+
+
+ /* Save VLAN we're filtering on, if needed. */
+ br_zif = (struct zebra_if *)br_if->info;
+ zif = (struct zebra_if *)ifp->info;
+ vxl = &zif->l2info.vxl;
+ if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
+ filter_vlan = vxl->access_vlan;
+
+ /* Get bridge FDB table for specific bridge - we do the VLAN filtering.
+ */
+ ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH,
+ br_if->ifindex);
+ if (ret < 0)
+ return ret;
+ ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns,
+ 0, 0);
+
+ /* Reset VLAN filter. */
+ filter_vlan = 0;
+ return ret;
}
-static int
-netlink_macfdb_update (struct interface *ifp, vlanid_t vid,
- struct ethaddr *mac,
- struct in_addr vtep_ip,
- int local, int cmd,
- u_char sticky)
+static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
+ struct ethaddr *mac, struct in_addr vtep_ip,
+ int local, int cmd, u_char sticky)
{
- struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
- struct
- {
- struct nlmsghdr n;
- struct ndmsg ndm;
- char buf[256];
- } req;
- int dst_alen;
- struct zebra_if *zif;
- struct interface *br_if;
- struct zebra_if *br_zif;
- char buf[ETHER_ADDR_STRLEN];
- int vid_present = 0, dst_present = 0;
- char vid_buf[20];
- char dst_buf[30];
-
- zif = ifp->info;
- if ((br_if = zif->brslave_info.br_if) == NULL)
- {
- zlog_warn ("MAC %s on IF %s(%u) - no mapping to bridge",
- (cmd == RTM_NEWNEIGH) ? "add" : "del",
- ifp->name, ifp->ifindex);
- return -1;
- }
-
- memset(&req.n, 0, sizeof(req.n));
- memset(&req.ndm, 0, sizeof(req.ndm));
-
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
- req.n.nlmsg_flags = NLM_F_REQUEST;
- if (cmd == RTM_NEWNEIGH)
- req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
- req.n.nlmsg_type = cmd;
- req.ndm.ndm_family = AF_BRIDGE;
- req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
- req.ndm.ndm_state = NUD_REACHABLE;
-
- if (sticky)
- req.ndm.ndm_state |= NUD_NOARP;
- else
- req.ndm.ndm_flags |= NTF_EXT_LEARNED;
-
- addattr_l (&req.n, sizeof (req), NDA_LLADDR, mac, 6);
- req.ndm.ndm_ifindex = ifp->ifindex;
- if (!local)
- {
- dst_alen = 4; // TODO: hardcoded
- addattr_l (&req.n, sizeof (req), NDA_DST, &vtep_ip, dst_alen);
- dst_present = 1;
- sprintf (dst_buf, " dst %s", inet_ntoa (vtep_ip));
- }
- br_zif = (struct zebra_if *) br_if->info;
- if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0)
- {
- addattr16 (&req.n, sizeof (req), NDA_VLAN, vid);
- vid_present = 1;
- sprintf (vid_buf, " VLAN %u", vid);
- }
- addattr32 (&req.n, sizeof (req), NDA_MASTER, br_if->ifindex);
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
- nl_msg_type_to_str (cmd),
- nl_family_to_str (req.ndm.ndm_family),
- ifp->name, ifp->ifindex,
- vid_present ? vid_buf : "",
- sticky ? "sticky " : "",
- prefix_mac2str (mac, buf, sizeof (buf)),
- dst_present ? dst_buf : "");
-
- return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+ struct {
+ struct nlmsghdr n;
+ struct ndmsg ndm;
+ char buf[256];
+ } req;
+ int dst_alen;
+ struct zebra_if *zif;
+ struct interface *br_if;
+ struct zebra_if *br_zif;
+ char buf[ETHER_ADDR_STRLEN];
+ int vid_present = 0, dst_present = 0;
+ char vid_buf[20];
+ char dst_buf[30];
+
+ zif = ifp->info;
+ if ((br_if = zif->brslave_info.br_if) == NULL) {
+ zlog_warn("MAC %s on IF %s(%u) - no mapping to bridge",
+ (cmd == RTM_NEWNEIGH) ? "add" : "del", ifp->name,
+ ifp->ifindex);
+ return -1;
+ }
+
+ memset(&req.n, 0, sizeof(req.n));
+ memset(&req.ndm, 0, sizeof(req.ndm));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ if (cmd == RTM_NEWNEIGH)
+ req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
+ req.n.nlmsg_type = cmd;
+ req.ndm.ndm_family = AF_BRIDGE;
+ req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
+ req.ndm.ndm_state = NUD_REACHABLE;
+
+ if (sticky)
+ req.ndm.ndm_state |= NUD_NOARP;
+ else
+ req.ndm.ndm_flags |= NTF_EXT_LEARNED;
+
+ addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
+ req.ndm.ndm_ifindex = ifp->ifindex;
+ if (!local) {
+ dst_alen = 4; // TODO: hardcoded
+ addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen);
+ dst_present = 1;
+ sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip));
+ }
+ br_zif = (struct zebra_if *)br_if->info;
+ if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) {
+ addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
+ vid_present = 1;
+ sprintf(vid_buf, " VLAN %u", vid);
+ }
+ addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
+ nl_msg_type_to_str(cmd),
+ nl_family_to_str(req.ndm.ndm_family), ifp->name,
+ ifp->ifindex, vid_present ? vid_buf : "",
+ sticky ? "sticky " : "",
+ prefix_mac2str(mac, buf, sizeof(buf)),
+ dst_present ? dst_buf : "");
+
+ return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
+ 0);
}
-#define NUD_VALID (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | \
- NUD_PROBE | NUD_STALE | NUD_DELAY)
+#define NUD_VALID \
+ (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE \
+ | NUD_DELAY)
-static int
-netlink_ipneigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h, int len)
+static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
+ int len)
{
- struct ndmsg *ndm;
- struct interface *ifp;
- struct zebra_if *zif;
- struct zebra_vrf *zvrf;
- struct rtattr *tb[NDA_MAX + 1];
- struct interface *link_if;
- struct ethaddr mac;
- struct ipaddr ip;
- char buf[ETHER_ADDR_STRLEN];
- char buf2[INET6_ADDRSTRLEN];
- int mac_present = 0;
- u_char ext_learned;
-
- ndm = NLMSG_DATA (h);
-
- /* The interface should exist. */
- ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ndm->ndm_ifindex);
- if (!ifp)
- return 0;
-
- /* Locate VRF corresponding to interface. We only process neigh notifications
- * if EVPN is enabled on this VRF.
- */
- zvrf = vrf_info_lookup(ifp->vrf_id);
- if (!zvrf || !EVPN_ENABLED(zvrf))
- return 0;
- if (!ifp->info)
- return 0;
-
- /* Drop "permanent" entries. */
- if (ndm->ndm_state & NUD_PERMANENT)
- return 0;
-
- zif = (struct zebra_if *)ifp->info;
- /* The neighbor is present on an SVI. From this, we locate the underlying
- * bridge because we're only interested in neighbors on a VxLAN bridge.
- * The bridge is located based on the nature of the SVI:
- * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
- * and is linked to the bridge
- * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
- * itself
- */
- if (IS_ZEBRA_IF_VLAN(ifp))
- {
- link_if = zif->link;
- if (!link_if)
- return 0;
- }
- else if (IS_ZEBRA_IF_BRIDGE(ifp))
- link_if = ifp;
- else
- return 0;
-
- /* Parse attributes and extract fields of interest. */
- memset (tb, 0, sizeof tb);
- netlink_parse_rtattr (tb, NDA_MAX, NDA_RTA (ndm), len);
-
- if (!tb[NDA_DST])
- {
- zlog_warn ("%s family %s IF %s(%u) - no DST",
- nl_msg_type_to_str (h->nlmsg_type),
- nl_family_to_str (ndm->ndm_family),
- ifp->name, ndm->ndm_ifindex);
- return 0;
- }
- memset (&mac, 0, sizeof (struct ethaddr));
- memset (&ip, 0, sizeof (struct ipaddr));
- ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6;
- memcpy (&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
-
- if (h->nlmsg_type == RTM_NEWNEIGH)
- {
- if (tb[NDA_LLADDR])
- {
- if (RTA_PAYLOAD (tb[NDA_LLADDR]) != ETHER_ADDR_LEN)
- {
- zlog_warn ("%s family %s IF %s(%u) - LLADDR is not MAC, len %ld",
- nl_msg_type_to_str (h->nlmsg_type),
- nl_family_to_str (ndm->ndm_family),
- ifp->name, ndm->ndm_ifindex,
- RTA_PAYLOAD (tb[NDA_LLADDR]));
- return 0;
- }
-
- mac_present = 1;
- memcpy (&mac, RTA_DATA (tb[NDA_LLADDR]), ETHER_ADDR_LEN);
- }
-
- ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0;
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x",
- nl_msg_type_to_str (h->nlmsg_type),
- nl_family_to_str (ndm->ndm_family),
- ifp->name, ndm->ndm_ifindex,
- ipaddr2str (&ip, buf2, sizeof(buf2)),
- mac_present ? prefix_mac2str (&mac, buf, sizeof (buf)) : "",
- ndm->ndm_state, ndm->ndm_flags);
-
- /* If the neighbor state is valid for use, process as an add or update
- * else process as a delete. Note that the delete handling may result
- * in re-adding the neighbor if it is a valid "remote" neighbor.
- */
- if (ndm->ndm_state & NUD_VALID)
- return zebra_vxlan_local_neigh_add_update (ifp, link_if,
- &ip, &mac,
- ndm->ndm_state, ext_learned);
-
- return zebra_vxlan_local_neigh_del (ifp, link_if, &ip);
- }
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("Rx %s family %s IF %s(%u) IP %s",
- nl_msg_type_to_str (h->nlmsg_type),
- nl_family_to_str (ndm->ndm_family),
- ifp->name, ndm->ndm_ifindex,
- ipaddr2str (&ip, buf2, sizeof(buf2)));
-
- /* Process the delete - it may result in re-adding the neighbor if it is
- * a valid "remote" neighbor.
- */
- return zebra_vxlan_local_neigh_del (ifp, link_if, &ip);
+ struct ndmsg *ndm;
+ struct interface *ifp;
+ struct zebra_if *zif;
+ struct zebra_vrf *zvrf;
+ struct rtattr *tb[NDA_MAX + 1];
+ struct interface *link_if;
+ struct ethaddr mac;
+ struct ipaddr ip;
+ char buf[ETHER_ADDR_STRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+ int mac_present = 0;
+ u_char ext_learned;
+
+ ndm = NLMSG_DATA(h);
+
+ /* The interface should exist. */
+ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+ ndm->ndm_ifindex);
+ if (!ifp)
+ return 0;
+
+ /* Locate VRF corresponding to interface. We only process neigh
+ * notifications
+ * if EVPN is enabled on this VRF.
+ */
+ zvrf = vrf_info_lookup(ifp->vrf_id);
+ if (!zvrf || !EVPN_ENABLED(zvrf))
+ return 0;
+ if (!ifp->info)
+ return 0;
+
+ /* Drop "permanent" entries. */
+ if (ndm->ndm_state & NUD_PERMANENT)
+ return 0;
+
+ zif = (struct zebra_if *)ifp->info;
+ /* The neighbor is present on an SVI. From this, we locate the
+ * underlying
+ * bridge because we're only interested in neighbors on a VxLAN bridge.
+ * The bridge is located based on the nature of the SVI:
+ * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN
+ * interface
+ * and is linked to the bridge
+ * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge
+ * inteface
+ * itself
+ */
+ if (IS_ZEBRA_IF_VLAN(ifp)) {
+ link_if = zif->link;
+ if (!link_if)
+ return 0;
+ } else if (IS_ZEBRA_IF_BRIDGE(ifp))
+ link_if = ifp;
+ else
+ return 0;
+
+ /* Parse attributes and extract fields of interest. */
+ memset(tb, 0, sizeof tb);
+ netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
+
+ if (!tb[NDA_DST]) {
+ zlog_warn("%s family %s IF %s(%u) - no DST",
+ nl_msg_type_to_str(h->nlmsg_type),
+ nl_family_to_str(ndm->ndm_family), ifp->name,
+ ndm->ndm_ifindex);
+ return 0;
+ }
+ memset(&mac, 0, sizeof(struct ethaddr));
+ memset(&ip, 0, sizeof(struct ipaddr));
+ ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6;
+ memcpy(&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
+
+ if (h->nlmsg_type == RTM_NEWNEIGH) {
+ if (tb[NDA_LLADDR]) {
+ if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETHER_ADDR_LEN) {
+ zlog_warn(
+ "%s family %s IF %s(%u) - LLADDR is not MAC, len %ld",
+ nl_msg_type_to_str(h->nlmsg_type),
+ nl_family_to_str(ndm->ndm_family),
+ ifp->name, ndm->ndm_ifindex,
+ RTA_PAYLOAD(tb[NDA_LLADDR]));
+ return 0;
+ }
+
+ mac_present = 1;
+ memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETHER_ADDR_LEN);
+ }
+
+ ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0;
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x",
+ nl_msg_type_to_str(h->nlmsg_type),
+ nl_family_to_str(ndm->ndm_family), ifp->name,
+ ndm->ndm_ifindex,
+ ipaddr2str(&ip, buf2, sizeof(buf2)),
+ mac_present
+ ? prefix_mac2str(&mac, buf, sizeof(buf))
+ : "",
+ ndm->ndm_state, ndm->ndm_flags);
+
+ /* If the neighbor state is valid for use, process as an add or
+ * update
+ * else process as a delete. Note that the delete handling may
+ * result
+ * in re-adding the neighbor if it is a valid "remote" neighbor.
+ */
+ if (ndm->ndm_state & NUD_VALID)
+ return zebra_vxlan_local_neigh_add_update(
+ ifp, link_if, &ip, &mac, ndm->ndm_state,
+ ext_learned);
+
+ return zebra_vxlan_local_neigh_del(ifp, link_if, &ip);
+ }
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("Rx %s family %s IF %s(%u) IP %s",
+ nl_msg_type_to_str(h->nlmsg_type),
+ nl_family_to_str(ndm->ndm_family), ifp->name,
+ ndm->ndm_ifindex,
+ ipaddr2str(&ip, buf2, sizeof(buf2)));
+
+ /* Process the delete - it may result in re-adding the neighbor if it is
+ * a valid "remote" neighbor.
+ */
+ return zebra_vxlan_local_neigh_del(ifp, link_if, &ip);
}
-static int
-netlink_neigh_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
- ns_id_t ns_id, int startup)
+static int netlink_neigh_table(struct sockaddr_nl *snl, struct nlmsghdr *h,
+ ns_id_t ns_id, int startup)
{
- int len;
- struct ndmsg *ndm;
+ int len;
+ struct ndmsg *ndm;
- if (h->nlmsg_type != RTM_NEWNEIGH)
- return 0;
+ if (h->nlmsg_type != RTM_NEWNEIGH)
+ return 0;
- /* Length validity. */
- len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg));
- if (len < 0)
- return -1;
+ /* Length validity. */
+ len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
+ if (len < 0)
+ return -1;
- /* We are interested only in AF_INET or AF_INET6 notifications. */
- ndm = NLMSG_DATA (h);
- if (ndm->ndm_family != AF_INET && ndm->ndm_family != AF_INET6)
- return 0;
+ /* We are interested only in AF_INET or AF_INET6 notifications. */
+ ndm = NLMSG_DATA(h);
+ if (ndm->ndm_family != AF_INET && ndm->ndm_family != AF_INET6)
+ return 0;
- return netlink_neigh_change (snl, h, len);
+ return netlink_neigh_change(snl, h, len);
}
/* Request for IP neighbor information from the kernel */
-static int
-netlink_request_neigh (struct zebra_ns *zns, int family, int type,
- ifindex_t ifindex)
+static int netlink_request_neigh(struct zebra_ns *zns, int family, int type,
+ ifindex_t ifindex)
{
- struct
- {
- struct nlmsghdr n;
- struct ndmsg ndm;
- char buf[256];
- } req;
-
- /* Form the request, specifying filter (rtattr) if needed. */
- memset (&req, 0, sizeof (req));
- req.n.nlmsg_type = type;
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
- req.ndm.ndm_family = family;
- if (ifindex)
- addattr32 (&req.n, sizeof(req), NDA_IFINDEX, ifindex);
-
- return netlink_request (&zns->netlink_cmd, &req.n);
+ struct {
+ struct nlmsghdr n;
+ struct ndmsg ndm;
+ char buf[256];
+ } req;
+
+ /* Form the request, specifying filter (rtattr) if needed. */
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_type = type;
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
+ req.ndm.ndm_family = family;
+ if (ifindex)
+ addattr32(&req.n, sizeof(req), NDA_IFINDEX, ifindex);
+
+ return netlink_request(&zns->netlink_cmd, &req.n);
}
/*
* IP Neighbor table read using netlink interface. This is invoked
* at startup.
*/
-int
-netlink_neigh_read (struct zebra_ns *zns)
+int netlink_neigh_read(struct zebra_ns *zns)
{
- int ret;
+ int ret;
- /* Get IP neighbor table. */
- ret = netlink_request_neigh (zns, AF_UNSPEC, RTM_GETNEIGH, 0);
- if (ret < 0)
- return ret;
- ret = netlink_parse_info (netlink_neigh_table, &zns->netlink_cmd, zns, 0, 1);
+ /* Get IP neighbor table. */
+ ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH, 0);
+ if (ret < 0)
+ return ret;
+ ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0,
+ 1);
- return ret;
+ return ret;
}
/*
* IP Neighbor table read using netlink interface. This is for a specific
* VLAN device.
*/
-int
-netlink_neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if)
+int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
{
- int ret = 0;
+ int ret = 0;
- ret = netlink_request_neigh (zns, AF_UNSPEC, RTM_GETNEIGH, vlan_if->ifindex);
- if (ret < 0)
- return ret;
- ret = netlink_parse_info (netlink_neigh_table, &zns->netlink_cmd, zns, 0, 0);
+ ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH,
+ vlan_if->ifindex);
+ if (ret < 0)
+ return ret;
+ ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0,
+ 0);
- return ret;
+ return ret;
}
-int
-netlink_neigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
- ns_id_t ns_id)
+int netlink_neigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
+ ns_id_t ns_id)
{
- int len;
- struct ndmsg *ndm;
+ int len;
+ struct ndmsg *ndm;
- if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH))
- return 0;
+ if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH))
+ return 0;
- /* Length validity. */
- len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg));
- if (len < 0)
- return -1;
+ /* Length validity. */
+ len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
+ if (len < 0)
+ return -1;
- /* Is this a notification for the MAC FDB or IP neighbor table? */
- ndm = NLMSG_DATA (h);
- if (ndm->ndm_family == AF_BRIDGE)
- return netlink_macfdb_change (snl, h, len);
+ /* Is this a notification for the MAC FDB or IP neighbor table? */
+ ndm = NLMSG_DATA(h);
+ if (ndm->ndm_family == AF_BRIDGE)
+ return netlink_macfdb_change(snl, h, len);
- if (ndm->ndm_type != RTN_UNICAST)
- return 0;
+ if (ndm->ndm_type != RTN_UNICAST)
+ return 0;
- if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6)
- return netlink_ipneigh_change (snl, h, len);
+ if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6)
+ return netlink_ipneigh_change(snl, h, len);
- return 0;
+ return 0;
}
-static int
-netlink_neigh_update2 (struct interface *ifp, struct ipaddr *ip,
- struct ethaddr *mac, u_int32_t flags, int cmd)
+static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
+ struct ethaddr *mac, u_int32_t flags, int cmd)
{
- struct {
- struct nlmsghdr n;
- struct ndmsg ndm;
- char buf[256];
- } req;
- int ipa_len;
-
- struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
- char buf[INET6_ADDRSTRLEN];
- char buf2[ETHER_ADDR_STRLEN];
-
- memset(&req.n, 0, sizeof(req.n));
- memset(&req.ndm, 0, sizeof(req.ndm));
-
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
- req.n.nlmsg_flags = NLM_F_REQUEST;
- if (cmd == RTM_NEWNEIGH)
- req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
- req.n.nlmsg_type = cmd; //RTM_NEWNEIGH or RTM_DELNEIGH
- req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
- req.ndm.ndm_state = flags;
- req.ndm.ndm_ifindex = ifp->ifindex;
- req.ndm.ndm_type = RTN_UNICAST;
- req.ndm.ndm_flags = NTF_EXT_LEARNED;
-
-
- ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
- addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
- if (mac)
- addattr_l (&req.n, sizeof (req), NDA_LLADDR, mac, 6);
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("Tx %s family %s IF %s(%u) Neigh %s MAC %s",
- nl_msg_type_to_str (cmd),
- nl_family_to_str (req.ndm.ndm_family),
- ifp->name, ifp->ifindex,
- ipaddr2str (ip, buf, sizeof(buf)),
- mac ? prefix_mac2str (mac, buf2, sizeof (buf2)) : "null");
-
- return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
+ struct {
+ struct nlmsghdr n;
+ struct ndmsg ndm;
+ char buf[256];
+ } req;
+ int ipa_len;
+
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+ char buf[INET6_ADDRSTRLEN];
+ char buf2[ETHER_ADDR_STRLEN];
+
+ memset(&req.n, 0, sizeof(req.n));
+ memset(&req.ndm, 0, sizeof(req.ndm));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ if (cmd == RTM_NEWNEIGH)
+ req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
+ req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
+ req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
+ req.ndm.ndm_state = flags;
+ req.ndm.ndm_ifindex = ifp->ifindex;
+ req.ndm.ndm_type = RTN_UNICAST;
+ req.ndm.ndm_flags = NTF_EXT_LEARNED;
+
+
+ ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
+ addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
+ if (mac)
+ addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s",
+ nl_msg_type_to_str(cmd),
+ nl_family_to_str(req.ndm.ndm_family), ifp->name,
+ ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)),
+ mac ? prefix_mac2str(mac, buf2, sizeof(buf2))
+ : "null");
+
+ return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
+ 0);
}
-int
-kernel_add_mac (struct interface *ifp, vlanid_t vid,
- struct ethaddr *mac, struct in_addr vtep_ip,
- u_char sticky)
+int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
+ struct in_addr vtep_ip, u_char sticky)
{
- return netlink_macfdb_update (ifp, vid, mac, vtep_ip, 0, RTM_NEWNEIGH, sticky);
+ return netlink_macfdb_update(ifp, vid, mac, vtep_ip, 0, RTM_NEWNEIGH,
+ sticky);
}
-int
-kernel_del_mac (struct interface *ifp, vlanid_t vid,
- struct ethaddr *mac, struct in_addr vtep_ip, int local)
+int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
+ struct in_addr vtep_ip, int local)
{
- return netlink_macfdb_update (ifp, vid, mac, vtep_ip, local, RTM_DELNEIGH, 0);
+ return netlink_macfdb_update(ifp, vid, mac, vtep_ip, local,
+ RTM_DELNEIGH, 0);
}
-int kernel_add_neigh (struct interface *ifp, struct ipaddr *ip,
- struct ethaddr *mac)
+int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
+ struct ethaddr *mac)
{
- return netlink_neigh_update2 (ifp, ip, mac, NUD_REACHABLE,
- RTM_NEWNEIGH);
+ return netlink_neigh_update2(ifp, ip, mac, NUD_REACHABLE, RTM_NEWNEIGH);
}
-int kernel_del_neigh (struct interface *ifp, struct ipaddr *ip)
+int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip)
{
- return netlink_neigh_update2 (ifp, ip, NULL, 0, RTM_DELNEIGH);
+ return netlink_neigh_update2(ifp, ip, NULL, 0, RTM_DELNEIGH);
}
/*
* MPLS label forwarding table change via netlink interface.
*/
-int
-netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp)
+int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
{
- mpls_lse_t lse;
- zebra_nhlfe_t *nhlfe;
- struct nexthop *nexthop = NULL;
- unsigned int nexthop_num;
- const char *routedesc;
- struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
-
- struct
- {
- struct nlmsghdr n;
- struct rtmsg r;
- char buf[NL_PKT_BUF_SIZE];
- } req;
-
- memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
-
-
- /*
- * Count # nexthops so we can decide whether to use singlepath
- * or multipath case.
- */
- nexthop_num = 0;
- for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
- {
- nexthop = nhlfe->nexthop;
- if (!nexthop)
- continue;
- if (cmd == RTM_NEWROUTE)
- {
- /* Count all selected NHLFEs */
- if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) &&
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- nexthop_num++;
- }
- else /* DEL */
- {
- /* Count all installed NHLFEs */
- if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) &&
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
- nexthop_num++;
- }
- }
-
- if (nexthop_num == 0) // unexpected
- return 0;
-
- req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
- req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
- req.n.nlmsg_type = cmd;
- req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
-
- req.r.rtm_family = AF_MPLS;
- req.r.rtm_table = RT_TABLE_MAIN;
- req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
- req.r.rtm_protocol = RTPROT_ZEBRA;
- req.r.rtm_scope = RT_SCOPE_UNIVERSE;
- req.r.rtm_type = RTN_UNICAST;
-
- if (cmd == RTM_NEWROUTE)
- /* We do a replace to handle update. */
- req.n.nlmsg_flags |= NLM_F_REPLACE;
-
- /* Fill destination */
- lse = mpls_lse_encode (lsp->ile.in_label, 0, 0, 1);
- addattr_l (&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t));
-
- /* Fill nexthops (paths) based on single-path or multipath. The paths
- * chosen depend on the operation.
- */
- if (nexthop_num == 1 || multipath_num == 1)
- {
- routedesc = "single hop";
- _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
-
- nexthop_num = 0;
- for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
- {
- nexthop = nhlfe->nexthop;
- if (!nexthop)
- continue;
-
- if ((cmd == RTM_NEWROUTE &&
- (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) &&
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) ||
- (cmd == RTM_DELROUTE &&
- (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) &&
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))))
- {
- /* Add the gateway */
- _netlink_mpls_build_singlepath(routedesc, nhlfe,
- &req.n, &req.r, sizeof req, cmd);
- if (cmd == RTM_NEWROUTE)
- {
- SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
- }
- else
- {
- UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
- }
- nexthop_num++;
- break;
- }
- }
- }
- else /* Multipath case */
- {
- char buf[NL_PKT_BUF_SIZE];
- struct rtattr *rta = (void *) buf;
- struct rtnexthop *rtnh;
- union g_addr *src1 = NULL;
-
- rta->rta_type = RTA_MULTIPATH;
- rta->rta_len = RTA_LENGTH (0);
- rtnh = RTA_DATA (rta);
-
- routedesc = "multihop";
- _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
-
- nexthop_num = 0;
- for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
- {
- nexthop = nhlfe->nexthop;
- if (!nexthop)
- continue;
-
- if (nexthop_num >= multipath_num)
- break;
-
- if ((cmd == RTM_NEWROUTE &&
- (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) &&
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) ||
- (cmd == RTM_DELROUTE &&
- (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) &&
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))))
- {
- nexthop_num++;
-
- /* Build the multipath */
- _netlink_mpls_build_multipath(routedesc, nhlfe, rta,
- rtnh, &req.r, &src1);
- rtnh = RTNH_NEXT (rtnh);
-
- if (cmd == RTM_NEWROUTE)
- {
- SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
- }
- else
- {
- UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
- }
-
- }
- }
-
- /* Add the multipath */
- if (rta->rta_len > RTA_LENGTH (0))
- addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
- RTA_PAYLOAD (rta));
- }
-
- /* Talk to netlink socket. */
- return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
+ mpls_lse_t lse;
+ zebra_nhlfe_t *nhlfe;
+ struct nexthop *nexthop = NULL;
+ unsigned int nexthop_num;
+ const char *routedesc;
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+
+ struct {
+ struct nlmsghdr n;
+ struct rtmsg r;
+ char buf[NL_PKT_BUF_SIZE];
+ } req;
+
+ memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE);
+
+
+ /*
+ * Count # nexthops so we can decide whether to use singlepath
+ * or multipath case.
+ */
+ nexthop_num = 0;
+ for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
+ nexthop = nhlfe->nexthop;
+ if (!nexthop)
+ continue;
+ if (cmd == RTM_NEWROUTE) {
+ /* Count all selected NHLFEs */
+ if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
+ && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ nexthop_num++;
+ } else /* DEL */
+ {
+ /* Count all installed NHLFEs */
+ if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)
+ && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
+ nexthop_num++;
+ }
+ }
+
+ if (nexthop_num == 0) // unexpected
+ return 0;
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
+ req.n.nlmsg_type = cmd;
+ req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
+
+ req.r.rtm_family = AF_MPLS;
+ req.r.rtm_table = RT_TABLE_MAIN;
+ req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
+ req.r.rtm_protocol = RTPROT_ZEBRA;
+ req.r.rtm_scope = RT_SCOPE_UNIVERSE;
+ req.r.rtm_type = RTN_UNICAST;
+
+ if (cmd == RTM_NEWROUTE)
+ /* We do a replace to handle update. */
+ req.n.nlmsg_flags |= NLM_F_REPLACE;
+
+ /* Fill destination */
+ lse = mpls_lse_encode(lsp->ile.in_label, 0, 0, 1);
+ addattr_l(&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t));
+
+ /* Fill nexthops (paths) based on single-path or multipath. The paths
+ * chosen depend on the operation.
+ */
+ if (nexthop_num == 1 || multipath_num == 1) {
+ routedesc = "single hop";
+ _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
+
+ nexthop_num = 0;
+ for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
+ nexthop = nhlfe->nexthop;
+ if (!nexthop)
+ continue;
+
+ if ((cmd == RTM_NEWROUTE
+ && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
+ && CHECK_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_ACTIVE)))
+ || (cmd == RTM_DELROUTE
+ && (CHECK_FLAG(nhlfe->flags,
+ NHLFE_FLAG_INSTALLED)
+ && CHECK_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_FIB)))) {
+ /* Add the gateway */
+ _netlink_mpls_build_singlepath(routedesc, nhlfe,
+ &req.n, &req.r,
+ sizeof req, cmd);
+ if (cmd == RTM_NEWROUTE) {
+ SET_FLAG(nhlfe->flags,
+ NHLFE_FLAG_INSTALLED);
+ SET_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_FIB);
+ } else {
+ UNSET_FLAG(nhlfe->flags,
+ NHLFE_FLAG_INSTALLED);
+ UNSET_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_FIB);
+ }
+ nexthop_num++;
+ break;
+ }
+ }
+ } else /* Multipath case */
+ {
+ char buf[NL_PKT_BUF_SIZE];
+ struct rtattr *rta = (void *)buf;
+ struct rtnexthop *rtnh;
+ union g_addr *src1 = NULL;
+
+ rta->rta_type = RTA_MULTIPATH;
+ rta->rta_len = RTA_LENGTH(0);
+ rtnh = RTA_DATA(rta);
+
+ routedesc = "multihop";
+ _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
+
+ nexthop_num = 0;
+ for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
+ nexthop = nhlfe->nexthop;
+ if (!nexthop)
+ continue;
+
+ if (nexthop_num >= multipath_num)
+ break;
+
+ if ((cmd == RTM_NEWROUTE
+ && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
+ && CHECK_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_ACTIVE)))
+ || (cmd == RTM_DELROUTE
+ && (CHECK_FLAG(nhlfe->flags,
+ NHLFE_FLAG_INSTALLED)
+ && CHECK_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_FIB)))) {
+ nexthop_num++;
+
+ /* Build the multipath */
+ _netlink_mpls_build_multipath(routedesc, nhlfe,
+ rta, rtnh, &req.r,
+ &src1);
+ rtnh = RTNH_NEXT(rtnh);
+
+ if (cmd == RTM_NEWROUTE) {
+ SET_FLAG(nhlfe->flags,
+ NHLFE_FLAG_INSTALLED);
+ SET_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_FIB);
+ } else {
+ UNSET_FLAG(nhlfe->flags,
+ NHLFE_FLAG_INSTALLED);
+ UNSET_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_FIB);
+ }
+ }
+ }
+
+ /* Add the multipath */
+ if (rta->rta_len > RTA_LENGTH(0))
+ addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH,
+ RTA_DATA(rta), RTA_PAYLOAD(rta));
+ }
+
+ /* Talk to netlink socket. */
+ return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
+ 0);
}
/*
* Handle failure in LSP install, clear flags for NHLFE.
*/
-void
-clear_nhlfe_installed (zebra_lsp_t *lsp)
+void clear_nhlfe_installed(zebra_lsp_t *lsp)
{
- zebra_nhlfe_t *nhlfe;
- struct nexthop *nexthop;
-
- for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
- {
- nexthop = nhlfe->nexthop;
- if (!nexthop)
- continue;
-
- UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
- }
+ zebra_nhlfe_t *nhlfe;
+ struct nexthop *nexthop;
+
+ for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
+ nexthop = nhlfe->nexthop;
+ if (!nexthop)
+ continue;
+
+ UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
+ UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+ }
}