diff options
Diffstat (limited to 'zebra/rt_netlink.c')
| -rw-r--r-- | zebra/rt_netlink.c | 4093 | 
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); +	}  }  | 
