]> git.proxmox.com Git - mirror_frr.git/blame - zebra/rt_netlink.c
fpm: don't check for NULL on async events
[mirror_frr.git] / zebra / rt_netlink.c
CommitLineData
718e3744 1/* Kernel routing table updates using netlink over GNU/Linux system.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 19 */
20
21#include <zebra.h>
ddfeb486
DL
22
23#ifdef HAVE_NETLINK
24
8ccc7e80 25#include <net/if_arp.h>
ba777396
RW
26#include <linux/lwtunnel.h>
27#include <linux/mpls_iptunnel.h>
28#include <linux/neighbour.h>
29#include <linux/rtnetlink.h>
d9f5b2f5 30#include <linux/nexthop.h>
718e3744 31
32/* Hack for GNU libc version 2. */
33#ifndef MSG_TRUNC
34#define MSG_TRUNC 0x20
35#endif /* MSG_TRUNC */
36
37#include "linklist.h"
38#include "if.h"
39#include "log.h"
40#include "prefix.h"
41#include "connected.h"
42#include "table.h"
26e2ae36 43#include "memory.h"
4a1ab8e4 44#include "zebra_memory.h"
718e3744 45#include "rib.h"
e04ab74d 46#include "thread.h"
edd7c245 47#include "privs.h"
fb018d25 48#include "nexthop.h"
78104b9b 49#include "vrf.h"
5e6a74d8 50#include "vty.h"
40c7bdb0 51#include "mpls.h"
13d60d35 52#include "vxlan.h"
8d03bc50 53#include "printfrr.h"
718e3744 54
bf094f69 55#include "zebra/zapi_msg.h"
fe18ee2d 56#include "zebra/zebra_ns.h"
7c551956 57#include "zebra/zebra_vrf.h"
6621ca86 58#include "zebra/rt.h"
718e3744 59#include "zebra/redistribute.h"
60#include "zebra/interface.h"
61#include "zebra/debug.h"
12f6fb97 62#include "zebra/rtadv.h"
567b877d 63#include "zebra/zebra_ptm.h"
40c7bdb0 64#include "zebra/zebra_mpls.h"
1fdc9eae 65#include "zebra/kernel_netlink.h"
66#include "zebra/rt_netlink.h"
d9f5b2f5 67#include "zebra/zebra_nhg.h"
e3be0432 68#include "zebra/zebra_mroute.h"
2232a77c 69#include "zebra/zebra_vxlan.h"
364fed6b 70#include "zebra/zebra_errors.h"
e3be0432 71
40c7bdb0 72#ifndef AF_MPLS
73#define AF_MPLS 28
74#endif
75
2232a77c 76static vlanid_t filter_vlan = 0;
77
7c99d51b
MS
78/* We capture whether the current kernel supports nexthop ids; by
79 * default, we'll use them if possible. There's also a configuration
80 * available to _disable_ use of kernel nexthops.
81 */
fec211ad 82static bool supports_nh;
81505946 83
d62a17ae 84struct gw_family_t {
d7c0a89a
QY
85 uint16_t filler;
86 uint16_t family;
d62a17ae 87 union g_addr gate;
40c7bdb0 88};
89
2b64873d
DL
90static const char ipv4_ll_buf[16] = "169.254.0.1";
91static struct in_addr ipv4_ll;
8755598a 92
7c99d51b
MS
93/* Helper to control use of kernel-level nexthop ids */
94static bool kernel_nexthops_supported(void)
95{
d982012a
SW
96 return (supports_nh && !vrf_is_backend_netns()
97 && zebra_nhg_kernel_nexthops_enabled());
7c99d51b
MS
98}
99
8755598a
DS
100/*
101 * The ipv4_ll data structure is used for all 5549
102 * additions to the kernel. Let's figure out the
103 * correct value one time instead for every
104 * install/remove of a 5549 type route
105 */
d62a17ae 106void rt_netlink_init(void)
8755598a 107{
d62a17ae 108 inet_pton(AF_INET, ipv4_ll_buf, &ipv4_ll);
8755598a
DS
109}
110
931fa60c
MS
111/*
112 * Mapping from dataplane neighbor flags to netlink flags
113 */
114static uint8_t neigh_flags_to_netlink(uint8_t dplane_flags)
115{
116 uint8_t flags = 0;
117
118 if (dplane_flags & DPLANE_NTF_EXT_LEARNED)
119 flags |= NTF_EXT_LEARNED;
120 if (dplane_flags & DPLANE_NTF_ROUTER)
121 flags |= NTF_ROUTER;
122
123 return flags;
124}
125
126/*
127 * Mapping from dataplane neighbor state to netlink state
128 */
129static uint16_t neigh_state_to_netlink(uint16_t dplane_state)
130{
131 uint16_t state = 0;
132
133 if (dplane_state & DPLANE_NUD_REACHABLE)
134 state |= NUD_REACHABLE;
135 if (dplane_state & DPLANE_NUD_STALE)
136 state |= NUD_STALE;
137 if (dplane_state & DPLANE_NUD_NOARP)
138 state |= NUD_NOARP;
139 if (dplane_state & DPLANE_NUD_PROBE)
140 state |= NUD_PROBE;
141
142 return state;
143}
144
145
6a6d11a3 146static inline bool is_selfroute(int proto)
23b1f334 147{
d62a17ae 148 if ((proto == RTPROT_BGP) || (proto == RTPROT_OSPF)
d4d71f11 149 || (proto == RTPROT_ZSTATIC) || (proto == RTPROT_ZEBRA)
d62a17ae 150 || (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG)
151 || (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP)
915902cb 152 || (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)
0761368a 153 || (proto == RTPROT_RIP) || (proto == RTPROT_SHARP)
da82f6b4 154 || (proto == RTPROT_PBR) || (proto == RTPROT_OPENFABRIC)) {
6a6d11a3 155 return true;
d62a17ae 156 }
157
6a6d11a3 158 return false;
23b1f334
DD
159}
160
915902cb 161static inline int zebra2proto(int proto)
23b1f334 162{
d62a17ae 163 switch (proto) {
164 case ZEBRA_ROUTE_BABEL:
165 proto = RTPROT_BABEL;
166 break;
167 case ZEBRA_ROUTE_BGP:
168 proto = RTPROT_BGP;
169 break;
170 case ZEBRA_ROUTE_OSPF:
171 case ZEBRA_ROUTE_OSPF6:
172 proto = RTPROT_OSPF;
173 break;
174 case ZEBRA_ROUTE_STATIC:
d4d71f11 175 proto = RTPROT_ZSTATIC;
d62a17ae 176 break;
177 case ZEBRA_ROUTE_ISIS:
178 proto = RTPROT_ISIS;
179 break;
180 case ZEBRA_ROUTE_RIP:
181 proto = RTPROT_RIP;
182 break;
183 case ZEBRA_ROUTE_RIPNG:
184 proto = RTPROT_RIPNG;
185 break;
186 case ZEBRA_ROUTE_NHRP:
187 proto = RTPROT_NHRP;
188 break;
189 case ZEBRA_ROUTE_EIGRP:
190 proto = RTPROT_EIGRP;
191 break;
192 case ZEBRA_ROUTE_LDP:
193 proto = RTPROT_LDP;
194 break;
8a71d93d
DS
195 case ZEBRA_ROUTE_SHARP:
196 proto = RTPROT_SHARP;
197 break;
0761368a
DS
198 case ZEBRA_ROUTE_PBR:
199 proto = RTPROT_PBR;
200 break;
da82f6b4
CF
201 case ZEBRA_ROUTE_OPENFABRIC:
202 proto = RTPROT_OPENFABRIC;
203 break;
a56ec5c0 204 case ZEBRA_ROUTE_TABLE:
38e40db1 205 case ZEBRA_ROUTE_NHG:
a56ec5c0
DS
206 proto = RTPROT_ZEBRA;
207 break;
d62a17ae 208 default:
0761368a
DS
209 /*
210 * When a user adds a new protocol this will show up
211 * to let them know to do something about it. This
212 * is intentionally a warn because we should see
213 * this as part of development of a new protocol
214 */
9df414fe
QY
215 zlog_debug(
216 "%s: Please add this protocol(%d) to proper rt_netlink.c handling",
15569c58 217 __func__, proto);
d62a17ae 218 proto = RTPROT_ZEBRA;
219 break;
220 }
221
222 return proto;
23b1f334
DD
223}
224
38e40db1 225static inline int proto2zebra(int proto, int family, bool is_nexthop)
915902cb
DS
226{
227 switch (proto) {
228 case RTPROT_BABEL:
229 proto = ZEBRA_ROUTE_BABEL;
230 break;
231 case RTPROT_BGP:
232 proto = ZEBRA_ROUTE_BGP;
233 break;
234 case RTPROT_OSPF:
996c9314
LB
235 proto = (family == AFI_IP) ? ZEBRA_ROUTE_OSPF
236 : ZEBRA_ROUTE_OSPF6;
915902cb
DS
237 break;
238 case RTPROT_ISIS:
239 proto = ZEBRA_ROUTE_ISIS;
240 break;
241 case RTPROT_RIP:
242 proto = ZEBRA_ROUTE_RIP;
243 break;
244 case RTPROT_RIPNG:
245 proto = ZEBRA_ROUTE_RIPNG;
246 break;
247 case RTPROT_NHRP:
248 proto = ZEBRA_ROUTE_NHRP;
249 break;
250 case RTPROT_EIGRP:
251 proto = ZEBRA_ROUTE_EIGRP;
252 break;
253 case RTPROT_LDP:
254 proto = ZEBRA_ROUTE_LDP;
255 break;
256 case RTPROT_STATIC:
d4d71f11 257 case RTPROT_ZSTATIC:
915902cb
DS
258 proto = ZEBRA_ROUTE_STATIC;
259 break;
0761368a
DS
260 case RTPROT_SHARP:
261 proto = ZEBRA_ROUTE_SHARP;
262 break;
263 case RTPROT_PBR:
264 proto = ZEBRA_ROUTE_PBR;
265 break;
da82f6b4
CF
266 case RTPROT_OPENFABRIC:
267 proto = ZEBRA_ROUTE_OPENFABRIC;
268 break;
38e40db1
SW
269 case RTPROT_ZEBRA:
270 if (is_nexthop) {
271 proto = ZEBRA_ROUTE_NHG;
272 break;
273 }
274 /* Intentional fall thru */
915902cb 275 default:
0761368a
DS
276 /*
277 * When a user adds a new protocol this will show up
278 * to let them know to do something about it. This
279 * is intentionally a warn because we should see
280 * this as part of development of a new protocol
281 */
9df414fe
QY
282 zlog_debug(
283 "%s: Please add this protocol(%d) to proper rt_netlink.c handling",
15569c58 284 __func__, proto);
915902cb
DS
285 proto = ZEBRA_ROUTE_KERNEL;
286 break;
287 }
288 return proto;
289}
290
12f6fb97
DS
291/*
292Pending: create an efficient table_id (in a tree/hash) based lookup)
293 */
9d866c07 294vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id)
12f6fb97 295{
d62a17ae 296 struct vrf *vrf;
297 struct zebra_vrf *zvrf;
12f6fb97 298
a2addae8 299 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
78dd30b2
PG
300 zvrf = vrf->info;
301 if (zvrf == NULL)
d62a17ae 302 continue;
78dd30b2
PG
303 /* case vrf with netns : match the netnsid */
304 if (vrf_is_backend_netns()) {
305 if (ns_id == zvrf_id(zvrf))
306 return zvrf_id(zvrf);
307 } else {
308 /* VRF is VRF_BACKEND_VRF_LITE */
309 if (zvrf->table_id != table_id)
310 continue;
311 return zvrf_id(zvrf);
312 }
d62a17ae 313 }
12f6fb97 314
d62a17ae 315 return VRF_DEFAULT;
12f6fb97
DS
316}
317
87da6a60
SW
318/**
319 * @parse_encap_mpls() - Parses encapsulated mpls attributes
320 * @tb: Pointer to rtattr to look for nested items in.
321 * @labels: Pointer to store labels in.
322 *
323 * Return: Number of mpls labels found.
324 */
325static int parse_encap_mpls(struct rtattr *tb, mpls_label_t *labels)
326{
327 struct rtattr *tb_encap[MPLS_IPTUNNEL_MAX + 1] = {0};
328 mpls_lse_t *lses = NULL;
329 int num_labels = 0;
330 uint32_t ttl = 0;
331 uint32_t bos = 0;
332 uint32_t exp = 0;
333 mpls_label_t label = 0;
334
335 netlink_parse_rtattr_nested(tb_encap, MPLS_IPTUNNEL_MAX, tb);
336 lses = (mpls_lse_t *)RTA_DATA(tb_encap[MPLS_IPTUNNEL_DST]);
337 while (!bos && num_labels < MPLS_MAX_LABELS) {
338 mpls_lse_decode(lses[num_labels], &label, &ttl, &exp, &bos);
339 labels[num_labels++] = label;
340 }
341
342 return num_labels;
343}
344
77a44d94
SW
345static struct nexthop
346parse_nexthop_unicast(ns_id_t ns_id, struct rtmsg *rtm, struct rtattr **tb,
347 enum blackhole_type bh_type, int index, void *prefsrc,
20822f9d 348 void *gate, afi_t afi, vrf_id_t vrf_id)
77a44d94
SW
349{
350 struct interface *ifp = NULL;
351 struct nexthop nh = {0};
352 mpls_label_t labels[MPLS_MAX_LABELS] = {0};
353 int num_labels = 0;
354
20822f9d 355 vrf_id_t nh_vrf_id = vrf_id;
77a44d94
SW
356 size_t sz = (afi == AFI_IP) ? 4 : 16;
357
358 if (bh_type == BLACKHOLE_UNSPEC) {
359 if (index && !gate)
360 nh.type = NEXTHOP_TYPE_IFINDEX;
361 else if (index && gate)
362 nh.type = (afi == AFI_IP) ? NEXTHOP_TYPE_IPV4_IFINDEX
363 : NEXTHOP_TYPE_IPV6_IFINDEX;
364 else if (!index && gate)
365 nh.type = (afi == AFI_IP) ? NEXTHOP_TYPE_IPV4
366 : NEXTHOP_TYPE_IPV6;
367 else {
368 nh.type = NEXTHOP_TYPE_BLACKHOLE;
369 nh.bh_type = bh_type;
370 }
371 } else {
372 nh.type = NEXTHOP_TYPE_BLACKHOLE;
373 nh.bh_type = bh_type;
374 }
375 nh.ifindex = index;
376 if (prefsrc)
377 memcpy(&nh.src, prefsrc, sz);
378 if (gate)
379 memcpy(&nh.gate, gate, sz);
380
381 if (index) {
382 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), index);
383 if (ifp)
384 nh_vrf_id = ifp->vrf_id;
385 }
386 nh.vrf_id = nh_vrf_id;
387
388 if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]
389 && *(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE])
390 == LWTUNNEL_ENCAP_MPLS) {
391 num_labels = parse_encap_mpls(tb[RTA_ENCAP], labels);
392 }
393
394 if (rtm->rtm_flags & RTNH_F_ONLINK)
395 SET_FLAG(nh.flags, NEXTHOP_FLAG_ONLINK);
396
397 if (num_labels)
398 nexthop_add_labels(&nh, ZEBRA_LSP_STATIC, num_labels, labels);
399
400 return nh;
401}
402
20822f9d 403static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id,
0eb97b86 404 struct nexthop_group *ng,
20822f9d
SW
405 struct rtmsg *rtm,
406 struct rtnexthop *rtnh,
407 struct rtattr **tb,
408 void *prefsrc, vrf_id_t vrf_id)
409{
410 void *gate = NULL;
411 struct interface *ifp = NULL;
412 int index = 0;
413 /* MPLS labels */
414 mpls_label_t labels[MPLS_MAX_LABELS] = {0};
415 int num_labels = 0;
416 struct rtattr *rtnh_tb[RTA_MAX + 1] = {};
417
418 int len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
419 vrf_id_t nh_vrf_id = vrf_id;
420
20822f9d
SW
421 for (;;) {
422 struct nexthop *nh = NULL;
423
424 if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len)
425 break;
426
427 index = rtnh->rtnh_ifindex;
428 if (index) {
429 /*
430 * Yes we are looking this up
431 * for every nexthop and just
432 * using the last one looked
433 * up right now
434 */
435 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
436 index);
437 if (ifp)
438 nh_vrf_id = ifp->vrf_id;
439 else {
440 flog_warn(
441 EC_ZEBRA_UNKNOWN_INTERFACE,
442 "%s: Unknown interface %u specified, defaulting to VRF_DEFAULT",
15569c58 443 __func__, index);
20822f9d
SW
444 nh_vrf_id = VRF_DEFAULT;
445 }
446 } else
447 nh_vrf_id = vrf_id;
448
449 if (rtnh->rtnh_len > sizeof(*rtnh)) {
450 memset(rtnh_tb, 0, sizeof(rtnh_tb));
451
452 netlink_parse_rtattr(rtnh_tb, RTA_MAX, RTNH_DATA(rtnh),
453 rtnh->rtnh_len - sizeof(*rtnh));
454 if (rtnh_tb[RTA_GATEWAY])
455 gate = RTA_DATA(rtnh_tb[RTA_GATEWAY]);
456 if (rtnh_tb[RTA_ENCAP] && rtnh_tb[RTA_ENCAP_TYPE]
457 && *(uint16_t *)RTA_DATA(rtnh_tb[RTA_ENCAP_TYPE])
458 == LWTUNNEL_ENCAP_MPLS) {
459 num_labels = parse_encap_mpls(
460 rtnh_tb[RTA_ENCAP], labels);
461 }
462 }
463
f3354e16
SW
464 if (gate && rtm->rtm_family == AF_INET) {
465 if (index)
0eb97b86
MS
466 nh = nexthop_from_ipv4_ifindex(
467 gate, prefsrc, index, nh_vrf_id);
f3354e16 468 else
0eb97b86
MS
469 nh = nexthop_from_ipv4(gate, prefsrc,
470 nh_vrf_id);
f3354e16
SW
471 } else if (gate && rtm->rtm_family == AF_INET6) {
472 if (index)
0eb97b86
MS
473 nh = nexthop_from_ipv6_ifindex(
474 gate, index, nh_vrf_id);
f3354e16 475 else
0eb97b86 476 nh = nexthop_from_ipv6(gate, nh_vrf_id);
20822f9d 477 } else
0eb97b86 478 nh = nexthop_from_ifindex(index, nh_vrf_id);
20822f9d
SW
479
480 if (nh) {
df7fb580
DS
481 nh->weight = rtnh->rtnh_hops + 1;
482
20822f9d
SW
483 if (num_labels)
484 nexthop_add_labels(nh, ZEBRA_LSP_STATIC,
485 num_labels, labels);
486
487 if (rtnh->rtnh_flags & RTNH_F_ONLINK)
488 SET_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK);
0eb97b86
MS
489
490 /* Add to temporary list */
491 nexthop_group_add_sorted(ng, nh);
20822f9d
SW
492 }
493
494 if (rtnh->rtnh_len == 0)
495 break;
496
497 len -= NLMSG_ALIGN(rtnh->rtnh_len);
498 rtnh = RTNH_NEXT(rtnh);
499 }
500
0eb97b86 501 uint8_t nhop_num = nexthop_group_nexthop_num(ng);
20822f9d
SW
502
503 return nhop_num;
504}
505
718e3744 506/* Looking up routing table by netlink interface. */
2414abd3 507static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
d62a17ae 508 int startup)
718e3744 509{
d62a17ae 510 int len;
511 struct rtmsg *rtm;
512 struct rtattr *tb[RTA_MAX + 1];
d7c0a89a 513 uint8_t flags = 0;
d62a17ae 514 struct prefix p;
792fa92e 515 struct prefix_ipv6 src_p = {};
78dd30b2 516 vrf_id_t vrf_id;
6a6d11a3 517 bool selfroute;
d62a17ae 518
519 char anyaddr[16] = {0};
520
915902cb 521 int proto = ZEBRA_ROUTE_KERNEL;
d62a17ae 522 int index = 0;
523 int table;
524 int metric = 0;
d7c0a89a 525 uint32_t mtu = 0;
25715c7e 526 uint8_t distance = 0;
4e40b6d6 527 route_tag_t tag = 0;
fcc89a9c 528 uint32_t nhe_id = 0;
d62a17ae 529
530 void *dest = NULL;
531 void *gate = NULL;
532 void *prefsrc = NULL; /* IPv4 preferred source host address */
533 void *src = NULL; /* IPv6 srcdest source prefix */
e655a03c 534 enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
d62a17ae 535
536 rtm = NLMSG_DATA(h);
537
538 if (startup && h->nlmsg_type != RTM_NEWROUTE)
539 return 0;
e655a03c
DL
540 switch (rtm->rtm_type) {
541 case RTN_UNICAST:
542 break;
543 case RTN_BLACKHOLE:
544 bh_type = BLACKHOLE_NULL;
545 break;
546 case RTN_UNREACHABLE:
547 bh_type = BLACKHOLE_REJECT;
548 break;
549 case RTN_PROHIBIT:
550 bh_type = BLACKHOLE_ADMINPROHIB;
551 break;
552 default:
8c8f250b
DS
553 if (IS_ZEBRA_DEBUG_KERNEL)
554 zlog_debug("Route rtm_type: %s(%d) intentionally ignoring",
555 nl_rttype_to_str(rtm->rtm_type),
556 rtm->rtm_type);
d62a17ae 557 return 0;
e655a03c 558 }
d62a17ae 559
560 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
9bdf8618 561 if (len < 0) {
15569c58
DA
562 zlog_err(
563 "%s: Message received from netlink is of a broken size %d %zu",
564 __func__, h->nlmsg_len,
565 (size_t)NLMSG_LENGTH(sizeof(struct rtmsg)));
d62a17ae 566 return -1;
9bdf8618 567 }
d62a17ae 568
0d6f7fd6 569 memset(tb, 0, sizeof(tb));
d62a17ae 570 netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len);
571
572 if (rtm->rtm_flags & RTM_F_CLONED)
573 return 0;
574 if (rtm->rtm_protocol == RTPROT_REDIRECT)
575 return 0;
576 if (rtm->rtm_protocol == RTPROT_KERNEL)
577 return 0;
578
6a6d11a3
NN
579 selfroute = is_selfroute(rtm->rtm_protocol);
580
581 if (!startup && selfroute && h->nlmsg_type == RTM_NEWROUTE) {
6ab5222f
DS
582 if (IS_ZEBRA_DEBUG_KERNEL)
583 zlog_debug("Route type: %d Received that we think we have originated, ignoring",
584 rtm->rtm_protocol);
d62a17ae 585 return 0;
6ab5222f 586 }
d62a17ae 587
588 /* We don't care about change notifications for the MPLS table. */
589 /* TODO: Revisit this. */
590 if (rtm->rtm_family == AF_MPLS)
591 return 0;
592
593 /* Table corresponding to route. */
594 if (tb[RTA_TABLE])
595 table = *(int *)RTA_DATA(tb[RTA_TABLE]);
596 else
597 table = rtm->rtm_table;
598
599 /* Map to VRF */
78dd30b2 600 vrf_id = vrf_lookup_by_table(table, ns_id);
d62a17ae 601 if (vrf_id == VRF_DEFAULT) {
602 if (!is_zebra_valid_kernel_table(table)
603 && !is_zebra_main_routing_table(table))
604 return 0;
605 }
606
607 /* Route which inserted by Zebra. */
6a6d11a3 608 if (selfroute) {
d62a17ae 609 flags |= ZEBRA_FLAG_SELFROUTE;
38e40db1 610 proto = proto2zebra(rtm->rtm_protocol, rtm->rtm_family, false);
915902cb 611 }
d62a17ae 612 if (tb[RTA_OIF])
613 index = *(int *)RTA_DATA(tb[RTA_OIF]);
614
615 if (tb[RTA_DST])
616 dest = RTA_DATA(tb[RTA_DST]);
617 else
618 dest = anyaddr;
619
620 if (tb[RTA_SRC])
621 src = RTA_DATA(tb[RTA_SRC]);
622 else
623 src = anyaddr;
624
625 if (tb[RTA_PREFSRC])
626 prefsrc = RTA_DATA(tb[RTA_PREFSRC]);
627
628 if (tb[RTA_GATEWAY])
629 gate = RTA_DATA(tb[RTA_GATEWAY]);
630
fcc89a9c
SW
631 if (tb[RTA_NH_ID])
632 nhe_id = *(uint32_t *)RTA_DATA(tb[RTA_NH_ID]);
633
f19435a8
DS
634 if (tb[RTA_PRIORITY])
635 metric = *(int *)RTA_DATA(tb[RTA_PRIORITY]);
d62a17ae 636
4e40b6d6
KK
637#if defined(SUPPORT_REALMS)
638 if (tb[RTA_FLOW])
639 tag = *(uint32_t *)RTA_DATA(tb[RTA_FLOW]);
640#endif
641
f19435a8
DS
642 if (tb[RTA_METRICS]) {
643 struct rtattr *mxrta[RTAX_MAX + 1];
d62a17ae 644
0d6f7fd6 645 memset(mxrta, 0, sizeof(mxrta));
996c9314 646 netlink_parse_rtattr(mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
f19435a8 647 RTA_PAYLOAD(tb[RTA_METRICS]));
d62a17ae 648
f19435a8 649 if (mxrta[RTAX_MTU])
d7c0a89a 650 mtu = *(uint32_t *)RTA_DATA(mxrta[RTAX_MTU]);
d62a17ae 651 }
652
653 if (rtm->rtm_family == AF_INET) {
654 p.family = AF_INET;
930571d2 655 if (rtm->rtm_dst_len > IPV4_MAX_BITLEN) {
e17d9b2d 656 zlog_err(
75829703 657 "Invalid destination prefix length: %u received from kernel route change",
930571d2 658 rtm->rtm_dst_len);
e17d9b2d 659 return -1;
930571d2 660 }
d62a17ae 661 memcpy(&p.u.prefix4, dest, 4);
662 p.prefixlen = rtm->rtm_dst_len;
663
1f610a1f
CF
664 if (rtm->rtm_src_len != 0) {
665 char buf[PREFIX_STRLEN];
9df414fe 666 flog_warn(
e914ccbe 667 EC_ZEBRA_UNSUPPORTED_V4_SRCDEST,
9df414fe
QY
668 "unsupported IPv4 sourcedest route (dest %s vrf %u)",
669 prefix2str(&p, buf, sizeof(buf)), vrf_id);
1f610a1f
CF
670 return 0;
671 }
930571d2 672
1f610a1f
CF
673 /* Force debug below to not display anything for source */
674 src_p.prefixlen = 0;
d62a17ae 675 } else if (rtm->rtm_family == AF_INET6) {
676 p.family = AF_INET6;
930571d2 677 if (rtm->rtm_dst_len > IPV6_MAX_BITLEN) {
e17d9b2d 678 zlog_err(
75829703 679 "Invalid destination prefix length: %u received from kernel route change",
930571d2 680 rtm->rtm_dst_len);
e17d9b2d 681 return -1;
930571d2 682 }
d62a17ae 683 memcpy(&p.u.prefix6, dest, 16);
684 p.prefixlen = rtm->rtm_dst_len;
685
686 src_p.family = AF_INET6;
930571d2 687 if (rtm->rtm_src_len > IPV6_MAX_BITLEN) {
e17d9b2d 688 zlog_err(
75829703 689 "Invalid source prefix length: %u received from kernel route change",
930571d2 690 rtm->rtm_src_len);
e17d9b2d 691 return -1;
930571d2 692 }
d62a17ae 693 memcpy(&src_p.prefix, src, 16);
694 src_p.prefixlen = rtm->rtm_src_len;
695 }
696
25715c7e
DS
697 /*
698 * For ZEBRA_ROUTE_KERNEL types:
699 *
700 * The metric/priority of the route received from the kernel
701 * is a 32 bit number. We are going to interpret the high
702 * order byte as the Admin Distance and the low order 3 bytes
703 * as the metric.
704 *
705 * This will allow us to do two things:
706 * 1) Allow the creation of kernel routes that can be
707 * overridden by zebra.
708 * 2) Allow the old behavior for 'most' kernel route types
709 * if a user enters 'ip route ...' v4 routes get a metric
710 * of 0 and v6 routes get a metric of 1024. Both of these
711 * values will end up with a admin distance of 0, which
712 * will cause them to win for the purposes of zebra.
713 */
714 if (proto == ZEBRA_ROUTE_KERNEL) {
715 distance = (metric >> 24) & 0xFF;
996c9314 716 metric = (metric & 0x00FFFFFF);
25715c7e
DS
717 }
718
d62a17ae 719 if (IS_ZEBRA_DEBUG_KERNEL) {
720 char buf[PREFIX_STRLEN];
721 char buf2[PREFIX_STRLEN];
bd47f3a3
JU
722 zlog_debug(
723 "%s %s%s%s vrf %s(%u) table_id: %u metric: %d Admin Distance: %d",
724 nl_msg_type_to_str(h->nlmsg_type),
725 prefix2str(&p, buf, sizeof(buf)),
726 src_p.prefixlen ? " from " : "",
727 src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2))
728 : "",
729 vrf_id_to_name(vrf_id), vrf_id, table, metric,
730 distance);
d62a17ae 731 }
732
733 afi_t afi = AFI_IP;
734 if (rtm->rtm_family == AF_INET6)
735 afi = AFI_IP6;
736
737 if (h->nlmsg_type == RTM_NEWROUTE) {
8795f904 738
fd36be7e 739 if (!tb[RTA_MULTIPATH]) {
77a44d94 740 struct nexthop nh = {0};
8795f904 741
77a44d94
SW
742 if (!nhe_id) {
743 nh = parse_nexthop_unicast(
744 ns_id, rtm, tb, bh_type, index, prefsrc,
20822f9d 745 gate, afi, vrf_id);
87da6a60 746 }
4a7371e9 747 rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p,
8032b717
SW
748 &src_p, &nh, nhe_id, table, metric, mtu,
749 distance, tag);
fd36be7e 750 } else {
d62a17ae 751 /* This is a multipath route */
d62a17ae 752 struct route_entry *re;
0eb97b86 753 struct nexthop_group *ng = NULL;
d62a17ae 754 struct rtnexthop *rtnh =
755 (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
d62a17ae 756
757 re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
915902cb 758 re->type = proto;
25715c7e 759 re->distance = distance;
d62a17ae 760 re->flags = flags;
761 re->metric = metric;
762 re->mtu = mtu;
763 re->vrf_id = vrf_id;
764 re->table = table;
98572489 765 re->uptime = monotime(NULL);
4e40b6d6 766 re->tag = tag;
bbb322f2 767 re->nhe_id = nhe_id;
3c04071d 768
20822f9d 769 if (!nhe_id) {
0eb97b86
MS
770 uint8_t nhop_num;
771
772 /* Use temporary list of nexthops; parse
773 * message payload's nexthops.
774 */
775 ng = nexthop_group_new();
776 nhop_num =
20822f9d 777 parse_multipath_nexthops_unicast(
0eb97b86 778 ns_id, ng, rtm, rtnh, tb,
20822f9d
SW
779 prefsrc, vrf_id);
780
781 zserv_nexthop_num_warn(
782 __func__, (const struct prefix *)&p,
783 nhop_num);
0eb97b86
MS
784
785 if (nhop_num == 0) {
786 nexthop_group_delete(&ng);
787 ng = NULL;
788 }
d62a17ae 789 }
790
0eb97b86 791 if (nhe_id || ng)
1f610a1f 792 rib_add_multipath(afi, SAFI_UNICAST, &p,
0eb97b86 793 &src_p, re, ng);
20822f9d
SW
794 else
795 XFREE(MTYPE_RE, re);
d62a17ae 796 }
797 } else {
bc541126
SW
798 if (nhe_id) {
799 rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags,
800 &p, &src_p, NULL, nhe_id, table, metric,
801 distance, true);
802 } else {
803 if (!tb[RTA_MULTIPATH]) {
804 struct nexthop nh;
760f39dc
HS
805
806 nh = parse_nexthop_unicast(
807 ns_id, rtm, tb, bh_type, index, prefsrc,
808 gate, afi, vrf_id);
bc541126
SW
809 rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0,
810 flags, &p, &src_p, &nh, 0, table,
811 metric, distance, true);
8ba5bd58 812 } else {
bc541126
SW
813 /* XXX: need to compare the entire list of
814 * nexthops here for NLM_F_APPEND stupidity */
815 rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0,
816 flags, &p, &src_p, NULL, 0, table,
817 metric, distance, true);
8ba5bd58 818 }
d62a17ae 819 }
820 }
821
822 return 0;
718e3744 823}
824
e3be0432
DS
825static struct mcast_route_data *mroute = NULL;
826
2414abd3 827static int netlink_route_change_read_multicast(struct nlmsghdr *h,
d62a17ae 828 ns_id_t ns_id, int startup)
565fdc75 829{
d62a17ae 830 int len;
831 struct rtmsg *rtm;
832 struct rtattr *tb[RTA_MAX + 1];
833 struct mcast_route_data *m;
834 struct mcast_route_data mr;
835 int iif = 0;
836 int count;
837 int oif[256];
838 int oif_count = 0;
839 char sbuf[40];
840 char gbuf[40];
841 char oif_list[256] = "\0";
78dd30b2 842 vrf_id_t vrf;
43b5cc5e 843 int table;
d62a17ae 844
845 if (mroute)
846 m = mroute;
847 else {
848 memset(&mr, 0, sizeof(mr));
849 m = &mr;
850 }
851
852 rtm = NLMSG_DATA(h);
853
854 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
855
0d6f7fd6 856 memset(tb, 0, sizeof(tb));
d62a17ae 857 netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len);
90d82769 858
43b5cc5e
DS
859 if (tb[RTA_TABLE])
860 table = *(int *)RTA_DATA(tb[RTA_TABLE]);
861 else
862 table = rtm->rtm_table;
863
78dd30b2 864 vrf = vrf_lookup_by_table(table, ns_id);
43b5cc5e 865
d62a17ae 866 if (tb[RTA_IIF])
867 iif = *(int *)RTA_DATA(tb[RTA_IIF]);
868
869 if (tb[RTA_SRC])
bd8b9272 870 m->sg.src = *(struct in_addr *)RTA_DATA(tb[RTA_SRC]);
d62a17ae 871
872 if (tb[RTA_DST])
bd8b9272 873 m->sg.grp = *(struct in_addr *)RTA_DATA(tb[RTA_DST]);
d62a17ae 874
62819462 875 if (tb[RTA_EXPIRES])
d62a17ae 876 m->lastused = *(unsigned long long *)RTA_DATA(tb[RTA_EXPIRES]);
877
878 if (tb[RTA_MULTIPATH]) {
879 struct rtnexthop *rtnh =
880 (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
881
882 len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
883 for (;;) {
884 if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len)
885 break;
886
887 oif[oif_count] = rtnh->rtnh_ifindex;
888 oif_count++;
889
3c04071d
SW
890 if (rtnh->rtnh_len == 0)
891 break;
892
d62a17ae 893 len -= NLMSG_ALIGN(rtnh->rtnh_len);
894 rtnh = RTNH_NEXT(rtnh);
895 }
896 }
897
898 if (IS_ZEBRA_DEBUG_KERNEL) {
822c9af2
SW
899 struct interface *ifp = NULL;
900 struct zebra_vrf *zvrf = NULL;
901
0af35d90
RW
902 strlcpy(sbuf, inet_ntoa(m->sg.src), sizeof(sbuf));
903 strlcpy(gbuf, inet_ntoa(m->sg.grp), sizeof(gbuf));
d62a17ae 904 for (count = 0; count < oif_count; count++) {
905 ifp = if_lookup_by_index(oif[count], vrf);
906 char temp[256];
907
772270f3
QY
908 snprintf(temp, sizeof(temp), "%s(%d) ",
909 ifp ? ifp->name : "Unknown", oif[count]);
eab4a5c2 910 strlcat(oif_list, temp, sizeof(oif_list));
d62a17ae 911 }
822c9af2 912 zvrf = zebra_vrf_lookup_by_id(vrf);
d62a17ae 913 ifp = if_lookup_by_index(iif, vrf);
822c9af2
SW
914 zlog_debug(
915 "MCAST VRF: %s(%d) %s (%s,%s) IIF: %s(%d) OIF: %s jiffies: %lld",
bd47f3a3
JU
916 zvrf_name(zvrf), vrf, nl_msg_type_to_str(h->nlmsg_type),
917 sbuf, gbuf, ifp ? ifp->name : "Unknown", iif, oif_list,
822c9af2 918 m->lastused);
90d82769 919 }
d62a17ae 920 return 0;
565fdc75
DS
921}
922
2414abd3 923int netlink_route_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
565fdc75 924{
d62a17ae 925 int len;
d62a17ae 926 struct rtmsg *rtm;
927
928 rtm = NLMSG_DATA(h);
929
930 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) {
931 /* If this is not route add/delete message print warning. */
9165c5f5 932 zlog_debug("Kernel message: %s NS %u",
87b5d1b0 933 nl_msg_type_to_str(h->nlmsg_type), ns_id);
d62a17ae 934 return 0;
935 }
936
c25e2f1a
DS
937 if (!(rtm->rtm_family == AF_INET ||
938 rtm->rtm_family == AF_INET6 ||
939 rtm->rtm_family == RTNL_FAMILY_IPMR )) {
9df414fe 940 flog_warn(
e914ccbe 941 EC_ZEBRA_UNKNOWN_FAMILY,
87b5d1b0
DS
942 "Invalid address family: %u received from kernel route change: %s",
943 rtm->rtm_family, nl_msg_type_to_str(h->nlmsg_type));
8a1b681c
SW
944 return 0;
945 }
946
d62a17ae 947 /* Connected route. */
948 if (IS_ZEBRA_DEBUG_KERNEL)
78dd30b2 949 zlog_debug("%s %s %s proto %s NS %u",
d62a17ae 950 nl_msg_type_to_str(h->nlmsg_type),
951 nl_family_to_str(rtm->rtm_family),
952 nl_rttype_to_str(rtm->rtm_type),
78dd30b2 953 nl_rtproto_to_str(rtm->rtm_protocol), ns_id);
d62a17ae 954
d62a17ae 955
956 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
9bdf8618 957 if (len < 0) {
15569c58
DA
958 zlog_err(
959 "%s: Message received from netlink is of a broken size: %d %zu",
960 __func__, h->nlmsg_len,
961 (size_t)NLMSG_LENGTH(sizeof(struct rtmsg)));
d62a17ae 962 return -1;
9bdf8618 963 }
d62a17ae 964
e655a03c 965 if (rtm->rtm_type == RTN_MULTICAST)
2414abd3 966 netlink_route_change_read_multicast(h, ns_id, startup);
e655a03c 967 else
2414abd3 968 netlink_route_change_read_unicast(h, ns_id, startup);
d62a17ae 969 return 0;
565fdc75
DS
970}
971
289602d7 972/* Request for specific route information from the kernel */
d62a17ae 973static int netlink_request_route(struct zebra_ns *zns, int family, int type)
289602d7 974{
d62a17ae 975 struct {
976 struct nlmsghdr n;
977 struct rtmsg rtm;
978 } req;
979
980 /* Form the request, specifying filter (rtattr) if needed. */
981 memset(&req, 0, sizeof(req));
982 req.n.nlmsg_type = type;
718f9b0f 983 req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
d62a17ae 984 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
985 req.rtm.rtm_family = family;
986
fd3f8e52 987 return netlink_request(&zns->netlink_cmd, &req);
289602d7 988}
989
718e3744 990/* Routing table read function using netlink interface. Only called
991 bootstrap time. */
d62a17ae 992int netlink_route_read(struct zebra_ns *zns)
718e3744 993{
d62a17ae 994 int ret;
85a75f1e
MS
995 struct zebra_dplane_info dp_info;
996
997 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
d62a17ae 998
999 /* Get IPv4 routing table. */
1000 ret = netlink_request_route(zns, AF_INET, RTM_GETROUTE);
1001 if (ret < 0)
1002 return ret;
1003 ret = netlink_parse_info(netlink_route_change_read_unicast,
85a75f1e 1004 &zns->netlink_cmd, &dp_info, 0, 1);
d62a17ae 1005 if (ret < 0)
1006 return ret;
1007
1008 /* Get IPv6 routing table. */
1009 ret = netlink_request_route(zns, AF_INET6, RTM_GETROUTE);
1010 if (ret < 0)
1011 return ret;
1012 ret = netlink_parse_info(netlink_route_change_read_unicast,
85a75f1e 1013 &zns->netlink_cmd, &dp_info, 0, 1);
d62a17ae 1014 if (ret < 0)
1015 return ret;
1016
1017 return 0;
718e3744 1018}
1019
d7c0a89a
QY
1020static void _netlink_route_nl_add_gateway_info(uint8_t route_family,
1021 uint8_t gw_family,
d62a17ae 1022 struct nlmsghdr *nlmsg,
1023 size_t req_size, int bytelen,
81793ac1 1024 const struct nexthop *nexthop)
40c7bdb0 1025{
d62a17ae 1026 if (route_family == AF_MPLS) {
1027 struct gw_family_t gw_fam;
1028
1029 gw_fam.family = gw_family;
1030 if (gw_family == AF_INET)
1031 memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
1032 else
1033 memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
1034 addattr_l(nlmsg, req_size, RTA_VIA, &gw_fam.family,
1035 bytelen + 2);
1036 } else {
1037 if (gw_family == AF_INET)
1038 addattr_l(nlmsg, req_size, RTA_GATEWAY,
1039 &nexthop->gate.ipv4, bytelen);
1040 else
1041 addattr_l(nlmsg, req_size, RTA_GATEWAY,
1042 &nexthop->gate.ipv6, bytelen);
1043 }
40c7bdb0 1044}
1045
d7c0a89a
QY
1046static void _netlink_route_rta_add_gateway_info(uint8_t route_family,
1047 uint8_t gw_family,
d62a17ae 1048 struct rtattr *rta,
1049 struct rtnexthop *rtnh,
1050 size_t req_size, int bytelen,
81793ac1 1051 const struct nexthop *nexthop)
40c7bdb0 1052{
d62a17ae 1053 if (route_family == AF_MPLS) {
1054 struct gw_family_t gw_fam;
1055
1056 gw_fam.family = gw_family;
1057 if (gw_family == AF_INET)
1058 memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
1059 else
1060 memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
1061 rta_addattr_l(rta, req_size, RTA_VIA, &gw_fam.family,
1062 bytelen + 2);
1063 rtnh->rtnh_len += RTA_LENGTH(bytelen + 2);
1064 } else {
1065 if (gw_family == AF_INET)
1066 rta_addattr_l(rta, req_size, RTA_GATEWAY,
1067 &nexthop->gate.ipv4, bytelen);
1068 else
1069 rta_addattr_l(rta, req_size, RTA_GATEWAY,
1070 &nexthop->gate.ipv6, bytelen);
1071 rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
1072 }
40c7bdb0 1073}
1074
b7537db6
SW
1075static int build_label_stack(struct mpls_label_stack *nh_label,
1076 mpls_lse_t *out_lse, char *label_buf,
1077 size_t label_buf_size)
1078{
1079 char label_buf1[20];
1080 int num_labels = 0;
1081
1082 for (int i = 0; nh_label && i < nh_label->num_labels; i++) {
1083 if (nh_label->label[i] == MPLS_LABEL_IMPLICIT_NULL)
1084 continue;
1085
1086 if (IS_ZEBRA_DEBUG_KERNEL) {
1087 if (!num_labels)
1088 sprintf(label_buf, "label %u",
1089 nh_label->label[i]);
1090 else {
772270f3
QY
1091 snprintf(label_buf1, sizeof(label_buf1), "/%u",
1092 nh_label->label[i]);
b7537db6
SW
1093 strlcat(label_buf, label_buf1, label_buf_size);
1094 }
1095 }
1096
1097 out_lse[num_labels] =
1098 mpls_lse_encode(nh_label->label[i], 0, 0, 0);
1099 num_labels++;
1100 }
1101
1102 return num_labels;
1103}
1104
fa713d9e
CF
1105/* This function takes a nexthop as argument and adds
1106 * the appropriate netlink attributes to an existing
1107 * netlink message.
1108 *
1109 * @param routedesc: Human readable description of route type
1110 * (direct/recursive, single-/multipath)
1111 * @param bytelen: Length of addresses in bytes.
1112 * @param nexthop: Nexthop information
1113 * @param nlmsg: nlmsghdr structure to fill in.
1114 * @param req_size: The size allocated for the message.
1115 */
9a0132a5
DS
1116static void _netlink_route_build_singlepath(const struct prefix *p,
1117 const char *routedesc, int bytelen,
81793ac1 1118 const struct nexthop *nexthop,
d62a17ae 1119 struct nlmsghdr *nlmsg,
1120 struct rtmsg *rtmsg,
1121 size_t req_size, int cmd)
fa713d9e 1122{
b7537db6 1123
d62a17ae 1124 mpls_lse_t out_lse[MPLS_MAX_LABELS];
9a62e84b 1125 char label_buf[256];
b7537db6 1126 int num_labels = 0;
bd47f3a3 1127 struct vrf *vrf;
9266b315 1128 char addrstr[INET6_ADDRSTRLEN];
b7537db6
SW
1129
1130 assert(nexthop);
d62a17ae 1131
bd47f3a3
JU
1132 vrf = vrf_lookup_by_id(nexthop->vrf_id);
1133
d62a17ae 1134 /*
1135 * label_buf is *only* currently used within debugging.
1136 * As such when we assign it we are guarding it inside
1137 * a debug test. If you want to change this make sure
1138 * you fix this assumption
1139 */
1140 label_buf[0] = '\0';
d62a17ae 1141
b7537db6
SW
1142 num_labels = build_label_stack(nexthop->nh_label, out_lse, label_buf,
1143 sizeof(label_buf));
fa712963
RW
1144
1145 if (num_labels) {
1146 /* Set the BoS bit */
1147 out_lse[num_labels - 1] |= htonl(1 << MPLS_LS_S_SHIFT);
1148
1149 if (rtmsg->rtm_family == AF_MPLS)
1150 addattr_l(nlmsg, req_size, RTA_NEWDST, &out_lse,
1151 num_labels * sizeof(mpls_lse_t));
1152 else {
1153 struct rtattr *nest;
d7c0a89a 1154 uint16_t encap = LWTUNNEL_ENCAP_MPLS;
fa712963
RW
1155
1156 addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE, &encap,
d7c0a89a 1157 sizeof(uint16_t));
fa712963
RW
1158 nest = addattr_nest(nlmsg, req_size, RTA_ENCAP);
1159 addattr_l(nlmsg, req_size, MPLS_IPTUNNEL_DST, &out_lse,
1160 num_labels * sizeof(mpls_lse_t));
1161 addattr_nest_end(nlmsg, nest);
66d42727 1162 }
0aabccc0 1163 }
fa713d9e 1164
d62a17ae 1165 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1166 rtmsg->rtm_flags |= RTNH_F_ONLINK;
1167
1168 if (rtmsg->rtm_family == AF_INET
1169 && (nexthop->type == NEXTHOP_TYPE_IPV6
1170 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) {
1171 rtmsg->rtm_flags |= RTNH_F_ONLINK;
1172 addattr_l(nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4);
1173 addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1174
975a328e
DA
1175 if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY
1176 && (cmd == RTM_NEWROUTE))
d62a17ae 1177 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1178 &nexthop->rmap_src.ipv4, bytelen);
975a328e
DA
1179 else if (nexthop->src.ipv4.s_addr != INADDR_ANY
1180 && (cmd == RTM_NEWROUTE))
d62a17ae 1181 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1182 &nexthop->src.ipv4, bytelen);
1183
1184 if (IS_ZEBRA_DEBUG_KERNEL)
9266b315
RZ
1185 zlog_debug("%s: 5549 (%s): %pFX nexthop via %s %s if %u vrf %s(%u)",
1186 __func__, routedesc, p, ipv4_ll_buf,
1187 label_buf, nexthop->ifindex,
1188 VRF_LOGNAME(vrf), nexthop->vrf_id);
d62a17ae 1189 return;
0aabccc0
DD
1190 }
1191
d62a17ae 1192 if (nexthop->type == NEXTHOP_TYPE_IPV4
1193 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
1194 /* Send deletes to the kernel without specifying the next-hop */
1195 if (cmd != RTM_DELROUTE)
1196 _netlink_route_nl_add_gateway_info(
1197 rtmsg->rtm_family, AF_INET, nlmsg, req_size,
1198 bytelen, nexthop);
1199
1200 if (cmd == RTM_NEWROUTE) {
975a328e 1201 if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY)
d62a17ae 1202 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1203 &nexthop->rmap_src.ipv4, bytelen);
975a328e 1204 else if (nexthop->src.ipv4.s_addr != INADDR_ANY)
d62a17ae 1205 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1206 &nexthop->src.ipv4, bytelen);
1207 }
1208
9266b315
RZ
1209 if (IS_ZEBRA_DEBUG_KERNEL) {
1210 inet_ntop(AF_INET, &nexthop->gate.ipv4, addrstr,
1211 sizeof(addrstr));
1212 zlog_debug("%s: (%s): %pFX nexthop via %s %s if %u vrf %s(%u)",
1213 __func__, routedesc, p, addrstr, label_buf,
1214 nexthop->ifindex, VRF_LOGNAME(vrf),
1215 nexthop->vrf_id);
1216 }
0aabccc0 1217 }
fa713d9e 1218
d62a17ae 1219 if (nexthop->type == NEXTHOP_TYPE_IPV6
1220 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
1221 _netlink_route_nl_add_gateway_info(rtmsg->rtm_family, AF_INET6,
1222 nlmsg, req_size, bytelen,
1223 nexthop);
1224
1225 if (cmd == RTM_NEWROUTE) {
1226 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
1227 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1228 &nexthop->rmap_src.ipv6, bytelen);
1229 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
1230 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1231 &nexthop->src.ipv6, bytelen);
1232 }
fa713d9e 1233
9266b315
RZ
1234 if (IS_ZEBRA_DEBUG_KERNEL) {
1235 inet_ntop(AF_INET6, &nexthop->gate.ipv6, addrstr,
1236 sizeof(addrstr));
1237 zlog_debug("%s: (%s): %pFX nexthop via %s %s if %u vrf %s(%u)",
1238 __func__, routedesc, p, addrstr, label_buf,
1239 nexthop->ifindex, VRF_LOGNAME(vrf),
1240 nexthop->vrf_id);
1241 }
d62a17ae 1242 }
5e210522
DS
1243
1244 /*
1245 * We have the ifindex so we should always send it
1246 * This is especially useful if we are doing route
1247 * leaking.
1248 */
1249 if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
d62a17ae 1250 addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1251
275565fb 1252 if (nexthop->type == NEXTHOP_TYPE_IFINDEX) {
d62a17ae 1253 if (cmd == RTM_NEWROUTE) {
975a328e 1254 if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY)
d62a17ae 1255 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1256 &nexthop->rmap_src.ipv4, bytelen);
975a328e 1257 else if (nexthop->src.ipv4.s_addr != INADDR_ANY)
d62a17ae 1258 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1259 &nexthop->src.ipv4, bytelen);
1260 }
fa713d9e 1261
d62a17ae 1262 if (IS_ZEBRA_DEBUG_KERNEL)
9266b315
RZ
1263 zlog_debug("%s: (%s): %pFX nexthop via if %u vrf %s(%u)",
1264 __func__, routedesc, p, nexthop->ifindex,
1265 VRF_LOGNAME(vrf), nexthop->vrf_id);
0aabccc0 1266 }
fa713d9e
CF
1267}
1268
1269/* This function takes a nexthop as argument and
1270 * appends to the given rtattr/rtnexthop pair the
1271 * representation of the nexthop. If the nexthop
1272 * defines a preferred source, the src parameter
1273 * will be modified to point to that src, otherwise
1274 * it will be kept unmodified.
1275 *
1276 * @param routedesc: Human readable description of route type
1277 * (direct/recursive, single-/multipath)
1278 * @param bytelen: Length of addresses in bytes.
1279 * @param nexthop: Nexthop information
1280 * @param rta: rtnetlink attribute structure
1281 * @param rtnh: pointer to an rtnetlink nexthop structure
1282 * @param src: pointer pointing to a location where
1283 * the prefsrc should be stored.
1284 */
9a0132a5
DS
1285static void
1286_netlink_route_build_multipath(const struct prefix *p, const char *routedesc,
1287 int bytelen, const struct nexthop *nexthop,
1288 struct rtattr *rta, struct rtnexthop *rtnh,
1289 struct rtmsg *rtmsg, const union g_addr **src)
fa713d9e 1290{
d62a17ae 1291 mpls_lse_t out_lse[MPLS_MAX_LABELS];
9a62e84b 1292 char label_buf[256];
b7537db6 1293 int num_labels = 0;
bd47f3a3 1294 struct vrf *vrf;
d62a17ae 1295
1296 rtnh->rtnh_len = sizeof(*rtnh);
1297 rtnh->rtnh_flags = 0;
1298 rtnh->rtnh_hops = 0;
1299 rta->rta_len += rtnh->rtnh_len;
1300
b7537db6
SW
1301 assert(nexthop);
1302
bd47f3a3
JU
1303 vrf = vrf_lookup_by_id(nexthop->vrf_id);
1304
d62a17ae 1305 /*
1306 * label_buf is *only* currently used within debugging.
1307 * As such when we assign it we are guarding it inside
1308 * a debug test. If you want to change this make sure
1309 * you fix this assumption
1310 */
1311 label_buf[0] = '\0';
d62a17ae 1312
b7537db6
SW
1313 num_labels = build_label_stack(nexthop->nh_label, out_lse, label_buf,
1314 sizeof(label_buf));
fa712963
RW
1315
1316 if (num_labels) {
1317 /* Set the BoS bit */
1318 out_lse[num_labels - 1] |= htonl(1 << MPLS_LS_S_SHIFT);
1319
1320 if (rtmsg->rtm_family == AF_MPLS) {
1321 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_NEWDST,
1322 &out_lse,
1323 num_labels * sizeof(mpls_lse_t));
1324 rtnh->rtnh_len +=
1325 RTA_LENGTH(num_labels * sizeof(mpls_lse_t));
1326 } else {
1327 struct rtattr *nest;
d7c0a89a 1328 uint16_t encap = LWTUNNEL_ENCAP_MPLS;
fa712963
RW
1329 int len = rta->rta_len;
1330
1331 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_ENCAP_TYPE,
d7c0a89a 1332 &encap, sizeof(uint16_t));
fa712963
RW
1333 nest = rta_nest(rta, NL_PKT_BUF_SIZE, RTA_ENCAP);
1334 rta_addattr_l(rta, NL_PKT_BUF_SIZE, MPLS_IPTUNNEL_DST,
1335 &out_lse,
1336 num_labels * sizeof(mpls_lse_t));
1337 rta_nest_end(rta, nest);
1338 rtnh->rtnh_len += rta->rta_len - len;
66d42727 1339 }
d62a17ae 1340 }
1341
1342 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1343 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1344
1345 if (rtmsg->rtm_family == AF_INET
1346 && (nexthop->type == NEXTHOP_TYPE_IPV6
1347 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) {
1348 bytelen = 4;
1349 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1350 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_GATEWAY, &ipv4_ll,
1351 bytelen);
1352 rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
1353 rtnh->rtnh_ifindex = nexthop->ifindex;
8d27e1aa 1354 if (nexthop->weight)
1355 rtnh->rtnh_hops = nexthop->weight - 1;
d62a17ae 1356
975a328e 1357 if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY)
d62a17ae 1358 *src = &nexthop->rmap_src;
975a328e 1359 else if (nexthop->src.ipv4.s_addr != INADDR_ANY)
d62a17ae 1360 *src = &nexthop->src;
1361
1362 if (IS_ZEBRA_DEBUG_KERNEL)
1363 zlog_debug(
9266b315
RZ
1364 "%s: 5549 (%s): %pFX nexthop via %s %s if %u vrf %s(%u)",
1365 __func__, routedesc, p, ipv4_ll_buf, label_buf,
bd47f3a3
JU
1366 nexthop->ifindex, VRF_LOGNAME(vrf),
1367 nexthop->vrf_id);
d62a17ae 1368 return;
1369 }
1370
1371 if (nexthop->type == NEXTHOP_TYPE_IPV4
1372 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
1373 _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET,
1374 rta, rtnh, NL_PKT_BUF_SIZE,
1375 bytelen, nexthop);
975a328e 1376 if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY)
d62a17ae 1377 *src = &nexthop->rmap_src;
975a328e 1378 else if (nexthop->src.ipv4.s_addr != INADDR_ANY)
d62a17ae 1379 *src = &nexthop->src;
1380
a50404aa
RZ
1381 if (IS_ZEBRA_DEBUG_KERNEL)
1382 zlog_debug("%s: (%s): %pFX nexthop via %pI4 %s if %u vrf %s(%u)",
1383 __func__, routedesc, p, &nexthop->gate.ipv4,
1384 label_buf, nexthop->ifindex,
1385 VRF_LOGNAME(vrf), nexthop->vrf_id);
d62a17ae 1386 }
1387 if (nexthop->type == NEXTHOP_TYPE_IPV6
1388 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
1389 _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET6,
1390 rta, rtnh, NL_PKT_BUF_SIZE,
1391 bytelen, nexthop);
1392
1393 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
1394 *src = &nexthop->rmap_src;
1395 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
1396 *src = &nexthop->src;
1397
a50404aa
RZ
1398 if (IS_ZEBRA_DEBUG_KERNEL)
1399 zlog_debug("%s: (%s): %pFX nexthop via %pI6 %s if %u vrf %s(%u)",
1400 __func__, routedesc, p, &nexthop->gate.ipv6,
1401 label_buf, nexthop->ifindex,
1402 VRF_LOGNAME(vrf), nexthop->vrf_id);
d62a17ae 1403 }
5e210522
DS
1404
1405 /*
1406 * We have figured out the ifindex so we should always send it
1407 * This is especially useful if we are doing route
1408 * leaking.
1409 */
1410 if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
1411 rtnh->rtnh_ifindex = nexthop->ifindex;
1412
d62a17ae 1413 /* ifindex */
275565fb 1414 if (nexthop->type == NEXTHOP_TYPE_IFINDEX) {
975a328e 1415 if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY)
d62a17ae 1416 *src = &nexthop->rmap_src;
975a328e 1417 else if (nexthop->src.ipv4.s_addr != INADDR_ANY)
d62a17ae 1418 *src = &nexthop->src;
1419
1420 if (IS_ZEBRA_DEBUG_KERNEL)
9266b315
RZ
1421 zlog_debug("%s: (%s): %pFX nexthop via if %u vrf %s(%u)",
1422 __func__, routedesc, p, nexthop->ifindex,
1423 VRF_LOGNAME(vrf), nexthop->vrf_id);
d62a17ae 1424 }
df7fb580
DS
1425
1426 if (nexthop->weight)
1427 rtnh->rtnh_hops = nexthop->weight - 1;
fa713d9e
CF
1428}
1429
9a0132a5
DS
1430static inline void _netlink_mpls_build_singlepath(const struct prefix *p,
1431 const char *routedesc,
81793ac1 1432 const zebra_nhlfe_t *nhlfe,
d62a17ae 1433 struct nlmsghdr *nlmsg,
1434 struct rtmsg *rtmsg,
1435 size_t req_size, int cmd)
40c7bdb0 1436{
d62a17ae 1437 int bytelen;
d7c0a89a 1438 uint8_t family;
40c7bdb0 1439
d62a17ae 1440 family = NHLFE_FAMILY(nhlfe);
1441 bytelen = (family == AF_INET ? 4 : 16);
9a0132a5 1442 _netlink_route_build_singlepath(p, routedesc, bytelen, nhlfe->nexthop,
d62a17ae 1443 nlmsg, rtmsg, req_size, cmd);
40c7bdb0 1444}
1445
1446
1447static inline void
9a0132a5
DS
1448_netlink_mpls_build_multipath(const struct prefix *p, const char *routedesc,
1449 const zebra_nhlfe_t *nhlfe, struct rtattr *rta,
1450 struct rtnexthop *rtnh, struct rtmsg *rtmsg,
1451 const union g_addr **src)
40c7bdb0 1452{
d62a17ae 1453 int bytelen;
d7c0a89a 1454 uint8_t family;
40c7bdb0 1455
d62a17ae 1456 family = NHLFE_FAMILY(nhlfe);
1457 bytelen = (family == AF_INET ? 4 : 16);
9a0132a5
DS
1458 _netlink_route_build_multipath(p, routedesc, bytelen, nhlfe->nexthop,
1459 rta, rtnh, rtmsg, src);
40c7bdb0 1460}
1461
d7c0a89a 1462static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc)
40c7bdb0 1463{
d62a17ae 1464 if (IS_ZEBRA_DEBUG_KERNEL)
1465 zlog_debug("netlink_mpls_multipath() (%s): %s %u/20", routedesc,
1466 nl_msg_type_to_str(cmd), label);
fa713d9e
CF
1467}
1468
d62a17ae 1469static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
5895d33f 1470 int llalen, ns_id_t ns_id)
5c610faf 1471{
f3dbec60 1472 uint8_t protocol = RTPROT_ZEBRA;
d62a17ae 1473 struct {
1474 struct nlmsghdr n;
1475 struct ndmsg ndm;
1476 char buf[256];
1477 } req;
5c610faf 1478
5895d33f 1479 struct zebra_ns *zns = zebra_ns_lookup(ns_id);
8f7d9fc0 1480
5605ecfc 1481 memset(&req, 0, sizeof(req));
5c610faf 1482
d62a17ae 1483 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1484 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1485 req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
1486 req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
a55ba23f 1487
d62a17ae 1488 req.ndm.ndm_family = AF_INET;
1489 req.ndm.ndm_state = NUD_PERMANENT;
1490 req.ndm.ndm_ifindex = ifindex;
1491 req.ndm.ndm_type = RTN_UNICAST;
5c610faf 1492
f3dbec60
DS
1493 addattr_l(&req.n, sizeof(req),
1494 NDA_PROTOCOL, &protocol, sizeof(protocol));
d62a17ae 1495 addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
1496 addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
5c610faf 1497
d62a17ae 1498 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
1499 0);
5c610faf
DS
1500}
1501
762288f5
SW
1502static bool nexthop_set_src(const struct nexthop *nexthop, int family,
1503 union g_addr *src)
1504{
1505 if (family == AF_INET) {
1506 if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY) {
1507 src->ipv4 = nexthop->rmap_src.ipv4;
1508 return true;
1509 } else if (nexthop->src.ipv4.s_addr != INADDR_ANY) {
1510 src->ipv4 = nexthop->src.ipv4;
1511 return true;
1512 }
1513 } else if (family == AF_INET6) {
1514 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) {
1515 src->ipv6 = nexthop->rmap_src.ipv6;
1516 return true;
1517 } else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) {
1518 src->ipv6 = nexthop->src.ipv6;
1519 return true;
1520 }
1521 }
1522
1523 return false;
1524}
1525
f2a0ba3a
RZ
1526static void netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen,
1527 struct nexthop *nh)
1528{
1529 struct rtattr *nest;
1530
1531 switch (nh->nh_encap_type) {
1532 case NET_VXLAN:
1533 addattr_l(n, nlen, RTA_ENCAP_TYPE, &nh->nh_encap_type,
1534 sizeof(uint16_t));
1535
1536 nest = addattr_nest(n, nlen, RTA_ENCAP);
1537 addattr32(n, nlen, 0 /* VXLAN_VNI */, nh->nh_encap.vni);
1538 addattr_nest_end(n, nest);
1539 break;
1540 }
1541}
1542
7cdb1a84
MS
1543/*
1544 * Routing table change via netlink interface, using a dataplane context object
1545 */
f78fe8f3 1546ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
f2a0ba3a 1547 uint8_t *data, size_t datalen, bool fpm)
7cdb1a84
MS
1548{
1549 int bytelen;
7cdb1a84
MS
1550 struct nexthop *nexthop = NULL;
1551 unsigned int nexthop_num;
7cdb1a84 1552 const char *routedesc;
762288f5 1553 bool setsrc = false;
7cdb1a84
MS
1554 union g_addr src;
1555 const struct prefix *p, *src_p;
1556 uint32_t table_id;
1557
1558 struct {
1559 struct nlmsghdr n;
1560 struct rtmsg r;
e57a3fab
RZ
1561 char buf[];
1562 } *req = (void *)data;
7cdb1a84
MS
1563
1564 p = dplane_ctx_get_dest(ctx);
1565 src_p = dplane_ctx_get_src(ctx);
1566
e57a3fab 1567 memset(req, 0, sizeof(*req));
7cdb1a84 1568
b9c87515 1569 bytelen = (p->family == AF_INET ? 4 : 16);
7cdb1a84 1570
e57a3fab
RZ
1571 req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1572 req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
7cdb1a84 1573
334734a8
DS
1574 if ((cmd == RTM_NEWROUTE) &&
1575 ((p->family == AF_INET) || v6_rr_semantics))
e57a3fab 1576 req->n.nlmsg_flags |= NLM_F_REPLACE;
7cdb1a84 1577
e57a3fab 1578 req->n.nlmsg_type = cmd;
7cdb1a84 1579
e57a3fab 1580 req->n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid;
7cdb1a84 1581
b9c87515 1582 req->r.rtm_family = p->family;
e57a3fab
RZ
1583 req->r.rtm_dst_len = p->prefixlen;
1584 req->r.rtm_src_len = src_p ? src_p->prefixlen : 0;
1585 req->r.rtm_scope = RT_SCOPE_UNIVERSE;
7cdb1a84 1586
5709131c 1587 if (cmd == RTM_DELROUTE)
e57a3fab 1588 req->r.rtm_protocol = zebra2proto(dplane_ctx_get_old_type(ctx));
5709131c 1589 else
e57a3fab 1590 req->r.rtm_protocol = zebra2proto(dplane_ctx_get_type(ctx));
7cdb1a84
MS
1591
1592 /*
1593 * blackhole routes are not RTN_UNICAST, they are
1594 * RTN_ BLACKHOLE|UNREACHABLE|PROHIBIT
1595 * so setting this value as a RTN_UNICAST would
1596 * cause the route lookup of just the prefix
1597 * to fail. So no need to specify this for
1598 * the RTM_DELROUTE case
1599 */
1600 if (cmd != RTM_DELROUTE)
e57a3fab 1601 req->r.rtm_type = RTN_UNICAST;
7cdb1a84 1602
e57a3fab 1603 addattr_l(&req->n, datalen, RTA_DST, &p->u.prefix, bytelen);
7cdb1a84 1604 if (src_p)
e57a3fab 1605 addattr_l(&req->n, datalen, RTA_SRC, &src_p->u.prefix, bytelen);
7cdb1a84
MS
1606
1607 /* Metric. */
1608 /* Hardcode the metric for all routes coming from zebra. Metric isn't
1609 * used
1610 * either by the kernel or by zebra. Its purely for calculating best
1611 * path(s)
1612 * by the routing protocol and for communicating with protocol peers.
1613 */
e57a3fab 1614 addattr32(&req->n, datalen, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
7cdb1a84
MS
1615
1616#if defined(SUPPORT_REALMS)
1617 {
1618 route_tag_t tag;
1619
5709131c 1620 if (cmd == RTM_DELROUTE)
7cdb1a84 1621 tag = dplane_ctx_get_old_tag(ctx);
5709131c 1622 else
7cdb1a84 1623 tag = dplane_ctx_get_tag(ctx);
7cdb1a84
MS
1624
1625 if (tag > 0 && tag <= 255)
e57a3fab 1626 addattr32(&req->n, datalen, RTA_FLOW, tag);
7cdb1a84
MS
1627 }
1628#endif
1629 /* Table corresponding to this route. */
1630 table_id = dplane_ctx_get_table(ctx);
1631 if (table_id < 256)
e57a3fab 1632 req->r.rtm_table = table_id;
7cdb1a84 1633 else {
e57a3fab
RZ
1634 req->r.rtm_table = RT_TABLE_UNSPEC;
1635 addattr32(&req->n, datalen, RTA_TABLE, table_id);
7cdb1a84
MS
1636 }
1637
9266b315
RZ
1638 if (IS_ZEBRA_DEBUG_KERNEL)
1639 zlog_debug(
1640 "%s: %s %pFX vrf %u(%u)", __func__,
1641 nl_msg_type_to_str(cmd), p, dplane_ctx_get_vrf(ctx),
1642 table_id);
7cdb1a84
MS
1643
1644 /*
1645 * If we are not updating the route and we have received
1646 * a route delete, then all we need to fill in is the
1647 * prefix information to tell the kernel to schwack
1648 * it.
1649 */
1650 if (cmd == RTM_DELROUTE)
f78fe8f3 1651 return req->n.nlmsg_len;
7cdb1a84
MS
1652
1653 if (dplane_ctx_get_mtu(ctx) || dplane_ctx_get_nh_mtu(ctx)) {
1654 char buf[NL_PKT_BUF_SIZE];
1655 struct rtattr *rta = (void *)buf;
1656 uint32_t mtu = dplane_ctx_get_mtu(ctx);
1657 uint32_t nexthop_mtu = dplane_ctx_get_nh_mtu(ctx);
5709131c 1658
7cdb1a84
MS
1659 if (!mtu || (nexthop_mtu && nexthop_mtu < mtu))
1660 mtu = nexthop_mtu;
1661 rta->rta_type = RTA_METRICS;
1662 rta->rta_len = RTA_LENGTH(0);
5709131c
MS
1663 rta_addattr_l(rta, NL_PKT_BUF_SIZE,
1664 RTAX_MTU, &mtu, sizeof(mtu));
e57a3fab 1665 addattr_l(&req->n, datalen, RTA_METRICS, RTA_DATA(rta),
7cdb1a84
MS
1666 RTA_PAYLOAD(rta));
1667 }
1668
7c99d51b 1669 if (kernel_nexthops_supported()) {
d8bfd8dc 1670 /* Kernel supports nexthop objects */
9a0132a5
DS
1671 if (IS_ZEBRA_DEBUG_KERNEL)
1672 zlog_debug(
1673 "netlink_route_multipath(): %pFX nhg_id is %u",
1674 p, dplane_ctx_get_nhe_id(ctx));
e57a3fab
RZ
1675
1676 addattr32(&req->n, datalen, RTA_NH_ID,
de3f5488 1677 dplane_ctx_get_nhe_id(ctx));
d8bfd8dc
SW
1678
1679 /* Have to determine src still */
1680 for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
1681 if (setsrc)
1682 break;
1683
e57a3fab 1684 setsrc = nexthop_set_src(nexthop, p->family, &src);
d8bfd8dc
SW
1685 }
1686
1687 if (setsrc) {
b9c87515 1688 if (p->family == AF_INET)
e57a3fab 1689 addattr_l(&req->n, datalen, RTA_PREFSRC,
d8bfd8dc 1690 &src.ipv4, bytelen);
b9c87515 1691 else if (p->family == AF_INET6)
e57a3fab 1692 addattr_l(&req->n, datalen, RTA_PREFSRC,
d8bfd8dc
SW
1693 &src.ipv6, bytelen);
1694 }
f78fe8f3
RZ
1695
1696 return req->n.nlmsg_len;
de3f5488
SW
1697 }
1698
7cdb1a84 1699 /* Count overall nexthops so we can decide whether to use singlepath
5709131c
MS
1700 * or multipath case.
1701 */
7cdb1a84
MS
1702 nexthop_num = 0;
1703 for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
1704 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1705 continue;
b9c87515 1706 if (!NEXTHOP_IS_ACTIVE(nexthop->flags))
7cdb1a84
MS
1707 continue;
1708
1709 nexthop_num++;
1710 }
1711
1712 /* Singlepath case. */
220f0f42 1713 if (nexthop_num == 1) {
7cdb1a84
MS
1714 nexthop_num = 0;
1715 for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
1716 /*
1717 * So we want to cover 2 types of blackhole
1718 * routes here:
1719 * 1) A normal blackhole route( ala from a static
1720 * install.
1721 * 2) A recursively resolved blackhole route
1722 */
1723 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
1724 switch (nexthop->bh_type) {
1725 case BLACKHOLE_ADMINPROHIB:
e57a3fab 1726 req->r.rtm_type = RTN_PROHIBIT;
7cdb1a84
MS
1727 break;
1728 case BLACKHOLE_REJECT:
e57a3fab 1729 req->r.rtm_type = RTN_UNREACHABLE;
7cdb1a84
MS
1730 break;
1731 default:
e57a3fab 1732 req->r.rtm_type = RTN_BLACKHOLE;
7cdb1a84
MS
1733 break;
1734 }
f78fe8f3 1735 return req->n.nlmsg_len;
7cdb1a84
MS
1736 }
1737 if (CHECK_FLAG(nexthop->flags,
1738 NEXTHOP_FLAG_RECURSIVE)) {
5709131c
MS
1739
1740 if (setsrc)
1741 continue;
1742
b9c87515
RZ
1743 setsrc = nexthop_set_src(nexthop, p->family,
1744 &src);
f183e380 1745 continue;
7cdb1a84
MS
1746 }
1747
b9c87515 1748 if (NEXTHOP_IS_ACTIVE(nexthop->flags)) {
7cdb1a84
MS
1749 routedesc = nexthop->rparent
1750 ? "recursive, single-path"
1751 : "single-path";
1752
1753 _netlink_route_build_singlepath(
e57a3fab
RZ
1754 p, routedesc, bytelen, nexthop, &req->n,
1755 &req->r, datalen, cmd);
7cdb1a84
MS
1756 nexthop_num++;
1757 break;
1758 }
f2a0ba3a
RZ
1759
1760 /*
1761 * Add encapsulation information when installing via
1762 * FPM.
1763 */
1764 if (fpm)
1765 netlink_route_nexthop_encap(&req->n, datalen,
1766 nexthop);
7cdb1a84 1767 }
f2a0ba3a 1768
13e0321a 1769 if (setsrc) {
b9c87515 1770 if (p->family == AF_INET)
e57a3fab 1771 addattr_l(&req->n, datalen, RTA_PREFSRC,
7cdb1a84 1772 &src.ipv4, bytelen);
b9c87515 1773 else if (p->family == AF_INET6)
e57a3fab 1774 addattr_l(&req->n, datalen, RTA_PREFSRC,
7cdb1a84
MS
1775 &src.ipv6, bytelen);
1776 }
1777 } else { /* Multipath case */
1778 char buf[NL_PKT_BUF_SIZE];
1779 struct rtattr *rta = (void *)buf;
1780 struct rtnexthop *rtnh;
81793ac1 1781 const union g_addr *src1 = NULL;
7cdb1a84
MS
1782
1783 rta->rta_type = RTA_MULTIPATH;
1784 rta->rta_len = RTA_LENGTH(0);
1785 rtnh = RTA_DATA(rta);
1786
1787 nexthop_num = 0;
1788 for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
7cdb1a84
MS
1789 if (CHECK_FLAG(nexthop->flags,
1790 NEXTHOP_FLAG_RECURSIVE)) {
1791 /* This only works for IPv4 now */
5709131c
MS
1792 if (setsrc)
1793 continue;
1794
b9c87515
RZ
1795 setsrc = nexthop_set_src(nexthop, p->family,
1796 &src);
78e54ded 1797 continue;
7cdb1a84
MS
1798 }
1799
b9c87515 1800 if (NEXTHOP_IS_ACTIVE(nexthop->flags)) {
7cdb1a84
MS
1801 routedesc = nexthop->rparent
1802 ? "recursive, multipath"
1803 : "multipath";
1804 nexthop_num++;
1805
1806 _netlink_route_build_multipath(
9a0132a5 1807 p, routedesc, bytelen, nexthop, rta,
e57a3fab 1808 rtnh, &req->r, &src1);
7cdb1a84
MS
1809 rtnh = RTNH_NEXT(rtnh);
1810
1811 if (!setsrc && src1) {
b9c87515 1812 if (p->family == AF_INET)
7cdb1a84 1813 src.ipv4 = src1->ipv4;
b9c87515 1814 else if (p->family == AF_INET6)
7cdb1a84
MS
1815 src.ipv6 = src1->ipv6;
1816
1817 setsrc = 1;
1818 }
1819 }
f2a0ba3a
RZ
1820
1821 /*
1822 * Add encapsulation information when installing via
1823 * FPM.
1824 */
1825 if (fpm)
1826 netlink_route_nexthop_encap(&req->n, datalen,
1827 nexthop);
7cdb1a84 1828 }
f2a0ba3a 1829
13e0321a 1830 if (setsrc) {
b9c87515 1831 if (p->family == AF_INET)
e57a3fab 1832 addattr_l(&req->n, datalen, RTA_PREFSRC,
7cdb1a84 1833 &src.ipv4, bytelen);
b9c87515 1834 else if (p->family == AF_INET6)
e57a3fab 1835 addattr_l(&req->n, datalen, RTA_PREFSRC,
7cdb1a84
MS
1836 &src.ipv6, bytelen);
1837 if (IS_ZEBRA_DEBUG_KERNEL)
1838 zlog_debug("Setting source");
1839 }
1840
1841 if (rta->rta_len > RTA_LENGTH(0))
e57a3fab 1842 addattr_l(&req->n, datalen, RTA_MULTIPATH,
7cdb1a84
MS
1843 RTA_DATA(rta), RTA_PAYLOAD(rta));
1844 }
1845
1846 /* If there is no useful nexthop then return. */
1847 if (nexthop_num == 0) {
1848 if (IS_ZEBRA_DEBUG_KERNEL)
9266b315 1849 zlog_debug("%s: No useful nexthop.", __func__);
7cdb1a84
MS
1850 }
1851
f78fe8f3 1852 return req->n.nlmsg_len;
7cdb1a84
MS
1853}
1854
43b5cc5e 1855int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
e3be0432 1856{
5523c156 1857 uint32_t actual_table;
d62a17ae 1858 int suc = 0;
1859 struct mcast_route_data *mr = (struct mcast_route_data *)in;
bd8b9272
DS
1860 struct {
1861 struct nlmsghdr n;
1862 struct ndmsg ndm;
1863 char buf[256];
1864 } req;
e3be0432 1865
d62a17ae 1866 mroute = mr;
5895d33f 1867 struct zebra_ns *zns;
bd8b9272 1868
009f8ad5 1869 zns = zvrf->zns;
5605ecfc 1870 memset(&req, 0, sizeof(req));
bd8b9272
DS
1871
1872 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1873 req.n.nlmsg_flags = NLM_F_REQUEST;
1874 req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
1875
1876 req.ndm.ndm_family = RTNL_FAMILY_IPMR;
1877 req.n.nlmsg_type = RTM_GETROUTE;
1878
1879 addattr_l(&req.n, sizeof(req), RTA_IIF, &mroute->ifindex, 4);
1880 addattr_l(&req.n, sizeof(req), RTA_OIF, &mroute->ifindex, 4);
1881 addattr_l(&req.n, sizeof(req), RTA_SRC, &mroute->sg.src.s_addr, 4);
1882 addattr_l(&req.n, sizeof(req), RTA_DST, &mroute->sg.grp.s_addr, 4);
5523c156
DS
1883 /*
1884 * What?
1885 *
1886 * So during the namespace cleanup we started storing
1887 * the zvrf table_id for the default table as RT_TABLE_MAIN
1888 * which is what the normal routing table for ip routing is.
1889 * This change caused this to break our lookups of sg data
1890 * because prior to this change the zvrf->table_id was 0
1891 * and when the pim multicast kernel code saw a 0,
1892 * it was auto-translated to RT_TABLE_DEFAULT. But since
1893 * we are now passing in RT_TABLE_MAIN there is no auto-translation
1894 * and the kernel goes screw you and the delicious cookies you
1895 * are trying to give me. So now we have this little hack.
1896 */
1897 actual_table = (zvrf->table_id == RT_TABLE_MAIN) ? RT_TABLE_DEFAULT :
1898 zvrf->table_id;
1899 addattr_l(&req.n, sizeof(req), RTA_TABLE, &actual_table, 4);
e3be0432 1900
bd8b9272
DS
1901 suc = netlink_talk(netlink_route_change_read_multicast, &req.n,
1902 &zns->netlink_cmd, zns, 0);
e3be0432 1903
bd8b9272 1904 mroute = NULL;
d62a17ae 1905 return suc;
e3be0432
DS
1906}
1907
8d03bc50
SW
1908/* Char length to debug ID with */
1909#define ID_LENGTH 10
1910
565ce0d3 1911static void _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size,
8d03bc50 1912 uint32_t id,
e22e8001 1913 const struct nh_grp *z_grp,
0c8215cb 1914 const uint8_t count)
565ce0d3 1915{
565ce0d3 1916 struct nexthop_grp grp[count];
8d03bc50
SW
1917 /* Need space for max group size, "/", and null term */
1918 char buf[(MULTIPATH_NUM * (ID_LENGTH + 1)) + 1];
1919 char buf1[ID_LENGTH + 2];
1920
1921 buf[0] = '\0';
565ce0d3
SW
1922
1923 memset(grp, 0, sizeof(grp));
1924
1925 if (count) {
0c8215cb 1926 for (int i = 0; i < count; i++) {
e22e8001 1927 grp[i].id = z_grp[i].id;
df7fb580 1928 grp[i].weight = z_grp[i].weight - 1;
8d03bc50
SW
1929
1930 if (IS_ZEBRA_DEBUG_KERNEL) {
1931 if (i == 0)
1932 snprintf(buf, sizeof(buf1), "group %u",
1933 grp[i].id);
1934 else {
1935 snprintf(buf1, sizeof(buf1), "/%u",
1936 grp[i].id);
1937 strlcat(buf, buf1, sizeof(buf));
1938 }
1939 }
565ce0d3 1940 }
0c8215cb 1941 addattr_l(n, req_size, NHA_GROUP, grp, count * sizeof(*grp));
565ce0d3 1942 }
8d03bc50
SW
1943
1944 if (IS_ZEBRA_DEBUG_KERNEL)
1945 zlog_debug("%s: ID (%u): %s", __func__, id, buf);
565ce0d3
SW
1946}
1947
f820d025
SW
1948/**
1949 * netlink_nexthop() - Nexthop change via the netlink interface
1950 *
1951 * @ctx: Dataplane ctx
1952 *
1953 * Return: Result status
1954 */
1955static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx)
1956{
f820d025
SW
1957 struct {
1958 struct nlmsghdr n;
1959 struct nhmsg nhm;
1960 char buf[NL_PKT_BUF_SIZE];
1961 } req;
1962
8d03bc50
SW
1963 mpls_lse_t out_lse[MPLS_MAX_LABELS];
1964 char label_buf[256];
1965 int num_labels = 0;
1966 size_t req_size = sizeof(req);
1967
81505946 1968 /* Nothing to do if the kernel doesn't support nexthop objects */
7c99d51b 1969 if (!kernel_nexthops_supported())
81505946
SW
1970 return 0;
1971
8d03bc50
SW
1972 label_buf[0] = '\0';
1973
1974 memset(&req, 0, req_size);
f820d025 1975
f820d025
SW
1976 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg));
1977 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
9a1588c4
SW
1978
1979 if (cmd == RTM_NEWNEXTHOP)
1980 req.n.nlmsg_flags |= NLM_F_REPLACE;
1981
f820d025 1982 req.n.nlmsg_type = cmd;
4f096395 1983 req.n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid;
f820d025
SW
1984
1985 req.nhm.nh_family = AF_UNSPEC;
fec211ad 1986 /* TODO: Scope? */
f820d025 1987
0c8215cb
SW
1988 uint32_t id = dplane_ctx_get_nhe_id(ctx);
1989
1990 if (!id) {
f820d025
SW
1991 flog_err(
1992 EC_ZEBRA_NHG_FIB_UPDATE,
1993 "Failed trying to update a nexthop group in the kernel that does not have an ID");
1994 return -1;
1995 }
1996
8d03bc50 1997 addattr32(&req.n, req_size, NHA_ID, id);
f820d025
SW
1998
1999 if (cmd == RTM_NEWNEXTHOP) {
bf1626a6
MS
2000 /*
2001 * We distinguish between a "group", which is a collection
2002 * of ids, and a singleton nexthop with an id. The
2003 * group is installed as an id that just refers to a list of
2004 * other ids.
2005 */
e22e8001 2006 if (dplane_ctx_get_nhe_nh_grp_count(ctx))
0c8215cb 2007 _netlink_nexthop_build_group(
8d03bc50 2008 &req.n, req_size, id,
e22e8001
SW
2009 dplane_ctx_get_nhe_nh_grp(ctx),
2010 dplane_ctx_get_nhe_nh_grp_count(ctx));
0c8215cb
SW
2011 else {
2012 const struct nexthop *nh =
2013 dplane_ctx_get_nhe_ng(ctx)->nexthop;
2014 afi_t afi = dplane_ctx_get_nhe_afi(ctx);
e8b0e420 2015
0c8215cb 2016 if (afi == AFI_IP)
565ce0d3 2017 req.nhm.nh_family = AF_INET;
0c8215cb 2018 else if (afi == AFI_IP6)
565ce0d3 2019 req.nhm.nh_family = AF_INET6;
f820d025 2020
565ce0d3 2021 switch (nh->type) {
a6e6a6d8 2022 case NEXTHOP_TYPE_IPV4:
565ce0d3 2023 case NEXTHOP_TYPE_IPV4_IFINDEX:
8d03bc50 2024 addattr_l(&req.n, req_size, NHA_GATEWAY,
565ce0d3
SW
2025 &nh->gate.ipv4, IPV4_MAX_BYTELEN);
2026 break;
a6e6a6d8 2027 case NEXTHOP_TYPE_IPV6:
565ce0d3 2028 case NEXTHOP_TYPE_IPV6_IFINDEX:
8d03bc50 2029 addattr_l(&req.n, req_size, NHA_GATEWAY,
565ce0d3
SW
2030 &nh->gate.ipv6, IPV6_MAX_BYTELEN);
2031 break;
2032 case NEXTHOP_TYPE_BLACKHOLE:
8d03bc50
SW
2033 addattr_l(&req.n, req_size, NHA_BLACKHOLE, NULL,
2034 0);
2035 /* Blackhole shouldn't have anymore attributes
2036 */
2037 goto nexthop_done;
565ce0d3
SW
2038 case NEXTHOP_TYPE_IFINDEX:
2039 /* Don't need anymore info for this */
2040 break;
a6e6a6d8
SW
2041 }
2042
2043 if (!nh->ifindex) {
565ce0d3
SW
2044 flog_err(
2045 EC_ZEBRA_NHG_FIB_UPDATE,
2046 "Context received for kernel nexthop update without an interface");
2047 return -1;
565ce0d3
SW
2048 }
2049
8d03bc50
SW
2050 addattr32(&req.n, req_size, NHA_OIF, nh->ifindex);
2051
62d2ecb2
SW
2052 if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK))
2053 req.nhm.nh_flags |= RTNH_F_ONLINK;
2054
8d03bc50
SW
2055 num_labels =
2056 build_label_stack(nh->nh_label, out_lse,
2057 label_buf, sizeof(label_buf));
2058
2059 if (num_labels) {
2060 /* Set the BoS bit */
2061 out_lse[num_labels - 1] |=
2062 htonl(1 << MPLS_LS_S_SHIFT);
2063
2064 /*
2065 * TODO: MPLS unsupported for now in kernel.
2066 */
2067 if (req.nhm.nh_family == AF_MPLS)
2068 goto nexthop_done;
2069#if 0
2070 addattr_l(&req.n, req_size, NHA_NEWDST,
2071 &out_lse,
2072 num_labels
2073 * sizeof(mpls_lse_t));
2074#endif
2075 else {
2076 struct rtattr *nest;
2077 uint16_t encap = LWTUNNEL_ENCAP_MPLS;
2078
2079 addattr_l(&req.n, req_size,
2080 NHA_ENCAP_TYPE, &encap,
2081 sizeof(uint16_t));
2082 nest = addattr_nest(&req.n, req_size,
2083 NHA_ENCAP);
2084 addattr_l(&req.n, req_size,
2085 MPLS_IPTUNNEL_DST, &out_lse,
2086 num_labels
2087 * sizeof(mpls_lse_t));
2088 addattr_nest_end(&req.n, nest);
2089 }
2090 }
2091
bf1626a6
MS
2092nexthop_done:
2093
2094 if (IS_ZEBRA_DEBUG_KERNEL)
2c77ddee
DS
2095 zlog_debug("%s: ID (%u): %pNHv(%d) vrf %s(%u) %s ",
2096 __func__, id, nh, nh->ifindex,
bd47f3a3
JU
2097 vrf_id_to_name(nh->vrf_id),
2098 nh->vrf_id, label_buf);
f820d025
SW
2099 }
2100
38e40db1 2101 req.nhm.nh_protocol = zebra2proto(dplane_ctx_get_nhe_type(ctx));
f820d025 2102
f820d025
SW
2103 } else if (cmd != RTM_DELNEXTHOP) {
2104 flog_err(
2105 EC_ZEBRA_NHG_FIB_UPDATE,
2106 "Nexthop group kernel update command (%d) does not exist",
2107 cmd);
2108 return -1;
2109 }
2110
9266b315
RZ
2111 if (IS_ZEBRA_DEBUG_KERNEL)
2112 zlog_debug("%s: %s, id=%u", __func__, nl_msg_type_to_str(cmd),
2113 id);
f820d025
SW
2114
2115 return netlink_talk_info(netlink_talk_filter, &req.n,
2116 dplane_ctx_get_ns(ctx), 0);
2117}
2118
2119/**
2120 * kernel_nexthop_update() - Update/delete a nexthop from the kernel
2121 *
2122 * @ctx: Dataplane context
2123 *
2124 * Return: Dataplane result flag
2125 */
2126enum zebra_dplane_result kernel_nexthop_update(struct zebra_dplane_ctx *ctx)
2127{
bf1626a6 2128 enum dplane_op_e op;
98cda54a
SW
2129 int cmd = 0;
2130 int ret = 0;
f820d025 2131
bf1626a6
MS
2132 op = dplane_ctx_get_op(ctx);
2133 if (op == DPLANE_OP_NH_INSTALL || op == DPLANE_OP_NH_UPDATE)
f820d025 2134 cmd = RTM_NEWNEXTHOP;
bf1626a6
MS
2135 else if (op == DPLANE_OP_NH_DELETE)
2136 cmd = RTM_DELNEXTHOP;
2137 else {
2138 flog_err(EC_ZEBRA_NHG_FIB_UPDATE,
2139 "Context received for kernel nexthop update with incorrect OP code (%u)",
2140 op);
f820d025 2141 return ZEBRA_DPLANE_REQUEST_FAILURE;
f820d025
SW
2142 }
2143
2144 ret = netlink_nexthop(cmd, ctx);
2145
2146 return (ret == 0 ? ZEBRA_DPLANE_REQUEST_SUCCESS
2147 : ZEBRA_DPLANE_REQUEST_FAILURE);
2148}
2149
7cdb1a84
MS
2150/*
2151 * Update or delete a prefix from the kernel,
2152 * using info from a dataplane context.
2153 */
25779064 2154enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
7cdb1a84
MS
2155{
2156 int cmd, ret;
2157 const struct prefix *p = dplane_ctx_get_dest(ctx);
f183e380 2158 struct nexthop *nexthop;
e57a3fab 2159 uint8_t nl_pkt[NL_PKT_BUF_SIZE];
7cdb1a84
MS
2160
2161 if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_DELETE) {
2162 cmd = RTM_DELROUTE;
2163 } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_INSTALL) {
2164 cmd = RTM_NEWROUTE;
2165 } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) {
2166
2167 if (p->family == AF_INET || v6_rr_semantics) {
2168 /* Single 'replace' operation */
2169 cmd = RTM_NEWROUTE;
fe5f21af
DS
2170
2171 /*
2172 * With route replace semantics in place
2173 * for v4 routes and the new route is a system
2174 * route we do not install anything.
2175 * The problem here is that the new system
2176 * route should cause us to withdraw from
2177 * the kernel the old non-system route
2178 */
2179 if (RSYSTEM_ROUTE(dplane_ctx_get_type(ctx)) &&
e57a3fab
RZ
2180 !RSYSTEM_ROUTE(dplane_ctx_get_old_type(ctx))) {
2181 netlink_route_multipath(RTM_DELROUTE, ctx,
f2a0ba3a
RZ
2182 nl_pkt, sizeof(nl_pkt),
2183 false);
e57a3fab
RZ
2184 netlink_talk_info(netlink_talk_filter,
2185 (struct nlmsghdr *)nl_pkt,
2186 dplane_ctx_get_ns(ctx), 0);
2187 }
7cdb1a84
MS
2188 } else {
2189 /*
2190 * So v6 route replace semantics are not in
2191 * the kernel at this point as I understand it.
2192 * so let's do a delete then an add.
2193 * In the future once v6 route replace semantics
2194 * are in we can figure out what to do here to
2195 * allow working with old and new kernels.
2196 *
2197 * I'm also intentionally ignoring the failure case
2198 * of the route delete. If that happens yeah we're
2199 * screwed.
2200 */
e57a3fab
RZ
2201 if (!RSYSTEM_ROUTE(dplane_ctx_get_old_type(ctx))) {
2202 netlink_route_multipath(RTM_DELROUTE, ctx,
f2a0ba3a
RZ
2203 nl_pkt, sizeof(nl_pkt),
2204 false);
e57a3fab
RZ
2205 netlink_talk_info(netlink_talk_filter,
2206 (struct nlmsghdr *)nl_pkt,
2207 dplane_ctx_get_ns(ctx), 0);
2208 }
7cdb1a84
MS
2209 cmd = RTM_NEWROUTE;
2210 }
2211
2212 } else {
2213 return ZEBRA_DPLANE_REQUEST_FAILURE;
2214 }
2215
e57a3fab 2216 if (!RSYSTEM_ROUTE(dplane_ctx_get_type(ctx))) {
f2a0ba3a
RZ
2217 netlink_route_multipath(cmd, ctx, nl_pkt, sizeof(nl_pkt),
2218 false);
e57a3fab
RZ
2219 ret = netlink_talk_info(netlink_talk_filter,
2220 (struct nlmsghdr *)nl_pkt,
2221 dplane_ctx_get_ns(ctx), 0);
2222 } else
3cdba47a 2223 ret = 0;
f183e380
MS
2224 if ((cmd == RTM_NEWROUTE) && (ret == 0)) {
2225 /* Update installed nexthops to signal which have been
2226 * installed.
2227 */
2228 for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
2229 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
2230 continue;
2231
2232 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) {
2233 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
f183e380
MS
2234 }
2235 }
2236 }
7cdb1a84
MS
2237
2238 return (ret == 0 ?
2239 ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
2240}
2241
d9f5b2f5
SW
2242/**
2243 * netlink_nexthop_process_nh() - Parse the gatway/if info from a new nexthop
2244 *
2245 * @tb: Netlink RTA data
2246 * @family: Address family in the nhmsg
8c0a24c1 2247 * @ifp: Interface connected - this should be NULL, we fill it in
d9f5b2f5
SW
2248 * @ns_id: Namspace id
2249 *
2250 * Return: New nexthop
2251 */
e22e8001
SW
2252static struct nexthop netlink_nexthop_process_nh(struct rtattr **tb,
2253 unsigned char family,
2254 struct interface **ifp,
2255 ns_id_t ns_id)
d9f5b2f5 2256{
e22e8001 2257 struct nexthop nh = {};
d9f5b2f5 2258 void *gate = NULL;
8e401b25 2259 enum nexthop_types_t type = 0;
e22e8001
SW
2260 int if_index = 0;
2261 size_t sz = 0;
7134ba70 2262 struct interface *ifp_lookup;
d9f5b2f5
SW
2263
2264 if_index = *(int *)RTA_DATA(tb[NHA_OIF]);
2265
8e401b25 2266
d9f5b2f5
SW
2267 if (tb[NHA_GATEWAY]) {
2268 switch (family) {
2269 case AF_INET:
8e401b25 2270 type = NEXTHOP_TYPE_IPV4_IFINDEX;
d9f5b2f5
SW
2271 sz = 4;
2272 break;
2273 case AF_INET6:
8e401b25 2274 type = NEXTHOP_TYPE_IPV6_IFINDEX;
d9f5b2f5
SW
2275 sz = 16;
2276 break;
2277 default:
2278 flog_warn(
2279 EC_ZEBRA_BAD_NHG_MESSAGE,
c4239c05 2280 "Nexthop gateway with bad address family (%d) received from kernel",
d9f5b2f5 2281 family);
e22e8001 2282 return nh;
d9f5b2f5
SW
2283 }
2284 gate = RTA_DATA(tb[NHA_GATEWAY]);
e22e8001 2285 } else
8e401b25 2286 type = NEXTHOP_TYPE_IFINDEX;
d9f5b2f5 2287
8e401b25 2288 if (type)
e22e8001 2289 nh.type = type;
8e401b25
SW
2290
2291 if (gate)
e22e8001 2292 memcpy(&(nh.gate), gate, sz);
8e401b25
SW
2293
2294 if (if_index)
e22e8001 2295 nh.ifindex = if_index;
8e401b25 2296
7134ba70
DS
2297 ifp_lookup =
2298 if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), nh.ifindex);
2299
e22e8001 2300 if (ifp)
7134ba70
DS
2301 *ifp = ifp_lookup;
2302 if (ifp_lookup)
2303 nh.vrf_id = ifp_lookup->vrf_id;
e22e8001 2304 else {
d9f5b2f5
SW
2305 flog_warn(
2306 EC_ZEBRA_UNKNOWN_INTERFACE,
2307 "%s: Unknown nexthop interface %u received, defaulting to VRF_DEFAULT",
15569c58 2308 __func__, nh.ifindex);
d9f5b2f5 2309
e22e8001 2310 nh.vrf_id = VRF_DEFAULT;
d9f5b2f5
SW
2311 }
2312
2313 if (tb[NHA_ENCAP] && tb[NHA_ENCAP_TYPE]) {
2314 uint16_t encap_type = *(uint16_t *)RTA_DATA(tb[NHA_ENCAP_TYPE]);
2315 int num_labels = 0;
6e728764 2316
d9f5b2f5
SW
2317 mpls_label_t labels[MPLS_MAX_LABELS] = {0};
2318
e22e8001 2319 if (encap_type == LWTUNNEL_ENCAP_MPLS)
d9f5b2f5 2320 num_labels = parse_encap_mpls(tb[NHA_ENCAP], labels);
d9f5b2f5 2321
e22e8001
SW
2322 if (num_labels)
2323 nexthop_add_labels(&nh, ZEBRA_LSP_STATIC, num_labels,
d9f5b2f5 2324 labels);
d9f5b2f5
SW
2325 }
2326
2327 return nh;
2328}
2329
85f5e761 2330static int netlink_nexthop_process_group(struct rtattr **tb,
5a935f79 2331 struct nh_grp *z_grp, int z_grp_size)
d9f5b2f5 2332{
e22e8001
SW
2333 uint8_t count = 0;
2334 /* linux/nexthop.h group struct */
d9f5b2f5
SW
2335 struct nexthop_grp *n_grp = NULL;
2336
85f5e761 2337 n_grp = (struct nexthop_grp *)RTA_DATA(tb[NHA_GROUP]);
d9f5b2f5
SW
2338 count = (RTA_PAYLOAD(tb[NHA_GROUP]) / sizeof(*n_grp));
2339
2340 if (!count || (count * sizeof(*n_grp)) != RTA_PAYLOAD(tb[NHA_GROUP])) {
2341 flog_warn(EC_ZEBRA_BAD_NHG_MESSAGE,
2342 "Invalid nexthop group received from the kernel");
85f5e761 2343 return count;
d9f5b2f5
SW
2344 }
2345
38e40db1 2346#if 0
d9f5b2f5 2347 // TODO: Need type for something?
85f5e761
SW
2348 zlog_debug("Nexthop group type: %d",
2349 *((uint16_t *)RTA_DATA(tb[NHA_GROUP_TYPE])));
d9f5b2f5 2350
38e40db1 2351#endif
d9f5b2f5 2352
5a935f79 2353 for (int i = 0; ((i < count) && (i < z_grp_size)); i++) {
e22e8001 2354 z_grp[i].id = n_grp[i].id;
df7fb580 2355 z_grp[i].weight = n_grp[i].weight + 1;
85f5e761 2356 }
d9f5b2f5
SW
2357 return count;
2358}
2359
2360/**
2361 * netlink_nexthop_change() - Read in change about nexthops from the kernel
2362 *
2363 * @h: Netlink message header
2364 * @ns_id: Namspace id
2365 * @startup: Are we reading under startup conditions?
2366 *
2367 * Return: Result status
2368 */
2369int netlink_nexthop_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
2370{
2371 int len;
2372 /* nexthop group id */
2373 uint32_t id;
2374 unsigned char family;
38e40db1 2375 int type;
e8b0e420 2376 afi_t afi = AFI_UNSPEC;
946de1b9 2377 vrf_id_t vrf_id = VRF_DEFAULT;
8c0a24c1 2378 struct interface *ifp = NULL;
d9f5b2f5 2379 struct nhmsg *nhm = NULL;
e22e8001
SW
2380 struct nexthop nh = {};
2381 struct nh_grp grp[MULTIPATH_NUM] = {};
85f5e761 2382 /* Count of nexthops in group array */
e22e8001 2383 uint8_t grp_count = 0;
e22e8001 2384 struct rtattr *tb[NHA_MAX + 1] = {};
d9f5b2f5 2385
d9f5b2f5
SW
2386 nhm = NLMSG_DATA(h);
2387
88cafda7
DS
2388 if (ns_id)
2389 vrf_id = ns_id;
2390
d9f5b2f5
SW
2391 if (startup && h->nlmsg_type != RTM_NEWNEXTHOP)
2392 return 0;
2393
2394 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct nhmsg));
2395 if (len < 0) {
2396 zlog_warn(
2397 "%s: Message received from netlink is of a broken size %d %zu",
15569c58 2398 __func__, h->nlmsg_len,
d9f5b2f5
SW
2399 (size_t)NLMSG_LENGTH(sizeof(struct nhmsg)));
2400 return -1;
2401 }
2402
d9f5b2f5
SW
2403 netlink_parse_rtattr(tb, NHA_MAX, RTM_NHA(nhm), len);
2404
2405
2406 if (!tb[NHA_ID]) {
2407 flog_warn(
2408 EC_ZEBRA_BAD_NHG_MESSAGE,
2409 "Nexthop group without an ID received from the kernel");
2410 return -1;
2411 }
2412
2413 /* We use the ID key'd nhg table for kernel updates */
2414 id = *((uint32_t *)RTA_DATA(tb[NHA_ID]));
d9f5b2f5 2415
e8b0e420 2416 family = nhm->nh_family;
e8b0e420
SW
2417 afi = family2afi(family);
2418
38e40db1
SW
2419 type = proto2zebra(nhm->nh_protocol, 0, true);
2420
fdee485a
SW
2421 if (IS_ZEBRA_DEBUG_KERNEL)
2422 zlog_debug("%s ID (%u) %s NS %u",
2423 nl_msg_type_to_str(h->nlmsg_type), id,
2424 nl_family_to_str(family), ns_id);
2425
2426
d9f5b2f5
SW
2427 if (h->nlmsg_type == RTM_NEWNEXTHOP) {
2428 if (tb[NHA_GROUP]) {
2429 /**
2430 * If this is a group message its only going to have
2431 * an array of nexthop IDs associated with it
2432 */
5a935f79
SW
2433 grp_count = netlink_nexthop_process_group(
2434 tb, grp, array_size(grp));
85f5e761
SW
2435 } else {
2436 if (tb[NHA_BLACKHOLE]) {
2437 /**
2438 * This nexthop is just for blackhole-ing
2439 * traffic, it should not have an OIF, GATEWAY,
2440 * or ENCAP
2441 */
e22e8001
SW
2442 nh.type = NEXTHOP_TYPE_BLACKHOLE;
2443 nh.bh_type = BLACKHOLE_UNSPEC;
2444 } else if (tb[NHA_OIF])
85f5e761
SW
2445 /**
2446 * This is a true new nexthop, so we need
2447 * to parse the gateway and device info
2448 */
2449 nh = netlink_nexthop_process_nh(tb, family,
2450 &ifp, ns_id);
e22e8001
SW
2451 else {
2452
8e401b25
SW
2453 flog_warn(
2454 EC_ZEBRA_BAD_NHG_MESSAGE,
2455 "Invalid Nexthop message received from the kernel with ID (%u)",
2456 id);
2457 return -1;
2458 }
e22e8001
SW
2459 SET_FLAG(nh.flags, NEXTHOP_FLAG_ACTIVE);
2460 if (nhm->nh_flags & RTNH_F_ONLINK)
2461 SET_FLAG(nh.flags, NEXTHOP_FLAG_ONLINK);
2462 vrf_id = nh.vrf_id;
d9f5b2f5
SW
2463 }
2464
38e40db1
SW
2465 if (zebra_nhg_kernel_find(id, &nh, grp, grp_count, vrf_id, afi,
2466 type, startup))
e22e8001 2467 return -1;
8e401b25 2468
9a1588c4 2469 } else if (h->nlmsg_type == RTM_DELNEXTHOP)
88cafda7 2470 zebra_nhg_kernel_del(id, vrf_id);
d9f5b2f5 2471
d9f5b2f5
SW
2472 return 0;
2473}
2474
2475/**
2476 * netlink_request_nexthop() - Request nextop information from the kernel
2477 * @zns: Zebra namespace
2478 * @family: AF_* netlink family
2479 * @type: RTM_* route type
2480 *
2481 * Return: Result status
2482 */
2483static int netlink_request_nexthop(struct zebra_ns *zns, int family, int type)
2484{
2485 struct {
2486 struct nlmsghdr n;
2487 struct nhmsg nhm;
2488 } req;
2489
2490 /* Form the request, specifying filter (rtattr) if needed. */
2491 memset(&req, 0, sizeof(req));
2492 req.n.nlmsg_type = type;
2493 req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
2494 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg));
2495 req.nhm.nh_family = family;
2496
fd3f8e52 2497 return netlink_request(&zns->netlink_cmd, &req);
d9f5b2f5
SW
2498}
2499
7d5bb02b 2500
d9f5b2f5
SW
2501/**
2502 * netlink_nexthop_read() - Nexthop read function using netlink interface
2503 *
2504 * @zns: Zebra name space
2505 *
2506 * Return: Result status
2507 * Only called at bootstrap time.
2508 */
2509int netlink_nexthop_read(struct zebra_ns *zns)
2510{
2511 int ret;
2512 struct zebra_dplane_info dp_info;
2513
2514 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
2515
2516 /* Get nexthop objects */
2517 ret = netlink_request_nexthop(zns, AF_UNSPEC, RTM_GETNEXTHOP);
2518 if (ret < 0)
2519 return ret;
2520 ret = netlink_parse_info(netlink_nexthop_change, &zns->netlink_cmd,
2521 &dp_info, 0, 1);
81505946
SW
2522
2523 if (!ret)
2524 /* If we succesfully read in nexthop objects,
2525 * this kernel must support them.
2526 */
2527 supports_nh = true;
7c99d51b
MS
2528
2529 if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_NHG)
2530 zlog_debug("Nexthop objects %ssupported on this kernel",
2531 supports_nh ? "" : "not ");
81505946 2532
60e0eaee 2533 return ret;
d9f5b2f5
SW
2534}
2535
2536
d62a17ae 2537int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
5895d33f 2538 int llalen, ns_id_t ns_id)
6b8a5694 2539{
d62a17ae 2540 return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex,
5895d33f 2541 addr, lla, llalen, ns_id);
6b8a5694 2542}
718e3744 2543
340845e2
JU
2544/**
2545 * netlink_update_neigh_ctx_internal() - Common helper api for evpn
2546 * neighbor updates using dataplane context object.
2547 * @ctx: Dataplane context
2548 * @cmd: Netlink command (RTM_NEWNEIGH or RTM_DELNEIGH)
2549 * @mac: A neighbor cache link layer address
2550 * @ip: A neighbor cache n/w layer destination address
2551 * @replace_obj: Whether NEW request should replace existing object or
2552 * add to the end of the list
2553 * @family: AF_* netlink family
2554 * @type: RTN_* route type
2555 * @flags: NTF_* flags
2556 * @state: NUD_* states
d4d4ec1c
RZ
2557 * @data: data buffer pointer
2558 * @datalen: total amount of data buffer space
340845e2
JU
2559 *
2560 * Return: Result status
13d60d35 2561 */
d4d4ec1c
RZ
2562static ssize_t
2563netlink_update_neigh_ctx_internal(const struct zebra_dplane_ctx *ctx,
2564 int cmd, const struct ethaddr *mac,
2565 const struct ipaddr *ip, bool replace_obj,
2566 uint8_t family, uint8_t type, uint8_t flags,
2567 uint16_t state, void *data, size_t datalen)
13d60d35 2568{
f3dbec60 2569 uint8_t protocol = RTPROT_ZEBRA;
d62a17ae 2570 struct {
2571 struct nlmsghdr n;
2572 struct ndmsg ndm;
d4d4ec1c
RZ
2573 char buf[];
2574 } *req = data;
340845e2
JU
2575 int ipa_len;
2576 enum dplane_op_e op;
d62a17ae 2577
d4d4ec1c 2578 memset(req, 0, datalen);
d62a17ae 2579
340845e2
JU
2580 op = dplane_ctx_get_op(ctx);
2581
d4d4ec1c
RZ
2582 req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
2583 req->n.nlmsg_flags = NLM_F_REQUEST;
d62a17ae 2584 if (cmd == RTM_NEWNEIGH)
d4d4ec1c 2585 req->n.nlmsg_flags |=
340845e2
JU
2586 NLM_F_CREATE
2587 | (replace_obj ? NLM_F_REPLACE : NLM_F_APPEND);
d4d4ec1c
RZ
2588 req->n.nlmsg_type = cmd;
2589 req->ndm.ndm_family = family;
2590 req->ndm.ndm_type = type;
2591 req->ndm.ndm_state = state;
2592 req->ndm.ndm_flags = flags;
2593 req->ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
d62a17ae 2594
d4d4ec1c 2595 addattr_l(&req->n, sizeof(req),
f3dbec60 2596 NDA_PROTOCOL, &protocol, sizeof(protocol));
340845e2 2597 if (mac)
d4d4ec1c 2598 addattr_l(&req->n, datalen, NDA_LLADDR, mac, 6);
13d60d35 2599
340845e2 2600 ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
d4d4ec1c 2601 addattr_l(&req->n, datalen, NDA_DST, &ip->ip.addr, ipa_len);
340845e2
JU
2602
2603 if (op == DPLANE_OP_MAC_INSTALL || op == DPLANE_OP_MAC_DELETE) {
2604 vlanid_t vid = dplane_ctx_mac_get_vlan(ctx);
13d60d35 2605
340845e2 2606 if (vid > 0)
d4d4ec1c 2607 addattr16(&req->n, datalen, NDA_VLAN, vid);
13d60d35 2608
d4d4ec1c 2609 addattr32(&req->n, datalen, NDA_MASTER,
340845e2
JU
2610 dplane_ctx_mac_get_br_ifindex(ctx));
2611 }
13d60d35 2612
d4d4ec1c 2613 return NLMSG_ALIGN(req->n.nlmsg_len);
13d60d35 2614}
2615
340845e2
JU
2616/*
2617 * Add remote VTEP to the flood list for this VxLAN interface (VNI). This
2618 * is done by adding an FDB entry with a MAC of 00:00:00:00:00:00.
2619 */
2620static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx,
2621 int cmd)
2622{
2623 struct ethaddr dst_mac = {.octet = {0}};
d4d4ec1c 2624 uint8_t nl_pkt[NL_PKT_BUF_SIZE];
340845e2 2625
d4d4ec1c 2626 netlink_update_neigh_ctx_internal(
340845e2 2627 ctx, cmd, &dst_mac, dplane_ctx_neigh_get_ipaddr(ctx), false,
d4d4ec1c
RZ
2628 PF_BRIDGE, 0, NTF_SELF, (NUD_NOARP | NUD_PERMANENT), nl_pkt,
2629 sizeof(nl_pkt));
2630
2631 return netlink_talk_info(netlink_talk_filter,
2632 (struct nlmsghdr *)nl_pkt,
2633 dplane_ctx_get_ns(ctx), 0);
340845e2
JU
2634}
2635
2232a77c 2636#ifndef NDA_RTA
d62a17ae 2637#define NDA_RTA(r) \
2638 ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
2232a77c 2639#endif
2640
2414abd3 2641static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
2232a77c 2642{
d62a17ae 2643 struct ndmsg *ndm;
2644 struct interface *ifp;
2645 struct zebra_if *zif;
d62a17ae 2646 struct rtattr *tb[NDA_MAX + 1];
2647 struct interface *br_if;
2648 struct ethaddr mac;
2649 vlanid_t vid = 0;
4b3f26f4 2650 struct in_addr vtep_ip;
d62a17ae 2651 int vid_present = 0, dst_present = 0;
2652 char buf[ETHER_ADDR_STRLEN];
2653 char vid_buf[20];
2654 char dst_buf[30];
a37f4598 2655 bool sticky;
d62a17ae 2656
2657 ndm = NLMSG_DATA(h);
2658
2853fed6 2659 /* We only process macfdb notifications if EVPN is enabled */
2660 if (!is_evpn_enabled())
2661 return 0;
2662
4b3f26f4 2663 /* Parse attributes and extract fields of interest. Do basic
2664 * validation of the fields.
2665 */
2666 memset(tb, 0, sizeof tb);
d62a17ae 2667 netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
2668
2669 if (!tb[NDA_LLADDR]) {
28bd0652 2670 if (IS_ZEBRA_DEBUG_KERNEL)
4b3f26f4 2671 zlog_debug("%s AF_BRIDGE IF %u - no LLADDR",
28bd0652 2672 nl_msg_type_to_str(h->nlmsg_type),
4b3f26f4 2673 ndm->ndm_ifindex);
d62a17ae 2674 return 0;
2675 }
2676
ff8b7eb8 2677 if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
28bd0652
DS
2678 if (IS_ZEBRA_DEBUG_KERNEL)
2679 zlog_debug(
4b3f26f4 2680 "%s AF_BRIDGE IF %u - LLADDR is not MAC, len %lu",
2681 nl_msg_type_to_str(h->nlmsg_type), ndm->ndm_ifindex,
28bd0652 2682 (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR]));
d62a17ae 2683 return 0;
2684 }
2685
ff8b7eb8 2686 memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETH_ALEN);
d62a17ae 2687
2688 if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN]) {
2689 vid_present = 1;
d7c0a89a 2690 vid = *(uint16_t *)RTA_DATA(tb[NDA_VLAN]);
772270f3 2691 snprintf(vid_buf, sizeof(vid_buf), " VLAN %u", vid);
d62a17ae 2692 }
2693
2694 if (tb[NDA_DST]) {
2695 /* TODO: Only IPv4 supported now. */
2696 dst_present = 1;
4b3f26f4 2697 memcpy(&vtep_ip.s_addr, RTA_DATA(tb[NDA_DST]),
d62a17ae 2698 IPV4_MAX_BYTELEN);
772270f3
QY
2699 snprintf(dst_buf, sizeof(dst_buf), " dst %s",
2700 inet_ntoa(vtep_ip));
d62a17ae 2701 }
2702
d62a17ae 2703 if (IS_ZEBRA_DEBUG_KERNEL)
4b3f26f4 2704 zlog_debug("Rx %s AF_BRIDGE IF %u%s st 0x%x fl 0x%x MAC %s%s",
d62a17ae 2705 nl_msg_type_to_str(h->nlmsg_type),
d62a17ae 2706 ndm->ndm_ifindex, vid_present ? vid_buf : "",
4b3f26f4 2707 ndm->ndm_state, ndm->ndm_flags,
d62a17ae 2708 prefix_mac2str(&mac, buf, sizeof(buf)),
2709 dst_present ? dst_buf : "");
2710
4b3f26f4 2711 /* The interface should exist. */
2712 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
2713 ndm->ndm_ifindex);
2714 if (!ifp || !ifp->info)
2715 return 0;
2716
2717 /* The interface should be something we're interested in. */
2718 if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
2719 return 0;
2720
2721 zif = (struct zebra_if *)ifp->info;
2722 if ((br_if = zif->brslave_info.br_if) == NULL) {
2723 if (IS_ZEBRA_DEBUG_KERNEL)
2724 zlog_debug(
2725 "%s AF_BRIDGE IF %s(%u) brIF %u - no bridge master",
2726 nl_msg_type_to_str(h->nlmsg_type), ifp->name,
2727 ndm->ndm_ifindex,
2728 zif->brslave_info.bridge_ifindex);
2729 return 0;
2730 }
2731
2732 sticky = !!(ndm->ndm_state & NUD_NOARP);
2733
28bd0652
DS
2734 if (filter_vlan && vid != filter_vlan) {
2735 if (IS_ZEBRA_DEBUG_KERNEL)
d6951e5e 2736 zlog_debug(" Filtered due to filter vlan: %d",
28bd0652 2737 filter_vlan);
d62a17ae 2738 return 0;
28bd0652 2739 }
d62a17ae 2740
2741 /* If add or update, do accordingly if learnt on a "local" interface; if
2742 * the notification is over VxLAN, this has to be related to
2743 * multi-homing,
2744 * so perform an implicit delete of any local entry (if it exists).
2745 */
2746 if (h->nlmsg_type == RTM_NEWNEIGH) {
4b3f26f4 2747 /* Drop "permanent" entries. */
2748 if (ndm->ndm_state & NUD_PERMANENT) {
2749 if (IS_ZEBRA_DEBUG_KERNEL)
d6951e5e
DL
2750 zlog_debug(
2751 " Dropping entry because of NUD_PERMANENT");
2752 return 0;
4b3f26f4 2753 }
2754
d62a17ae 2755 if (IS_ZEBRA_IF_VXLAN(ifp))
2756 return zebra_vxlan_check_del_local_mac(ifp, br_if, &mac,
2757 vid);
2758
2759 return zebra_vxlan_local_mac_add_update(ifp, br_if, &mac, vid,
2760 sticky);
2761 }
2762
2763 /* This is a delete notification.
4b3f26f4 2764 * Ignore the notification with IP dest as it may just signify that the
2765 * MAC has moved from remote to local. The exception is the special
2766 * all-zeros MAC that represents the BUM flooding entry; we may have
2767 * to readd it. Otherwise,
d62a17ae 2768 * 1. For a MAC over VxLan, check if it needs to be refreshed(readded)
2769 * 2. For a MAC over "local" interface, delete the mac
2770 * Note: We will get notifications from both bridge driver and VxLAN
2771 * driver.
d62a17ae 2772 */
28bd0652 2773 if (dst_present) {
4b3f26f4 2774 u_char zero_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
2775
2776 if (!memcmp(zero_mac, mac.octet, ETH_ALEN))
2777 return zebra_vxlan_check_readd_vtep(ifp, vtep_ip);
d62a17ae 2778 return 0;
28bd0652 2779 }
d62a17ae 2780
2781 if (IS_ZEBRA_IF_VXLAN(ifp))
2782 return zebra_vxlan_check_readd_remote_mac(ifp, br_if, &mac,
2783 vid);
2784
2785 return zebra_vxlan_local_mac_del(ifp, br_if, &mac, vid);
2232a77c 2786}
2787
2414abd3 2788static int netlink_macfdb_table(struct nlmsghdr *h, ns_id_t ns_id, int startup)
2232a77c 2789{
d62a17ae 2790 int len;
2791 struct ndmsg *ndm;
2232a77c 2792
d62a17ae 2793 if (h->nlmsg_type != RTM_NEWNEIGH)
2794 return 0;
2232a77c 2795
d62a17ae 2796 /* Length validity. */
2797 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
2798 if (len < 0)
2799 return -1;
2232a77c 2800
d62a17ae 2801 /* We are interested only in AF_BRIDGE notifications. */
2802 ndm = NLMSG_DATA(h);
2803 if (ndm->ndm_family != AF_BRIDGE)
2804 return 0;
2232a77c 2805
2414abd3 2806 return netlink_macfdb_change(h, len, ns_id);
2232a77c 2807}
2808
2809/* Request for MAC FDB information from the kernel */
85a75f1e
MS
2810static int netlink_request_macs(struct nlsock *netlink_cmd, int family,
2811 int type, ifindex_t master_ifindex)
2232a77c 2812{
d62a17ae 2813 struct {
2814 struct nlmsghdr n;
2815 struct ifinfomsg ifm;
2816 char buf[256];
2817 } req;
2818
2819 /* Form the request, specifying filter (rtattr) if needed. */
2820 memset(&req, 0, sizeof(req));
2821 req.n.nlmsg_type = type;
718f9b0f 2822 req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
d62a17ae 2823 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
2824 req.ifm.ifi_family = family;
2825 if (master_ifindex)
2826 addattr32(&req.n, sizeof(req), IFLA_MASTER, master_ifindex);
2827
fd3f8e52 2828 return netlink_request(netlink_cmd, &req);
2232a77c 2829}
2830
2831/*
2832 * MAC forwarding database read using netlink interface. This is invoked
2833 * at startup.
2834 */
d62a17ae 2835int netlink_macfdb_read(struct zebra_ns *zns)
2232a77c 2836{
d62a17ae 2837 int ret;
85a75f1e
MS
2838 struct zebra_dplane_info dp_info;
2839
2840 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
d62a17ae 2841
2842 /* Get bridge FDB table. */
85a75f1e
MS
2843 ret = netlink_request_macs(&zns->netlink_cmd, AF_BRIDGE, RTM_GETNEIGH,
2844 0);
d62a17ae 2845 if (ret < 0)
2846 return ret;
2847 /* We are reading entire table. */
2848 filter_vlan = 0;
85a75f1e
MS
2849 ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd,
2850 &dp_info, 0, 1);
d62a17ae 2851
2852 return ret;
2232a77c 2853}
2854
2855/*
2856 * MAC forwarding database read using netlink interface. This is for a
2857 * specific bridge and matching specific access VLAN (if VLAN-aware bridge).
2858 */
d62a17ae 2859int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
2860 struct interface *br_if)
2232a77c 2861{
d62a17ae 2862 struct zebra_if *br_zif;
2863 struct zebra_if *zif;
2864 struct zebra_l2info_vxlan *vxl;
85a75f1e 2865 struct zebra_dplane_info dp_info;
d62a17ae 2866 int ret = 0;
2867
85a75f1e 2868 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
d62a17ae 2869
2870 /* Save VLAN we're filtering on, if needed. */
2871 br_zif = (struct zebra_if *)br_if->info;
2872 zif = (struct zebra_if *)ifp->info;
2873 vxl = &zif->l2info.vxl;
2874 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
2875 filter_vlan = vxl->access_vlan;
2876
2877 /* Get bridge FDB table for specific bridge - we do the VLAN filtering.
2878 */
85a75f1e 2879 ret = netlink_request_macs(&zns->netlink_cmd, AF_BRIDGE, RTM_GETNEIGH,
d62a17ae 2880 br_if->ifindex);
2881 if (ret < 0)
2882 return ret;
85a75f1e
MS
2883 ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd,
2884 &dp_info, 0, 0);
d62a17ae 2885
2886 /* Reset VLAN filter. */
2887 filter_vlan = 0;
2888 return ret;
2232a77c 2889}
2890
67fb9374
CS
2891
2892/* Request for MAC FDB for a specific MAC address in VLAN from the kernel */
2893static int netlink_request_specific_mac_in_bridge(struct zebra_ns *zns,
2894 int family,
2895 int type,
2896 struct interface *br_if,
2897 struct ethaddr *mac,
2898 vlanid_t vid)
2899{
2900 struct {
2901 struct nlmsghdr n;
2902 struct ndmsg ndm;
2903 char buf[256];
2904 } req;
2905 struct zebra_if *br_zif;
2906 char buf[ETHER_ADDR_STRLEN];
2907
2908 memset(&req, 0, sizeof(req));
2909 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
2910 req.n.nlmsg_type = type; /* RTM_GETNEIGH */
2911 req.n.nlmsg_flags = NLM_F_REQUEST;
2912 req.ndm.ndm_family = family; /* AF_BRIDGE */
2913 /* req.ndm.ndm_state = NUD_REACHABLE; */
2914
2915 addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
2916
2917 br_zif = (struct zebra_if *)br_if->info;
2918 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0)
2919 addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
2920
2921 addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
2922
2923 if (IS_ZEBRA_DEBUG_KERNEL)
bd47f3a3
JU
2924 zlog_debug(
2925 "%s: Tx family %s IF %s(%u) vrf %s(%u) MAC %s vid %u",
2926 __func__, nl_family_to_str(req.ndm.ndm_family),
2927 br_if->name, br_if->ifindex,
2928 vrf_id_to_name(br_if->vrf_id), br_if->vrf_id,
2929 prefix_mac2str(mac, buf, sizeof(buf)), vid);
67fb9374 2930
fd3f8e52 2931 return netlink_request(&zns->netlink_cmd, &req);
67fb9374
CS
2932}
2933
2934int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
2935 struct interface *br_if,
2936 struct ethaddr *mac, vlanid_t vid)
2937{
2938 int ret = 0;
2939 struct zebra_dplane_info dp_info;
2940
2941 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
2942
2943 /* Get bridge FDB table for specific bridge - we do the VLAN filtering.
2944 */
2945 ret = netlink_request_specific_mac_in_bridge(zns, AF_BRIDGE,
2946 RTM_GETNEIGH,
2947 br_if, mac, vid);
2948 if (ret < 0)
2949 return ret;
2950
2951 ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd,
2952 &dp_info, 1, 0);
2953
2954 return ret;
2955}
036d93c0
MS
2956
2957/*
2958 * Netlink-specific handler for MAC updates using dataplane context object.
2959 */
d4d4ec1c
RZ
2960ssize_t
2961netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, uint8_t *data,
2962 size_t datalen)
2232a77c 2963{
340845e2 2964 struct ipaddr vtep_ip;
036d93c0 2965 vlanid_t vid;
d4d4ec1c
RZ
2966 ssize_t total;
2967 int cmd;
340845e2
JU
2968 uint8_t flags;
2969 uint16_t state;
d4d4ec1c
RZ
2970 uint8_t nl_pkt[NL_PKT_BUF_SIZE];
2971
2972 cmd = dplane_ctx_get_op(ctx) == DPLANE_OP_MAC_INSTALL
2973 ? RTM_NEWNEIGH : RTM_DELNEIGH;
036d93c0 2974
340845e2
JU
2975 flags = (NTF_SELF | NTF_MASTER);
2976 state = NUD_REACHABLE;
d62a17ae 2977
036d93c0 2978 if (dplane_ctx_mac_is_sticky(ctx))
340845e2 2979 state |= NUD_NOARP;
d62a17ae 2980 else
340845e2 2981 flags |= NTF_EXT_LEARNED;
478566d6 2982
340845e2
JU
2983 vtep_ip.ipaddr_v4 = *(dplane_ctx_mac_get_vtep_ip(ctx));
2984 SET_IPADDR_V4(&vtep_ip);
d62a17ae 2985
036d93c0
MS
2986 if (IS_ZEBRA_DEBUG_KERNEL) {
2987 char ipbuf[PREFIX_STRLEN];
2988 char buf[ETHER_ADDR_STRLEN];
478566d6
MS
2989 char vid_buf[20];
2990
340845e2
JU
2991 vid = dplane_ctx_mac_get_vlan(ctx);
2992 if (vid > 0)
478566d6
MS
2993 snprintf(vid_buf, sizeof(vid_buf), " VLAN %u", vid);
2994 else
2995 vid_buf[0] = '\0';
036d93c0 2996
340845e2 2997 const struct ethaddr *mac = dplane_ctx_mac_get_addr(ctx);
036d93c0 2998
340845e2
JU
2999 zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s dst %s",
3000 nl_msg_type_to_str(cmd), nl_family_to_str(AF_BRIDGE),
478566d6
MS
3001 dplane_ctx_get_ifname(ctx),
3002 dplane_ctx_get_ifindex(ctx), vid_buf,
036d93c0 3003 dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "",
340845e2
JU
3004 prefix_mac2str(mac, buf, sizeof(buf)),
3005 ipaddr2str(&vtep_ip, ipbuf, sizeof(ipbuf)));
036d93c0 3006 }
d62a17ae 3007
d4d4ec1c
RZ
3008 total = netlink_update_neigh_ctx_internal(
3009 ctx, cmd, dplane_ctx_mac_get_addr(ctx),
3010 dplane_ctx_neigh_get_ipaddr(ctx), true, AF_BRIDGE, 0,
3011 flags, state, nl_pkt, sizeof(nl_pkt));
3012
3013 return total;
2232a77c 3014}
3015
f17b99ed
DS
3016/*
3017 * In the event the kernel deletes ipv4 link-local neighbor entries created for
3018 * 5549 support, re-install them.
3019 */
3020static void netlink_handle_5549(struct ndmsg *ndm, struct zebra_if *zif,
9b036974
DS
3021 struct interface *ifp, struct ipaddr *ip,
3022 bool handle_failed)
f17b99ed
DS
3023{
3024 if (ndm->ndm_family != AF_INET)
3025 return;
3026
3027 if (!zif->v6_2_v4_ll_neigh_entry)
3028 return;
3029
3030 if (ipv4_ll.s_addr != ip->ip._v4_addr.s_addr)
3031 return;
3032
9b036974
DS
3033 if (handle_failed && ndm->ndm_state & NUD_FAILED) {
3034 zlog_info("Neighbor Entry for %s has entered a failed state, not reinstalling",
3035 ifp->name);
3036 return;
3037 }
3038
f17b99ed
DS
3039 if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, &zif->v6_2_v4_ll_addr6, true);
3040}
3041
d62a17ae 3042#define NUD_VALID \
3043 (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE \
3044 | NUD_DELAY)
2232a77c 3045
2414abd3 3046static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
2232a77c 3047{
d62a17ae 3048 struct ndmsg *ndm;
3049 struct interface *ifp;
3050 struct zebra_if *zif;
d62a17ae 3051 struct rtattr *tb[NDA_MAX + 1];
3052 struct interface *link_if;
3053 struct ethaddr mac;
3054 struct ipaddr ip;
bd47f3a3 3055 struct vrf *vrf;
d62a17ae 3056 char buf[ETHER_ADDR_STRLEN];
3057 char buf2[INET6_ADDRSTRLEN];
3058 int mac_present = 0;
a37f4598 3059 bool is_ext;
3060 bool is_router;
d62a17ae 3061
3062 ndm = NLMSG_DATA(h);
3063
3064 /* The interface should exist. */
5895d33f 3065 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
d62a17ae 3066 ndm->ndm_ifindex);
2853fed6 3067 if (!ifp || !ifp->info)
d62a17ae 3068 return 0;
3069
bd47f3a3 3070 vrf = vrf_lookup_by_id(ifp->vrf_id);
20089ae2
DS
3071 zif = (struct zebra_if *)ifp->info;
3072
3073 /* Parse attributes and extract fields of interest. */
0d6f7fd6 3074 memset(tb, 0, sizeof(tb));
20089ae2
DS
3075 netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
3076
3077 if (!tb[NDA_DST]) {
bd47f3a3 3078 zlog_debug("%s family %s IF %s(%u) vrf %s(%u) - no DST",
9df414fe
QY
3079 nl_msg_type_to_str(h->nlmsg_type),
3080 nl_family_to_str(ndm->ndm_family), ifp->name,
bd47f3a3 3081 ndm->ndm_ifindex, VRF_LOGNAME(vrf), ifp->vrf_id);
d62a17ae 3082 return 0;
20089ae2
DS
3083 }
3084
3085 memset(&ip, 0, sizeof(struct ipaddr));
3086 ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6;
3087 memcpy(&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
3088
f17b99ed
DS
3089 /* if kernel deletes our rfc5549 neighbor entry, re-install it */
3090 if (h->nlmsg_type == RTM_DELNEIGH && (ndm->ndm_state & NUD_PERMANENT)) {
9b036974 3091 netlink_handle_5549(ndm, zif, ifp, &ip, false);
28bd0652
DS
3092 if (IS_ZEBRA_DEBUG_KERNEL)
3093 zlog_debug(
3094 "\tNeighbor Entry Received is a 5549 entry, finished");
20089ae2
DS
3095 return 0;
3096 }
d62a17ae 3097
f17b99ed 3098 /* if kernel marks our rfc5549 neighbor entry invalid, re-install it */
9b036974
DS
3099 if (h->nlmsg_type == RTM_NEWNEIGH && !(ndm->ndm_state & NUD_VALID))
3100 netlink_handle_5549(ndm, zif, ifp, &ip, true);
f17b99ed 3101
d62a17ae 3102 /* The neighbor is present on an SVI. From this, we locate the
3103 * underlying
3104 * bridge because we're only interested in neighbors on a VxLAN bridge.
3105 * The bridge is located based on the nature of the SVI:
3106 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN
3107 * interface
3108 * and is linked to the bridge
3109 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge
3110 * inteface
3111 * itself
3112 */
3113 if (IS_ZEBRA_IF_VLAN(ifp)) {
5895d33f 3114 link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
71349e03 3115 zif->link_ifindex);
d62a17ae 3116 if (!link_if)
3117 return 0;
3118 } else if (IS_ZEBRA_IF_BRIDGE(ifp))
3119 link_if = ifp;
28bd0652
DS
3120 else {
3121 if (IS_ZEBRA_DEBUG_KERNEL)
3122 zlog_debug(
3123 "\tNeighbor Entry received is not on a VLAN or a BRIDGE, ignoring");
d62a17ae 3124 return 0;
28bd0652 3125 }
d62a17ae 3126
d62a17ae 3127 memset(&mac, 0, sizeof(struct ethaddr));
d62a17ae 3128 if (h->nlmsg_type == RTM_NEWNEIGH) {
3129 if (tb[NDA_LLADDR]) {
ff8b7eb8 3130 if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
28bd0652
DS
3131 if (IS_ZEBRA_DEBUG_KERNEL)
3132 zlog_debug(
bd47f3a3 3133 "%s family %s IF %s(%u) vrf %s(%u) - LLADDR is not MAC, len %lu",
28bd0652
DS
3134 nl_msg_type_to_str(
3135 h->nlmsg_type),
3136 nl_family_to_str(
3137 ndm->ndm_family),
3138 ifp->name, ndm->ndm_ifindex,
bd47f3a3 3139 VRF_LOGNAME(vrf), ifp->vrf_id,
28bd0652
DS
3140 (unsigned long)RTA_PAYLOAD(
3141 tb[NDA_LLADDR]));
d62a17ae 3142 return 0;
3143 }
3144
3145 mac_present = 1;
ff8b7eb8 3146 memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETH_ALEN);
d62a17ae 3147 }
3148
a37f4598 3149 is_ext = !!(ndm->ndm_flags & NTF_EXT_LEARNED);
3150 is_router = !!(ndm->ndm_flags & NTF_ROUTER);
d62a17ae 3151
3152 if (IS_ZEBRA_DEBUG_KERNEL)
3153 zlog_debug(
bd47f3a3 3154 "Rx %s family %s IF %s(%u) vrf %s(%u) IP %s MAC %s state 0x%x flags 0x%x",
d62a17ae 3155 nl_msg_type_to_str(h->nlmsg_type),
3156 nl_family_to_str(ndm->ndm_family), ifp->name,
bd47f3a3 3157 ndm->ndm_ifindex, VRF_LOGNAME(vrf), ifp->vrf_id,
d62a17ae 3158 ipaddr2str(&ip, buf2, sizeof(buf2)),
3159 mac_present
3160 ? prefix_mac2str(&mac, buf, sizeof(buf))
3161 : "",
3162 ndm->ndm_state, ndm->ndm_flags);
3163
3164 /* If the neighbor state is valid for use, process as an add or
3165 * update
3166 * else process as a delete. Note that the delete handling may
3167 * result
3168 * in re-adding the neighbor if it is a valid "remote" neighbor.
3169 */
3170 if (ndm->ndm_state & NUD_VALID)
ee69da27 3171 return zebra_vxlan_handle_kernel_neigh_update(
d62a17ae 3172 ifp, link_if, &ip, &mac, ndm->ndm_state,
a37f4598 3173 is_ext, is_router);
d62a17ae 3174
ee69da27 3175 return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
d62a17ae 3176 }
3177
3178 if (IS_ZEBRA_DEBUG_KERNEL)
bd47f3a3 3179 zlog_debug("Rx %s family %s IF %s(%u) vrf %s(%u) IP %s",
d62a17ae 3180 nl_msg_type_to_str(h->nlmsg_type),
3181 nl_family_to_str(ndm->ndm_family), ifp->name,
bd47f3a3 3182 ndm->ndm_ifindex, VRF_LOGNAME(vrf), ifp->vrf_id,
d62a17ae 3183 ipaddr2str(&ip, buf2, sizeof(buf2)));
3184
3185 /* Process the delete - it may result in re-adding the neighbor if it is
3186 * a valid "remote" neighbor.
3187 */
ee69da27 3188 return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
2232a77c 3189}
3190
2414abd3 3191static int netlink_neigh_table(struct nlmsghdr *h, ns_id_t ns_id, int startup)
2232a77c 3192{
d62a17ae 3193 int len;
3194 struct ndmsg *ndm;
2232a77c 3195
d62a17ae 3196 if (h->nlmsg_type != RTM_NEWNEIGH)
3197 return 0;
2232a77c 3198
d62a17ae 3199 /* Length validity. */
3200 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
3201 if (len < 0)
3202 return -1;
2232a77c 3203
d62a17ae 3204 /* We are interested only in AF_INET or AF_INET6 notifications. */
3205 ndm = NLMSG_DATA(h);
3206 if (ndm->ndm_family != AF_INET && ndm->ndm_family != AF_INET6)
3207 return 0;
2232a77c 3208
2414abd3 3209 return netlink_neigh_change(h, len);
2232a77c 3210}
3211
3212/* Request for IP neighbor information from the kernel */
85a75f1e
MS
3213static int netlink_request_neigh(struct nlsock *netlink_cmd, int family,
3214 int type, ifindex_t ifindex)
2232a77c 3215{
d62a17ae 3216 struct {
3217 struct nlmsghdr n;
3218 struct ndmsg ndm;
3219 char buf[256];
3220 } req;
3221
3222 /* Form the request, specifying filter (rtattr) if needed. */
3223 memset(&req, 0, sizeof(req));
3224 req.n.nlmsg_type = type;
718f9b0f 3225 req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
d62a17ae 3226 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
3227 req.ndm.ndm_family = family;
3228 if (ifindex)
3229 addattr32(&req.n, sizeof(req), NDA_IFINDEX, ifindex);
3230
fd3f8e52 3231 return netlink_request(netlink_cmd, &req);
2232a77c 3232}
3233
3234/*
3235 * IP Neighbor table read using netlink interface. This is invoked
3236 * at startup.
3237 */
d62a17ae 3238int netlink_neigh_read(struct zebra_ns *zns)
2232a77c 3239{
d62a17ae 3240 int ret;
85a75f1e
MS
3241 struct zebra_dplane_info dp_info;
3242
3243 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
2232a77c 3244
d62a17ae 3245 /* Get IP neighbor table. */
85a75f1e
MS
3246 ret = netlink_request_neigh(&zns->netlink_cmd, AF_UNSPEC, RTM_GETNEIGH,
3247 0);
d62a17ae 3248 if (ret < 0)
3249 return ret;
85a75f1e
MS
3250 ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd,
3251 &dp_info, 0, 1);
2232a77c 3252
d62a17ae 3253 return ret;
2232a77c 3254}
3255
3256/*
3257 * IP Neighbor table read using netlink interface. This is for a specific
3258 * VLAN device.
3259 */
d62a17ae 3260int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
2232a77c 3261{
d62a17ae 3262 int ret = 0;
85a75f1e
MS
3263 struct zebra_dplane_info dp_info;
3264
3265 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
2232a77c 3266
85a75f1e 3267 ret = netlink_request_neigh(&zns->netlink_cmd, AF_UNSPEC, RTM_GETNEIGH,
d62a17ae 3268 vlan_if->ifindex);
3269 if (ret < 0)
3270 return ret;
85a75f1e
MS
3271 ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd,
3272 &dp_info, 0, 0);
2232a77c 3273
d62a17ae 3274 return ret;
2232a77c 3275}
3276
67fb9374
CS
3277/*
3278 * Request for a specific IP in VLAN (SVI) device from IP Neighbor table,
3279 * read using netlink interface.
3280 */
3281static int netlink_request_specific_neigh_in_vlan(struct zebra_ns *zns,
3282 int type, struct ipaddr *ip,
3283 ifindex_t ifindex)
3284{
3285 struct {
3286 struct nlmsghdr n;
3287 struct ndmsg ndm;
3288 char buf[256];
3289 } req;
3290 int ipa_len;
3291
3292 /* Form the request, specifying filter (rtattr) if needed. */
3293 memset(&req, 0, sizeof(req));
3294 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
3295 req.n.nlmsg_flags = NLM_F_REQUEST;
3296 req.n.nlmsg_type = type; /* RTM_GETNEIGH */
3297 req.ndm.ndm_ifindex = ifindex;
3298
3299 if (IS_IPADDR_V4(ip)) {
3300 ipa_len = IPV4_MAX_BYTELEN;
3301 req.ndm.ndm_family = AF_INET;
3302
3303 } else {
3304 ipa_len = IPV6_MAX_BYTELEN;
3305 req.ndm.ndm_family = AF_INET6;
3306 }
3307
3308 addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
3309
7c26c121
CS
3310 if (IS_ZEBRA_DEBUG_KERNEL) {
3311 char buf[INET6_ADDRSTRLEN];
3312
3313 zlog_debug("%s: Tx %s family %s IF %u IP %s flags 0x%x",
3314 __func__, nl_msg_type_to_str(type),
3315 nl_family_to_str(req.ndm.ndm_family), ifindex,
3316 ipaddr2str(ip, buf, sizeof(buf)), req.n.nlmsg_flags);
3317 }
3318
fd3f8e52 3319 return netlink_request(&zns->netlink_cmd, &req);
67fb9374
CS
3320}
3321
3322int netlink_neigh_read_specific_ip(struct ipaddr *ip,
3323 struct interface *vlan_if)
3324{
3325 int ret = 0;
3326 struct zebra_ns *zns;
3327 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vlan_if->vrf_id);
3328 char buf[INET6_ADDRSTRLEN];
3329 struct zebra_dplane_info dp_info;
3330
3331 zns = zvrf->zns;
3332
3333 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
3334
3335 if (IS_ZEBRA_DEBUG_KERNEL)
bd47f3a3 3336 zlog_debug("%s: neigh request IF %s(%u) IP %s vrf %s(%u)",
15569c58 3337 __func__, vlan_if->name, vlan_if->ifindex,
bd47f3a3
JU
3338 ipaddr2str(ip, buf, sizeof(buf)),
3339 vrf_id_to_name(vlan_if->vrf_id), vlan_if->vrf_id);
67fb9374
CS
3340
3341 ret = netlink_request_specific_neigh_in_vlan(zns, RTM_GETNEIGH, ip,
3342 vlan_if->ifindex);
3343 if (ret < 0)
3344 return ret;
3345
3346 ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd,
3347 &dp_info, 1, 0);
3348
3349 return ret;
3350}
3351
2414abd3 3352int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
2232a77c 3353{
d62a17ae 3354 int len;
3355 struct ndmsg *ndm;
2232a77c 3356
d62a17ae 3357 if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH))
3358 return 0;
2232a77c 3359
d62a17ae 3360 /* Length validity. */
3361 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
9bdf8618 3362 if (len < 0) {
15569c58
DA
3363 zlog_err(
3364 "%s: Message received from netlink is of a broken size %d %zu",
3365 __func__, h->nlmsg_len,
3366 (size_t)NLMSG_LENGTH(sizeof(struct ndmsg)));
d62a17ae 3367 return -1;
9bdf8618 3368 }
2232a77c 3369
d62a17ae 3370 /* Is this a notification for the MAC FDB or IP neighbor table? */
3371 ndm = NLMSG_DATA(h);
3372 if (ndm->ndm_family == AF_BRIDGE)
2414abd3 3373 return netlink_macfdb_change(h, len, ns_id);
2232a77c 3374
d62a17ae 3375 if (ndm->ndm_type != RTN_UNICAST)
3376 return 0;
2232a77c 3377
d62a17ae 3378 if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6)
2414abd3 3379 return netlink_ipneigh_change(h, len, ns_id);
8a1b681c 3380 else {
9df414fe 3381 flog_warn(
e914ccbe 3382 EC_ZEBRA_UNKNOWN_FAMILY,
87b5d1b0
DS
3383 "Invalid address family: %u received from kernel neighbor change: %s",
3384 ndm->ndm_family, nl_msg_type_to_str(h->nlmsg_type));
8a1b681c
SW
3385 return 0;
3386 }
2232a77c 3387
d62a17ae 3388 return 0;
2232a77c 3389}
3390
931fa60c
MS
3391/*
3392 * Utility neighbor-update function, using info from dplane context.
3393 */
3394static int netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
3395 int cmd)
2232a77c 3396{
931fa60c
MS
3397 const struct ipaddr *ip;
3398 const struct ethaddr *mac;
3399 uint8_t flags;
3400 uint16_t state;
340845e2 3401 uint8_t family;
d4d4ec1c 3402 uint8_t nl_pkt[NL_PKT_BUF_SIZE];
d62a17ae 3403
931fa60c
MS
3404 ip = dplane_ctx_neigh_get_ipaddr(ctx);
3405 mac = dplane_ctx_neigh_get_mac(ctx);
3406 if (is_zero_mac(mac))
3407 mac = NULL;
3408
3409 flags = neigh_flags_to_netlink(dplane_ctx_neigh_get_flags(ctx));
3410 state = neigh_state_to_netlink(dplane_ctx_neigh_get_state(ctx));
3411
340845e2 3412 family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
d62a17ae 3413
340845e2
JU
3414 if (IS_ZEBRA_DEBUG_KERNEL) {
3415 char buf[INET6_ADDRSTRLEN];
3416 char buf2[ETHER_ADDR_STRLEN];
d62a17ae 3417
340845e2
JU
3418 zlog_debug(
3419 "Tx %s family %s IF %s(%u) Neigh %s MAC %s flags 0x%x state 0x%x",
3420 nl_msg_type_to_str(cmd), nl_family_to_str(family),
3421 dplane_ctx_get_ifname(ctx), dplane_ctx_get_ifindex(ctx),
3422 ipaddr2str(ip, buf, sizeof(buf)),
3423 mac ? prefix_mac2str(mac, buf2, sizeof(buf2)) : "null",
3424 flags, state);
3425 }
d62a17ae 3426
d4d4ec1c
RZ
3427 netlink_update_neigh_ctx_internal(
3428 ctx, cmd, mac, ip, true, family, RTN_UNICAST, flags,
3429 state, nl_pkt, sizeof(nl_pkt));
3430
3431 return netlink_talk_info(netlink_talk_filter, (struct nlmsghdr *)nl_pkt,
3432 dplane_ctx_get_ns(ctx), 0);
2232a77c 3433}
3434
036d93c0
MS
3435/*
3436 * Update MAC, using dataplane context object.
3437 */
3438enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
2232a77c 3439{
d4d4ec1c
RZ
3440 uint8_t nl_pkt[NL_PKT_BUF_SIZE];
3441 ssize_t rv;
340845e2 3442
d4d4ec1c
RZ
3443 rv = netlink_macfdb_update_ctx(ctx, nl_pkt, sizeof(nl_pkt));
3444 if (rv <= 0)
3445 return ZEBRA_DPLANE_REQUEST_FAILURE;
3446
3447 rv = netlink_talk_info(netlink_talk_filter, (struct nlmsghdr *)nl_pkt,
3448 dplane_ctx_get_ns(ctx), 0);
3449
3450 return rv == 0 ?
3451 ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE;
2232a77c 3452}
3453
931fa60c 3454enum zebra_dplane_result kernel_neigh_update_ctx(struct zebra_dplane_ctx *ctx)
2232a77c 3455{
931fa60c 3456 int ret = -1;
2232a77c 3457
931fa60c
MS
3458 switch (dplane_ctx_get_op(ctx)) {
3459 case DPLANE_OP_NEIGH_INSTALL:
3460 case DPLANE_OP_NEIGH_UPDATE:
3461 ret = netlink_neigh_update_ctx(ctx, RTM_NEWNEIGH);
3462 break;
3463 case DPLANE_OP_NEIGH_DELETE:
3464 ret = netlink_neigh_update_ctx(ctx, RTM_DELNEIGH);
3465 break;
0bbd4ff4
MS
3466 case DPLANE_OP_VTEP_ADD:
3467 ret = netlink_vxlan_flood_update_ctx(ctx, RTM_NEWNEIGH);
3468 break;
3469 case DPLANE_OP_VTEP_DELETE:
3470 ret = netlink_vxlan_flood_update_ctx(ctx, RTM_DELNEIGH);
3471 break;
931fa60c
MS
3472 default:
3473 break;
3474 }
2232a77c 3475
931fa60c
MS
3476 return (ret == 0 ?
3477 ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
6fe2b0e6
CS
3478}
3479
16c628de
MS
3480/*
3481 * MPLS label forwarding table change via netlink interface, using dataplane
3482 * context information.
3483 */
fc608372 3484int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
16c628de
MS
3485{
3486 mpls_lse_t lse;
81793ac1 3487 const zebra_nhlfe_t *nhlfe;
16c628de
MS
3488 struct nexthop *nexthop = NULL;
3489 unsigned int nexthop_num;
3490 const char *routedesc;
3491 int route_type;
9a0132a5 3492 struct prefix p = {0};
16c628de
MS
3493
3494 struct {
3495 struct nlmsghdr n;
3496 struct rtmsg r;
3497 char buf[NL_PKT_BUF_SIZE];
3498 } req;
3499
3500 memset(&req, 0, sizeof(req) - NL_PKT_BUF_SIZE);
3501
3502 /*
3503 * Count # nexthops so we can decide whether to use singlepath
3504 * or multipath case.
3505 */
3506 nexthop_num = 0;
3507 for (nhlfe = dplane_ctx_get_nhlfe(ctx); nhlfe; nhlfe = nhlfe->next) {
3508 nexthop = nhlfe->nexthop;
3509 if (!nexthop)
3510 continue;
3511 if (cmd == RTM_NEWROUTE) {
3512 /* Count all selected NHLFEs */
3513 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
3514 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
3515 nexthop_num++;
3516 } else { /* DEL */
3517 /* Count all installed NHLFEs */
3518 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)
3519 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
3520 nexthop_num++;
3521 }
3522 }
3523
3524 if ((nexthop_num == 0) ||
3525 (!dplane_ctx_get_best_nhlfe(ctx) && (cmd != RTM_DELROUTE)))
3526 return 0;
3527
3528 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
3529 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
3530 req.n.nlmsg_type = cmd;
3531 req.n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid;
3532
3533 req.r.rtm_family = AF_MPLS;
3534 req.r.rtm_table = RT_TABLE_MAIN;
3535 req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
3536 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
3537 req.r.rtm_type = RTN_UNICAST;
3538
3539 if (cmd == RTM_NEWROUTE) {
3540 /* We do a replace to handle update. */
3541 req.n.nlmsg_flags |= NLM_F_REPLACE;
3542
3543 /* set the protocol value if installing */
3544 route_type = re_type_from_lsp_type(
3545 dplane_ctx_get_best_nhlfe(ctx)->type);
3546 req.r.rtm_protocol = zebra2proto(route_type);
3547 }
3548
3549 /* Fill destination */
3550 lse = mpls_lse_encode(dplane_ctx_get_in_label(ctx), 0, 0, 1);
3551 addattr_l(&req.n, sizeof(req), RTA_DST, &lse, sizeof(mpls_lse_t));
3552
3553 /* Fill nexthops (paths) based on single-path or multipath. The paths
3554 * chosen depend on the operation.
3555 */
fc608372 3556 if (nexthop_num == 1) {
16c628de
MS
3557 routedesc = "single-path";
3558 _netlink_mpls_debug(cmd, dplane_ctx_get_in_label(ctx),
3559 routedesc);
3560
3561 nexthop_num = 0;
3562 for (nhlfe = dplane_ctx_get_nhlfe(ctx);
3563 nhlfe; nhlfe = nhlfe->next) {
3564 nexthop = nhlfe->nexthop;
3565 if (!nexthop)
3566 continue;
3567
3568 if ((cmd == RTM_NEWROUTE
3569 && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
3570 && CHECK_FLAG(nexthop->flags,
3571 NEXTHOP_FLAG_ACTIVE)))
3572 || (cmd == RTM_DELROUTE
3573 && (CHECK_FLAG(nhlfe->flags,
3574 NHLFE_FLAG_INSTALLED)
3575 && CHECK_FLAG(nexthop->flags,
3576 NEXTHOP_FLAG_FIB)))) {
3577 /* Add the gateway */
3578 _netlink_mpls_build_singlepath(
9a0132a5 3579 &p, routedesc, nhlfe, &req.n, &req.r,
16c628de
MS
3580 sizeof(req), cmd);
3581
3582 nexthop_num++;
3583 break;
3584 }
3585 }
3586 } else { /* Multipath case */
3587 char buf[NL_PKT_BUF_SIZE];
3588 struct rtattr *rta = (void *)buf;
3589 struct rtnexthop *rtnh;
81793ac1 3590 const union g_addr *src1 = NULL;
16c628de
MS
3591
3592 rta->rta_type = RTA_MULTIPATH;
3593 rta->rta_len = RTA_LENGTH(0);
3594 rtnh = RTA_DATA(rta);
3595
3596 routedesc = "multipath";
3597 _netlink_mpls_debug(cmd, dplane_ctx_get_in_label(ctx),
3598 routedesc);
3599
3600 nexthop_num = 0;
3601 for (nhlfe = dplane_ctx_get_nhlfe(ctx);
3602 nhlfe; nhlfe = nhlfe->next) {
3603 nexthop = nhlfe->nexthop;
3604 if (!nexthop)
3605 continue;
3606
16c628de
MS
3607 if ((cmd == RTM_NEWROUTE
3608 && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
3609 && CHECK_FLAG(nexthop->flags,
3610 NEXTHOP_FLAG_ACTIVE)))
3611 || (cmd == RTM_DELROUTE
3612 && (CHECK_FLAG(nhlfe->flags,
3613 NHLFE_FLAG_INSTALLED)
3614 && CHECK_FLAG(nexthop->flags,
3615 NEXTHOP_FLAG_FIB)))) {
3616 nexthop_num++;
3617
3618 /* Build the multipath */
9a0132a5
DS
3619 _netlink_mpls_build_multipath(&p, routedesc,
3620 nhlfe, rta, rtnh,
3621 &req.r, &src1);
16c628de
MS
3622 rtnh = RTNH_NEXT(rtnh);
3623 }
3624 }
3625
3626 /* Add the multipath */
3627 if (rta->rta_len > RTA_LENGTH(0))
3628 addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH,
3629 RTA_DATA(rta), RTA_PAYLOAD(rta));
3630 }
3631
3632 /* Talk to netlink socket. */
3633 return netlink_talk_info(netlink_talk_filter, &req.n,
3634 dplane_ctx_get_ns(ctx), 0);
3635}
ddfeb486 3636#endif /* HAVE_NETLINK */