]> git.proxmox.com Git - mirror_frr.git/blame - zebra/rt_netlink.c
zebra: Print out netlink message type instead of number
[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>
718e3744 30
31/* Hack for GNU libc version 2. */
32#ifndef MSG_TRUNC
33#define MSG_TRUNC 0x20
34#endif /* MSG_TRUNC */
35
36#include "linklist.h"
37#include "if.h"
38#include "log.h"
39#include "prefix.h"
40#include "connected.h"
41#include "table.h"
26e2ae36 42#include "memory.h"
4a1ab8e4 43#include "zebra_memory.h"
718e3744 44#include "rib.h"
e04ab74d 45#include "thread.h"
edd7c245 46#include "privs.h"
fb018d25 47#include "nexthop.h"
78104b9b 48#include "vrf.h"
5e6a74d8 49#include "vty.h"
40c7bdb0 50#include "mpls.h"
13d60d35 51#include "vxlan.h"
718e3744 52
bf094f69 53#include "zebra/zapi_msg.h"
fe18ee2d 54#include "zebra/zebra_ns.h"
7c551956 55#include "zebra/zebra_vrf.h"
6621ca86 56#include "zebra/rt.h"
718e3744 57#include "zebra/redistribute.h"
58#include "zebra/interface.h"
59#include "zebra/debug.h"
12f6fb97 60#include "zebra/rtadv.h"
567b877d 61#include "zebra/zebra_ptm.h"
40c7bdb0 62#include "zebra/zebra_mpls.h"
1fdc9eae 63#include "zebra/kernel_netlink.h"
64#include "zebra/rt_netlink.h"
e3be0432 65#include "zebra/zebra_mroute.h"
2232a77c 66#include "zebra/zebra_vxlan.h"
364fed6b 67#include "zebra/zebra_errors.h"
e3be0432 68
40c7bdb0 69#ifndef AF_MPLS
70#define AF_MPLS 28
71#endif
72
2232a77c 73static vlanid_t filter_vlan = 0;
74
d62a17ae 75struct gw_family_t {
d7c0a89a
QY
76 uint16_t filler;
77 uint16_t family;
d62a17ae 78 union g_addr gate;
40c7bdb0 79};
80
8755598a
DS
81char ipv4_ll_buf[16] = "169.254.0.1";
82struct in_addr ipv4_ll;
83
84/*
85 * The ipv4_ll data structure is used for all 5549
86 * additions to the kernel. Let's figure out the
87 * correct value one time instead for every
88 * install/remove of a 5549 type route
89 */
d62a17ae 90void rt_netlink_init(void)
8755598a 91{
d62a17ae 92 inet_pton(AF_INET, ipv4_ll_buf, &ipv4_ll);
8755598a
DS
93}
94
23b1f334
DD
95static inline int is_selfroute(int proto)
96{
d62a17ae 97 if ((proto == RTPROT_BGP) || (proto == RTPROT_OSPF)
d4d71f11 98 || (proto == RTPROT_ZSTATIC) || (proto == RTPROT_ZEBRA)
d62a17ae 99 || (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG)
100 || (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP)
915902cb 101 || (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)
0761368a 102 || (proto == RTPROT_RIP) || (proto == RTPROT_SHARP)
da82f6b4 103 || (proto == RTPROT_PBR) || (proto == RTPROT_OPENFABRIC)) {
d62a17ae 104 return 1;
105 }
106
107 return 0;
23b1f334
DD
108}
109
915902cb 110static inline int zebra2proto(int proto)
23b1f334 111{
d62a17ae 112 switch (proto) {
113 case ZEBRA_ROUTE_BABEL:
114 proto = RTPROT_BABEL;
115 break;
116 case ZEBRA_ROUTE_BGP:
117 proto = RTPROT_BGP;
118 break;
119 case ZEBRA_ROUTE_OSPF:
120 case ZEBRA_ROUTE_OSPF6:
121 proto = RTPROT_OSPF;
122 break;
123 case ZEBRA_ROUTE_STATIC:
d4d71f11 124 proto = RTPROT_ZSTATIC;
d62a17ae 125 break;
126 case ZEBRA_ROUTE_ISIS:
127 proto = RTPROT_ISIS;
128 break;
129 case ZEBRA_ROUTE_RIP:
130 proto = RTPROT_RIP;
131 break;
132 case ZEBRA_ROUTE_RIPNG:
133 proto = RTPROT_RIPNG;
134 break;
135 case ZEBRA_ROUTE_NHRP:
136 proto = RTPROT_NHRP;
137 break;
138 case ZEBRA_ROUTE_EIGRP:
139 proto = RTPROT_EIGRP;
140 break;
141 case ZEBRA_ROUTE_LDP:
142 proto = RTPROT_LDP;
143 break;
8a71d93d
DS
144 case ZEBRA_ROUTE_SHARP:
145 proto = RTPROT_SHARP;
146 break;
0761368a
DS
147 case ZEBRA_ROUTE_PBR:
148 proto = RTPROT_PBR;
149 break;
da82f6b4
CF
150 case ZEBRA_ROUTE_OPENFABRIC:
151 proto = RTPROT_OPENFABRIC;
152 break;
d62a17ae 153 default:
0761368a
DS
154 /*
155 * When a user adds a new protocol this will show up
156 * to let them know to do something about it. This
157 * is intentionally a warn because we should see
158 * this as part of development of a new protocol
159 */
9df414fe
QY
160 zlog_debug(
161 "%s: Please add this protocol(%d) to proper rt_netlink.c handling",
162 __PRETTY_FUNCTION__, proto);
d62a17ae 163 proto = RTPROT_ZEBRA;
164 break;
165 }
166
167 return proto;
23b1f334
DD
168}
169
915902cb
DS
170static inline int proto2zebra(int proto, int family)
171{
172 switch (proto) {
173 case RTPROT_BABEL:
174 proto = ZEBRA_ROUTE_BABEL;
175 break;
176 case RTPROT_BGP:
177 proto = ZEBRA_ROUTE_BGP;
178 break;
179 case RTPROT_OSPF:
996c9314
LB
180 proto = (family == AFI_IP) ? ZEBRA_ROUTE_OSPF
181 : ZEBRA_ROUTE_OSPF6;
915902cb
DS
182 break;
183 case RTPROT_ISIS:
184 proto = ZEBRA_ROUTE_ISIS;
185 break;
186 case RTPROT_RIP:
187 proto = ZEBRA_ROUTE_RIP;
188 break;
189 case RTPROT_RIPNG:
190 proto = ZEBRA_ROUTE_RIPNG;
191 break;
192 case RTPROT_NHRP:
193 proto = ZEBRA_ROUTE_NHRP;
194 break;
195 case RTPROT_EIGRP:
196 proto = ZEBRA_ROUTE_EIGRP;
197 break;
198 case RTPROT_LDP:
199 proto = ZEBRA_ROUTE_LDP;
200 break;
201 case RTPROT_STATIC:
d4d71f11 202 case RTPROT_ZSTATIC:
915902cb
DS
203 proto = ZEBRA_ROUTE_STATIC;
204 break;
0761368a
DS
205 case RTPROT_SHARP:
206 proto = ZEBRA_ROUTE_SHARP;
207 break;
208 case RTPROT_PBR:
209 proto = ZEBRA_ROUTE_PBR;
210 break;
da82f6b4
CF
211 case RTPROT_OPENFABRIC:
212 proto = ZEBRA_ROUTE_OPENFABRIC;
213 break;
915902cb 214 default:
0761368a
DS
215 /*
216 * When a user adds a new protocol this will show up
217 * to let them know to do something about it. This
218 * is intentionally a warn because we should see
219 * this as part of development of a new protocol
220 */
9df414fe
QY
221 zlog_debug(
222 "%s: Please add this protocol(%d) to proper rt_netlink.c handling",
223 __PRETTY_FUNCTION__, proto);
915902cb
DS
224 proto = ZEBRA_ROUTE_KERNEL;
225 break;
226 }
227 return proto;
228}
229
12f6fb97
DS
230/*
231Pending: create an efficient table_id (in a tree/hash) based lookup)
232 */
d7c0a89a 233static vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id)
12f6fb97 234{
d62a17ae 235 struct vrf *vrf;
236 struct zebra_vrf *zvrf;
12f6fb97 237
a2addae8 238 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
78dd30b2
PG
239 zvrf = vrf->info;
240 if (zvrf == NULL)
d62a17ae 241 continue;
78dd30b2
PG
242 /* case vrf with netns : match the netnsid */
243 if (vrf_is_backend_netns()) {
244 if (ns_id == zvrf_id(zvrf))
245 return zvrf_id(zvrf);
246 } else {
247 /* VRF is VRF_BACKEND_VRF_LITE */
248 if (zvrf->table_id != table_id)
249 continue;
250 return zvrf_id(zvrf);
251 }
d62a17ae 252 }
12f6fb97 253
d62a17ae 254 return VRF_DEFAULT;
12f6fb97
DS
255}
256
87da6a60
SW
257/**
258 * @parse_encap_mpls() - Parses encapsulated mpls attributes
259 * @tb: Pointer to rtattr to look for nested items in.
260 * @labels: Pointer to store labels in.
261 *
262 * Return: Number of mpls labels found.
263 */
264static int parse_encap_mpls(struct rtattr *tb, mpls_label_t *labels)
265{
266 struct rtattr *tb_encap[MPLS_IPTUNNEL_MAX + 1] = {0};
267 mpls_lse_t *lses = NULL;
268 int num_labels = 0;
269 uint32_t ttl = 0;
270 uint32_t bos = 0;
271 uint32_t exp = 0;
272 mpls_label_t label = 0;
273
274 netlink_parse_rtattr_nested(tb_encap, MPLS_IPTUNNEL_MAX, tb);
275 lses = (mpls_lse_t *)RTA_DATA(tb_encap[MPLS_IPTUNNEL_DST]);
276 while (!bos && num_labels < MPLS_MAX_LABELS) {
277 mpls_lse_decode(lses[num_labels], &label, &ttl, &exp, &bos);
278 labels[num_labels++] = label;
279 }
280
281 return num_labels;
282}
283
718e3744 284/* Looking up routing table by netlink interface. */
2414abd3 285static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
d62a17ae 286 int startup)
718e3744 287{
d62a17ae 288 int len;
289 struct rtmsg *rtm;
290 struct rtattr *tb[RTA_MAX + 1];
d7c0a89a 291 uint8_t flags = 0;
d62a17ae 292 struct prefix p;
792fa92e 293 struct prefix_ipv6 src_p = {};
78dd30b2 294 vrf_id_t vrf_id;
d62a17ae 295
296 char anyaddr[16] = {0};
297
915902cb 298 int proto = ZEBRA_ROUTE_KERNEL;
d62a17ae 299 int index = 0;
300 int table;
301 int metric = 0;
d7c0a89a 302 uint32_t mtu = 0;
25715c7e 303 uint8_t distance = 0;
4e40b6d6 304 route_tag_t tag = 0;
d62a17ae 305
306 void *dest = NULL;
307 void *gate = NULL;
308 void *prefsrc = NULL; /* IPv4 preferred source host address */
309 void *src = NULL; /* IPv6 srcdest source prefix */
e655a03c 310 enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
d62a17ae 311
87da6a60
SW
312 /* MPLS labels */
313 mpls_label_t labels[MPLS_MAX_LABELS] = {0};
314 int num_labels = 0;
315
d62a17ae 316 rtm = NLMSG_DATA(h);
317
318 if (startup && h->nlmsg_type != RTM_NEWROUTE)
319 return 0;
e655a03c
DL
320 switch (rtm->rtm_type) {
321 case RTN_UNICAST:
322 break;
323 case RTN_BLACKHOLE:
324 bh_type = BLACKHOLE_NULL;
325 break;
326 case RTN_UNREACHABLE:
327 bh_type = BLACKHOLE_REJECT;
328 break;
329 case RTN_PROHIBIT:
330 bh_type = BLACKHOLE_ADMINPROHIB;
331 break;
332 default:
d62a17ae 333 return 0;
e655a03c 334 }
d62a17ae 335
336 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
9bdf8618
DS
337 if (len < 0) {
338 zlog_err("%s: Message received from netlink is of a broken size %d %zu",
339 __PRETTY_FUNCTION__, h->nlmsg_len,
340 (size_t)NLMSG_LENGTH(sizeof(struct rtmsg)));
d62a17ae 341 return -1;
9bdf8618 342 }
d62a17ae 343
344 memset(tb, 0, sizeof tb);
345 netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len);
346
347 if (rtm->rtm_flags & RTM_F_CLONED)
348 return 0;
349 if (rtm->rtm_protocol == RTPROT_REDIRECT)
350 return 0;
351 if (rtm->rtm_protocol == RTPROT_KERNEL)
352 return 0;
353
354 if (!startup && is_selfroute(rtm->rtm_protocol)
6ab5222f
DS
355 && h->nlmsg_type == RTM_NEWROUTE) {
356 if (IS_ZEBRA_DEBUG_KERNEL)
357 zlog_debug("Route type: %d Received that we think we have originated, ignoring",
358 rtm->rtm_protocol);
d62a17ae 359 return 0;
6ab5222f 360 }
d62a17ae 361
362 /* We don't care about change notifications for the MPLS table. */
363 /* TODO: Revisit this. */
364 if (rtm->rtm_family == AF_MPLS)
365 return 0;
366
367 /* Table corresponding to route. */
368 if (tb[RTA_TABLE])
369 table = *(int *)RTA_DATA(tb[RTA_TABLE]);
370 else
371 table = rtm->rtm_table;
372
373 /* Map to VRF */
78dd30b2 374 vrf_id = vrf_lookup_by_table(table, ns_id);
d62a17ae 375 if (vrf_id == VRF_DEFAULT) {
376 if (!is_zebra_valid_kernel_table(table)
377 && !is_zebra_main_routing_table(table))
378 return 0;
379 }
380
381 /* Route which inserted by Zebra. */
915902cb 382 if (is_selfroute(rtm->rtm_protocol)) {
d62a17ae 383 flags |= ZEBRA_FLAG_SELFROUTE;
915902cb
DS
384 proto = proto2zebra(rtm->rtm_protocol, rtm->rtm_family);
385 }
d62a17ae 386 if (tb[RTA_OIF])
387 index = *(int *)RTA_DATA(tb[RTA_OIF]);
388
389 if (tb[RTA_DST])
390 dest = RTA_DATA(tb[RTA_DST]);
391 else
392 dest = anyaddr;
393
394 if (tb[RTA_SRC])
395 src = RTA_DATA(tb[RTA_SRC]);
396 else
397 src = anyaddr;
398
399 if (tb[RTA_PREFSRC])
400 prefsrc = RTA_DATA(tb[RTA_PREFSRC]);
401
402 if (tb[RTA_GATEWAY])
403 gate = RTA_DATA(tb[RTA_GATEWAY]);
404
f19435a8
DS
405 if (tb[RTA_PRIORITY])
406 metric = *(int *)RTA_DATA(tb[RTA_PRIORITY]);
d62a17ae 407
4e40b6d6
KK
408#if defined(SUPPORT_REALMS)
409 if (tb[RTA_FLOW])
410 tag = *(uint32_t *)RTA_DATA(tb[RTA_FLOW]);
411#endif
412
f19435a8
DS
413 if (tb[RTA_METRICS]) {
414 struct rtattr *mxrta[RTAX_MAX + 1];
d62a17ae 415
f19435a8 416 memset(mxrta, 0, sizeof mxrta);
996c9314 417 netlink_parse_rtattr(mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
f19435a8 418 RTA_PAYLOAD(tb[RTA_METRICS]));
d62a17ae 419
f19435a8 420 if (mxrta[RTAX_MTU])
d7c0a89a 421 mtu = *(uint32_t *)RTA_DATA(mxrta[RTAX_MTU]);
d62a17ae 422 }
423
424 if (rtm->rtm_family == AF_INET) {
425 p.family = AF_INET;
930571d2 426 if (rtm->rtm_dst_len > IPV4_MAX_BITLEN) {
e17d9b2d 427 zlog_err(
75829703 428 "Invalid destination prefix length: %u received from kernel route change",
930571d2 429 rtm->rtm_dst_len);
e17d9b2d 430 return -1;
930571d2 431 }
d62a17ae 432 memcpy(&p.u.prefix4, dest, 4);
433 p.prefixlen = rtm->rtm_dst_len;
434
1f610a1f
CF
435 if (rtm->rtm_src_len != 0) {
436 char buf[PREFIX_STRLEN];
9df414fe 437 flog_warn(
e914ccbe 438 EC_ZEBRA_UNSUPPORTED_V4_SRCDEST,
9df414fe
QY
439 "unsupported IPv4 sourcedest route (dest %s vrf %u)",
440 prefix2str(&p, buf, sizeof(buf)), vrf_id);
1f610a1f
CF
441 return 0;
442 }
930571d2 443
1f610a1f
CF
444 /* Force debug below to not display anything for source */
445 src_p.prefixlen = 0;
d62a17ae 446 } else if (rtm->rtm_family == AF_INET6) {
447 p.family = AF_INET6;
930571d2 448 if (rtm->rtm_dst_len > IPV6_MAX_BITLEN) {
e17d9b2d 449 zlog_err(
75829703 450 "Invalid destination prefix length: %u received from kernel route change",
930571d2 451 rtm->rtm_dst_len);
e17d9b2d 452 return -1;
930571d2 453 }
d62a17ae 454 memcpy(&p.u.prefix6, dest, 16);
455 p.prefixlen = rtm->rtm_dst_len;
456
457 src_p.family = AF_INET6;
930571d2 458 if (rtm->rtm_src_len > IPV6_MAX_BITLEN) {
e17d9b2d 459 zlog_err(
75829703 460 "Invalid source prefix length: %u received from kernel route change",
930571d2 461 rtm->rtm_src_len);
e17d9b2d 462 return -1;
930571d2 463 }
d62a17ae 464 memcpy(&src_p.prefix, src, 16);
465 src_p.prefixlen = rtm->rtm_src_len;
466 }
467
25715c7e
DS
468 /*
469 * For ZEBRA_ROUTE_KERNEL types:
470 *
471 * The metric/priority of the route received from the kernel
472 * is a 32 bit number. We are going to interpret the high
473 * order byte as the Admin Distance and the low order 3 bytes
474 * as the metric.
475 *
476 * This will allow us to do two things:
477 * 1) Allow the creation of kernel routes that can be
478 * overridden by zebra.
479 * 2) Allow the old behavior for 'most' kernel route types
480 * if a user enters 'ip route ...' v4 routes get a metric
481 * of 0 and v6 routes get a metric of 1024. Both of these
482 * values will end up with a admin distance of 0, which
483 * will cause them to win for the purposes of zebra.
484 */
485 if (proto == ZEBRA_ROUTE_KERNEL) {
486 distance = (metric >> 24) & 0xFF;
996c9314 487 metric = (metric & 0x00FFFFFF);
25715c7e
DS
488 }
489
d62a17ae 490 if (IS_ZEBRA_DEBUG_KERNEL) {
491 char buf[PREFIX_STRLEN];
492 char buf2[PREFIX_STRLEN];
45df4e96 493 zlog_debug("%s %s%s%s vrf %u(%u) metric: %d Admin Distance: %d",
996c9314
LB
494 nl_msg_type_to_str(h->nlmsg_type),
495 prefix2str(&p, buf, sizeof(buf)),
496 src_p.prefixlen ? " from " : "",
497 src_p.prefixlen
498 ? prefix2str(&src_p, buf2, sizeof(buf2))
499 : "",
45df4e96 500 vrf_id, table, metric, distance);
d62a17ae 501 }
502
503 afi_t afi = AFI_IP;
504 if (rtm->rtm_family == AF_INET6)
505 afi = AFI_IP6;
506
507 if (h->nlmsg_type == RTM_NEWROUTE) {
8795f904
DS
508 struct interface *ifp;
509 vrf_id_t nh_vrf_id = vrf_id;
510
fd36be7e
DL
511 if (!tb[RTA_MULTIPATH]) {
512 struct nexthop nh;
513 size_t sz = (afi == AFI_IP) ? 4 : 16;
514
515 memset(&nh, 0, sizeof(nh));
af760ec1
DS
516
517 if (bh_type == BLACKHOLE_UNSPEC) {
518 if (index && !gate)
519 nh.type = NEXTHOP_TYPE_IFINDEX;
520 else if (index && gate)
996c9314
LB
521 nh.type =
522 (afi == AFI_IP)
523 ? NEXTHOP_TYPE_IPV4_IFINDEX
524 : NEXTHOP_TYPE_IPV6_IFINDEX;
af760ec1 525 else if (!index && gate)
1dca2eaa
RW
526 nh.type = (afi == AFI_IP)
527 ? NEXTHOP_TYPE_IPV4
528 : NEXTHOP_TYPE_IPV6;
af760ec1
DS
529 else {
530 nh.type = NEXTHOP_TYPE_BLACKHOLE;
531 nh.bh_type = bh_type;
532 }
533 } else {
fd36be7e 534 nh.type = NEXTHOP_TYPE_BLACKHOLE;
e655a03c
DL
535 nh.bh_type = bh_type;
536 }
fd36be7e
DL
537 nh.ifindex = index;
538 if (prefsrc)
539 memcpy(&nh.src, prefsrc, sz);
540 if (gate)
541 memcpy(&nh.gate, gate, sz);
915902cb 542
8795f904 543 if (index) {
fac4d51e
PG
544 ifp = if_lookup_by_index_per_ns(
545 zebra_ns_lookup(ns_id),
546 index);
8795f904
DS
547 if (ifp)
548 nh_vrf_id = ifp->vrf_id;
549 }
4a7371e9 550 nh.vrf_id = nh_vrf_id;
8795f904 551
87da6a60
SW
552 if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]
553 && *(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE])
554 == LWTUNNEL_ENCAP_MPLS) {
555 num_labels =
556 parse_encap_mpls(tb[RTA_ENCAP], labels);
557 }
558
559 if (num_labels)
560 nexthop_add_labels(&nh, ZEBRA_LSP_STATIC,
561 num_labels, labels);
562
4a7371e9 563 rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p,
1f610a1f 564 &src_p, &nh, table, metric, mtu, distance, tag);
fd36be7e 565 } else {
d62a17ae 566 /* This is a multipath route */
567
568 struct route_entry *re;
569 struct rtnexthop *rtnh =
570 (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
571
572 len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
573
574 re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
915902cb 575 re->type = proto;
25715c7e 576 re->distance = distance;
d62a17ae 577 re->flags = flags;
578 re->metric = metric;
579 re->mtu = mtu;
580 re->vrf_id = vrf_id;
581 re->table = table;
582 re->nexthop_num = 0;
583 re->uptime = time(NULL);
4e40b6d6 584 re->tag = tag;
d62a17ae 585
586 for (;;) {
87da6a60 587 struct nexthop *nh = NULL;
c683bd44 588
d62a17ae 589 if (len < (int)sizeof(*rtnh)
590 || rtnh->rtnh_len > len)
591 break;
592
593 index = rtnh->rtnh_ifindex;
8795f904
DS
594 if (index) {
595 /*
596 * Yes we are looking this up
597 * for every nexthop and just
598 * using the last one looked
599 * up right now
600 */
fac4d51e
PG
601 ifp = if_lookup_by_index_per_ns(
602 zebra_ns_lookup(ns_id),
603 index);
8795f904 604 if (ifp)
4a7371e9
DS
605 nh_vrf_id = ifp->vrf_id;
606 else {
9df414fe 607 flog_warn(
e914ccbe 608 EC_ZEBRA_UNKNOWN_INTERFACE,
4a7371e9
DS
609 "%s: Unknown interface %u specified, defaulting to VRF_DEFAULT",
610 __PRETTY_FUNCTION__,
611 index);
612 nh_vrf_id = VRF_DEFAULT;
613 }
614 } else
615 nh_vrf_id = vrf_id;
616
d62a17ae 617 gate = 0;
618 if (rtnh->rtnh_len > sizeof(*rtnh)) {
619 memset(tb, 0, sizeof(tb));
620 netlink_parse_rtattr(
621 tb, RTA_MAX, RTNH_DATA(rtnh),
622 rtnh->rtnh_len - sizeof(*rtnh));
623 if (tb[RTA_GATEWAY])
624 gate = RTA_DATA(
625 tb[RTA_GATEWAY]);
87da6a60
SW
626 if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]
627 && *(uint16_t *)RTA_DATA(
628 tb[RTA_ENCAP_TYPE])
629 == LWTUNNEL_ENCAP_MPLS) {
630 num_labels = parse_encap_mpls(
631 tb[RTA_ENCAP], labels);
632 }
d62a17ae 633 }
634
635 if (gate) {
636 if (rtm->rtm_family == AF_INET) {
637 if (index)
87da6a60 638 nh = route_entry_nexthop_ipv4_ifindex_add(
d62a17ae 639 re, gate,
4a7371e9
DS
640 prefsrc, index,
641 nh_vrf_id);
d62a17ae 642 else
87da6a60 643 nh = route_entry_nexthop_ipv4_add(
d62a17ae 644 re, gate,
4a7371e9
DS
645 prefsrc,
646 nh_vrf_id);
d62a17ae 647 } else if (rtm->rtm_family
648 == AF_INET6) {
649 if (index)
87da6a60 650 nh = route_entry_nexthop_ipv6_ifindex_add(
4a7371e9
DS
651 re, gate, index,
652 nh_vrf_id);
d62a17ae 653 else
87da6a60 654 nh = route_entry_nexthop_ipv6_add(
4a7371e9
DS
655 re, gate,
656 nh_vrf_id);
d62a17ae 657 }
658 } else
87da6a60 659 nh = route_entry_nexthop_ifindex_add(
4a7371e9 660 re, index, nh_vrf_id);
d62a17ae 661
87da6a60
SW
662 if (nh && num_labels)
663 nexthop_add_labels(nh, ZEBRA_LSP_STATIC,
664 num_labels, labels);
665
3c04071d
SW
666 if (rtnh->rtnh_len == 0)
667 break;
668
d62a17ae 669 len -= NLMSG_ALIGN(rtnh->rtnh_len);
670 rtnh = RTNH_NEXT(rtnh);
671 }
672
673 zserv_nexthop_num_warn(__func__,
674 (const struct prefix *)&p,
675 re->nexthop_num);
676 if (re->nexthop_num == 0)
677 XFREE(MTYPE_RE, re);
678 else
1f610a1f
CF
679 rib_add_multipath(afi, SAFI_UNICAST, &p,
680 &src_p, re);
d62a17ae 681 }
682 } else {
fd36be7e
DL
683 if (!tb[RTA_MULTIPATH]) {
684 struct nexthop nh;
685 size_t sz = (afi == AFI_IP) ? 4 : 16;
686
687 memset(&nh, 0, sizeof(nh));
8ba5bd58
RW
688 if (bh_type == BLACKHOLE_UNSPEC) {
689 if (index && !gate)
690 nh.type = NEXTHOP_TYPE_IFINDEX;
691 else if (index && gate)
692 nh.type =
693 (afi == AFI_IP)
694 ? NEXTHOP_TYPE_IPV4_IFINDEX
695 : NEXTHOP_TYPE_IPV6_IFINDEX;
696 else if (!index && gate)
697 nh.type = (afi == AFI_IP)
698 ? NEXTHOP_TYPE_IPV4
60466a63 699 : NEXTHOP_TYPE_IPV6;
8ba5bd58
RW
700 else {
701 nh.type = NEXTHOP_TYPE_BLACKHOLE;
702 nh.bh_type = BLACKHOLE_UNSPEC;
703 }
704 } else {
fd36be7e 705 nh.type = NEXTHOP_TYPE_BLACKHOLE;
8ba5bd58
RW
706 nh.bh_type = bh_type;
707 }
fd36be7e
DL
708 nh.ifindex = index;
709 if (gate)
710 memcpy(&nh.gate, gate, sz);
996c9314 711 rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags,
51c4ed0a
DS
712 &p, &src_p, &nh, table, metric, distance,
713 true);
fd36be7e
DL
714 } else {
715 /* XXX: need to compare the entire list of nexthops
716 * here for NLM_F_APPEND stupidity */
996c9314 717 rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags,
51c4ed0a
DS
718 &p, &src_p, NULL, table, metric, distance,
719 true);
d62a17ae 720 }
721 }
722
723 return 0;
718e3744 724}
725
e3be0432
DS
726static struct mcast_route_data *mroute = NULL;
727
2414abd3 728static int netlink_route_change_read_multicast(struct nlmsghdr *h,
d62a17ae 729 ns_id_t ns_id, int startup)
565fdc75 730{
d62a17ae 731 int len;
732 struct rtmsg *rtm;
733 struct rtattr *tb[RTA_MAX + 1];
734 struct mcast_route_data *m;
735 struct mcast_route_data mr;
736 int iif = 0;
737 int count;
738 int oif[256];
739 int oif_count = 0;
740 char sbuf[40];
741 char gbuf[40];
742 char oif_list[256] = "\0";
78dd30b2 743 vrf_id_t vrf;
43b5cc5e 744 int table;
d62a17ae 745
746 if (mroute)
747 m = mroute;
748 else {
749 memset(&mr, 0, sizeof(mr));
750 m = &mr;
751 }
752
753 rtm = NLMSG_DATA(h);
754
755 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
756
757 memset(tb, 0, sizeof tb);
758 netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len);
90d82769 759
43b5cc5e
DS
760 if (tb[RTA_TABLE])
761 table = *(int *)RTA_DATA(tb[RTA_TABLE]);
762 else
763 table = rtm->rtm_table;
764
78dd30b2 765 vrf = vrf_lookup_by_table(table, ns_id);
43b5cc5e 766
d62a17ae 767 if (tb[RTA_IIF])
768 iif = *(int *)RTA_DATA(tb[RTA_IIF]);
769
770 if (tb[RTA_SRC])
bd8b9272 771 m->sg.src = *(struct in_addr *)RTA_DATA(tb[RTA_SRC]);
d62a17ae 772
773 if (tb[RTA_DST])
bd8b9272 774 m->sg.grp = *(struct in_addr *)RTA_DATA(tb[RTA_DST]);
d62a17ae 775
776 if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES])
777 m->lastused = *(unsigned long long *)RTA_DATA(tb[RTA_EXPIRES]);
778
779 if (tb[RTA_MULTIPATH]) {
780 struct rtnexthop *rtnh =
781 (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
782
783 len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
784 for (;;) {
785 if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len)
786 break;
787
788 oif[oif_count] = rtnh->rtnh_ifindex;
789 oif_count++;
790
3c04071d
SW
791 if (rtnh->rtnh_len == 0)
792 break;
793
d62a17ae 794 len -= NLMSG_ALIGN(rtnh->rtnh_len);
795 rtnh = RTNH_NEXT(rtnh);
796 }
797 }
798
799 if (IS_ZEBRA_DEBUG_KERNEL) {
800 struct interface *ifp;
0af35d90
RW
801 strlcpy(sbuf, inet_ntoa(m->sg.src), sizeof(sbuf));
802 strlcpy(gbuf, inet_ntoa(m->sg.grp), sizeof(gbuf));
d62a17ae 803 for (count = 0; count < oif_count; count++) {
804 ifp = if_lookup_by_index(oif[count], vrf);
805 char temp[256];
806
5b4256ca
DS
807 sprintf(temp, "%s(%d) ", ifp ? ifp->name : "Unknown",
808 oif[count]);
d62a17ae 809 strcat(oif_list, temp);
810 }
43b5cc5e 811 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vrf);
d62a17ae 812 ifp = if_lookup_by_index(iif, vrf);
5b4256ca
DS
813 zlog_debug("MCAST VRF: %s(%d) %s (%s,%s) IIF: %s(%d) OIF: %s jiffies: %lld",
814 zvrf->vrf->name, vrf,
815 nl_msg_type_to_str(h->nlmsg_type),
816 sbuf, gbuf, ifp ? ifp->name : "Unknown", iif,
817 oif_list, m->lastused);
90d82769 818 }
d62a17ae 819 return 0;
565fdc75
DS
820}
821
2414abd3 822int netlink_route_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
565fdc75 823{
d62a17ae 824 int len;
d62a17ae 825 struct rtmsg *rtm;
826
827 rtm = NLMSG_DATA(h);
828
829 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) {
830 /* If this is not route add/delete message print warning. */
87b5d1b0
DS
831 zlog_debug("Kernel message: %s NS %u\n",
832 nl_msg_type_to_str(h->nlmsg_type), ns_id);
d62a17ae 833 return 0;
834 }
835
de1cd6b9 836 if (!(rtm->rtm_family == AF_INET || rtm->rtm_family == AF_INET6)) {
9df414fe 837 flog_warn(
e914ccbe 838 EC_ZEBRA_UNKNOWN_FAMILY,
87b5d1b0
DS
839 "Invalid address family: %u received from kernel route change: %s",
840 rtm->rtm_family, nl_msg_type_to_str(h->nlmsg_type));
8a1b681c
SW
841 return 0;
842 }
843
d62a17ae 844 /* Connected route. */
845 if (IS_ZEBRA_DEBUG_KERNEL)
78dd30b2 846 zlog_debug("%s %s %s proto %s NS %u",
d62a17ae 847 nl_msg_type_to_str(h->nlmsg_type),
848 nl_family_to_str(rtm->rtm_family),
849 nl_rttype_to_str(rtm->rtm_type),
78dd30b2 850 nl_rtproto_to_str(rtm->rtm_protocol), ns_id);
d62a17ae 851
d62a17ae 852
853 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
9bdf8618
DS
854 if (len < 0) {
855 zlog_err("%s: Message received from netlink is of a broken size: %d %zu",
856 __PRETTY_FUNCTION__,
857 h->nlmsg_len,
858 (size_t)NLMSG_LENGTH(sizeof(struct rtmsg)));
d62a17ae 859 return -1;
9bdf8618 860 }
d62a17ae 861
e655a03c 862 if (rtm->rtm_type == RTN_MULTICAST)
2414abd3 863 netlink_route_change_read_multicast(h, ns_id, startup);
e655a03c 864 else
2414abd3 865 netlink_route_change_read_unicast(h, ns_id, startup);
d62a17ae 866 return 0;
565fdc75
DS
867}
868
289602d7 869/* Request for specific route information from the kernel */
d62a17ae 870static int netlink_request_route(struct zebra_ns *zns, int family, int type)
289602d7 871{
d62a17ae 872 struct {
873 struct nlmsghdr n;
874 struct rtmsg rtm;
875 } req;
876
877 /* Form the request, specifying filter (rtattr) if needed. */
878 memset(&req, 0, sizeof(req));
879 req.n.nlmsg_type = type;
880 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
881 req.rtm.rtm_family = family;
882
883 return netlink_request(&zns->netlink_cmd, &req.n);
289602d7 884}
885
718e3744 886/* Routing table read function using netlink interface. Only called
887 bootstrap time. */
d62a17ae 888int netlink_route_read(struct zebra_ns *zns)
718e3744 889{
d62a17ae 890 int ret;
891
892 /* Get IPv4 routing table. */
893 ret = netlink_request_route(zns, AF_INET, RTM_GETROUTE);
894 if (ret < 0)
895 return ret;
896 ret = netlink_parse_info(netlink_route_change_read_unicast,
897 &zns->netlink_cmd, zns, 0, 1);
898 if (ret < 0)
899 return ret;
900
901 /* Get IPv6 routing table. */
902 ret = netlink_request_route(zns, AF_INET6, RTM_GETROUTE);
903 if (ret < 0)
904 return ret;
905 ret = netlink_parse_info(netlink_route_change_read_unicast,
906 &zns->netlink_cmd, zns, 0, 1);
907 if (ret < 0)
908 return ret;
909
910 return 0;
718e3744 911}
912
d7c0a89a
QY
913static void _netlink_route_nl_add_gateway_info(uint8_t route_family,
914 uint8_t gw_family,
d62a17ae 915 struct nlmsghdr *nlmsg,
916 size_t req_size, int bytelen,
917 struct nexthop *nexthop)
40c7bdb0 918{
d62a17ae 919 if (route_family == AF_MPLS) {
920 struct gw_family_t gw_fam;
921
922 gw_fam.family = gw_family;
923 if (gw_family == AF_INET)
924 memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
925 else
926 memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
927 addattr_l(nlmsg, req_size, RTA_VIA, &gw_fam.family,
928 bytelen + 2);
929 } else {
930 if (gw_family == AF_INET)
931 addattr_l(nlmsg, req_size, RTA_GATEWAY,
932 &nexthop->gate.ipv4, bytelen);
933 else
934 addattr_l(nlmsg, req_size, RTA_GATEWAY,
935 &nexthop->gate.ipv6, bytelen);
936 }
40c7bdb0 937}
938
d7c0a89a
QY
939static void _netlink_route_rta_add_gateway_info(uint8_t route_family,
940 uint8_t gw_family,
d62a17ae 941 struct rtattr *rta,
942 struct rtnexthop *rtnh,
943 size_t req_size, int bytelen,
944 struct nexthop *nexthop)
40c7bdb0 945{
d62a17ae 946 if (route_family == AF_MPLS) {
947 struct gw_family_t gw_fam;
948
949 gw_fam.family = gw_family;
950 if (gw_family == AF_INET)
951 memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
952 else
953 memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
954 rta_addattr_l(rta, req_size, RTA_VIA, &gw_fam.family,
955 bytelen + 2);
956 rtnh->rtnh_len += RTA_LENGTH(bytelen + 2);
957 } else {
958 if (gw_family == AF_INET)
959 rta_addattr_l(rta, req_size, RTA_GATEWAY,
960 &nexthop->gate.ipv4, bytelen);
961 else
962 rta_addattr_l(rta, req_size, RTA_GATEWAY,
963 &nexthop->gate.ipv6, bytelen);
964 rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
965 }
40c7bdb0 966}
967
fa713d9e
CF
968/* This function takes a nexthop as argument and adds
969 * the appropriate netlink attributes to an existing
970 * netlink message.
971 *
972 * @param routedesc: Human readable description of route type
973 * (direct/recursive, single-/multipath)
974 * @param bytelen: Length of addresses in bytes.
975 * @param nexthop: Nexthop information
976 * @param nlmsg: nlmsghdr structure to fill in.
977 * @param req_size: The size allocated for the message.
978 */
d62a17ae 979static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
980 struct nexthop *nexthop,
981 struct nlmsghdr *nlmsg,
982 struct rtmsg *rtmsg,
983 size_t req_size, int cmd)
fa713d9e 984{
8ecdb26e 985 struct mpls_label_stack *nh_label;
d62a17ae 986 mpls_lse_t out_lse[MPLS_MAX_LABELS];
fa712963 987 int num_labels = 0;
9a62e84b 988 char label_buf[256];
d62a17ae 989
990 /*
991 * label_buf is *only* currently used within debugging.
992 * As such when we assign it we are guarding it inside
993 * a debug test. If you want to change this make sure
994 * you fix this assumption
995 */
996 label_buf[0] = '\0';
d62a17ae 997
fa712963
RW
998 assert(nexthop);
999 for (struct nexthop *nh = nexthop; nh; nh = nh->rparent) {
d62a17ae 1000 char label_buf1[20];
1001
fa712963
RW
1002 nh_label = nh->nh_label;
1003 if (!nh_label || !nh_label->num_labels)
1004 continue;
1005
1006 for (int i = 0; i < nh_label->num_labels; i++) {
1007 if (nh_label->label[i] == MPLS_LABEL_IMPLICIT_NULL)
1008 continue;
1009
1010 if (IS_ZEBRA_DEBUG_KERNEL) {
1011 if (!num_labels)
1012 sprintf(label_buf, "label %u",
1013 nh_label->label[i]);
1014 else {
1015 sprintf(label_buf1, "/%u",
1016 nh_label->label[i]);
1017 strlcat(label_buf, label_buf1,
1018 sizeof(label_buf));
d62a17ae 1019 }
d62a17ae 1020 }
fa712963
RW
1021
1022 out_lse[num_labels] =
1023 mpls_lse_encode(nh_label->label[i], 0, 0, 0);
1024 num_labels++;
d62a17ae 1025 }
fa712963
RW
1026 }
1027
1028 if (num_labels) {
1029 /* Set the BoS bit */
1030 out_lse[num_labels - 1] |= htonl(1 << MPLS_LS_S_SHIFT);
1031
1032 if (rtmsg->rtm_family == AF_MPLS)
1033 addattr_l(nlmsg, req_size, RTA_NEWDST, &out_lse,
1034 num_labels * sizeof(mpls_lse_t));
1035 else {
1036 struct rtattr *nest;
d7c0a89a 1037 uint16_t encap = LWTUNNEL_ENCAP_MPLS;
fa712963
RW
1038
1039 addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE, &encap,
d7c0a89a 1040 sizeof(uint16_t));
fa712963
RW
1041 nest = addattr_nest(nlmsg, req_size, RTA_ENCAP);
1042 addattr_l(nlmsg, req_size, MPLS_IPTUNNEL_DST, &out_lse,
1043 num_labels * sizeof(mpls_lse_t));
1044 addattr_nest_end(nlmsg, nest);
66d42727 1045 }
0aabccc0 1046 }
fa713d9e 1047
d62a17ae 1048 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1049 rtmsg->rtm_flags |= RTNH_F_ONLINK;
1050
1051 if (rtmsg->rtm_family == AF_INET
1052 && (nexthop->type == NEXTHOP_TYPE_IPV6
1053 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) {
1054 rtmsg->rtm_flags |= RTNH_F_ONLINK;
1055 addattr_l(nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4);
1056 addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1057
1058 if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
1059 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1060 &nexthop->rmap_src.ipv4, bytelen);
1061 else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
1062 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1063 &nexthop->src.ipv4, bytelen);
1064
1065 if (IS_ZEBRA_DEBUG_KERNEL)
1066 zlog_debug(
1067 " 5549: _netlink_route_build_singlepath() (%s): "
7556c3fd 1068 "nexthop via %s %s if %u(%u)",
d62a17ae 1069 routedesc, ipv4_ll_buf, label_buf,
7556c3fd 1070 nexthop->ifindex, nexthop->vrf_id);
d62a17ae 1071 return;
0aabccc0
DD
1072 }
1073
d62a17ae 1074 if (nexthop->type == NEXTHOP_TYPE_IPV4
1075 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
1076 /* Send deletes to the kernel without specifying the next-hop */
1077 if (cmd != RTM_DELROUTE)
1078 _netlink_route_nl_add_gateway_info(
1079 rtmsg->rtm_family, AF_INET, nlmsg, req_size,
1080 bytelen, nexthop);
1081
1082 if (cmd == RTM_NEWROUTE) {
1083 if (nexthop->rmap_src.ipv4.s_addr)
1084 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1085 &nexthop->rmap_src.ipv4, bytelen);
1086 else if (nexthop->src.ipv4.s_addr)
1087 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1088 &nexthop->src.ipv4, bytelen);
1089 }
1090
1091 if (IS_ZEBRA_DEBUG_KERNEL)
1092 zlog_debug(
1093 "netlink_route_multipath() (%s): "
7556c3fd 1094 "nexthop via %s %s if %u(%u)",
d62a17ae 1095 routedesc, inet_ntoa(nexthop->gate.ipv4),
7556c3fd 1096 label_buf, nexthop->ifindex, nexthop->vrf_id);
0aabccc0 1097 }
fa713d9e 1098
d62a17ae 1099 if (nexthop->type == NEXTHOP_TYPE_IPV6
1100 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
1101 _netlink_route_nl_add_gateway_info(rtmsg->rtm_family, AF_INET6,
1102 nlmsg, req_size, bytelen,
1103 nexthop);
1104
1105 if (cmd == RTM_NEWROUTE) {
1106 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
1107 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1108 &nexthop->rmap_src.ipv6, bytelen);
1109 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
1110 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1111 &nexthop->src.ipv6, bytelen);
1112 }
fa713d9e 1113
d62a17ae 1114 if (IS_ZEBRA_DEBUG_KERNEL)
1115 zlog_debug(
1116 "netlink_route_multipath() (%s): "
7556c3fd 1117 "nexthop via %s %s if %u(%u)",
d62a17ae 1118 routedesc, inet6_ntoa(nexthop->gate.ipv6),
7556c3fd 1119 label_buf, nexthop->ifindex, nexthop->vrf_id);
d62a17ae 1120 }
5e210522
DS
1121
1122 /*
1123 * We have the ifindex so we should always send it
1124 * This is especially useful if we are doing route
1125 * leaking.
1126 */
1127 if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
d62a17ae 1128 addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1129
5e210522
DS
1130 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1131 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
d62a17ae 1132 if (cmd == RTM_NEWROUTE) {
1133 if (nexthop->rmap_src.ipv4.s_addr)
1134 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1135 &nexthop->rmap_src.ipv4, bytelen);
1136 else if (nexthop->src.ipv4.s_addr)
1137 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1138 &nexthop->src.ipv4, bytelen);
1139 }
fa713d9e 1140
d62a17ae 1141 if (IS_ZEBRA_DEBUG_KERNEL)
1142 zlog_debug(
1143 "netlink_route_multipath() (%s): "
7556c3fd
DS
1144 "nexthop via if %u(%u)",
1145 routedesc, nexthop->ifindex, nexthop->vrf_id);
0aabccc0
DD
1146 }
1147
d62a17ae 1148 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
d62a17ae 1149 if (cmd == RTM_NEWROUTE) {
1150 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
1151 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1152 &nexthop->rmap_src.ipv6, bytelen);
1153 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
1154 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1155 &nexthop->src.ipv6, bytelen);
1156 }
1157
1158 if (IS_ZEBRA_DEBUG_KERNEL)
1159 zlog_debug(
1160 "netlink_route_multipath() (%s): "
7556c3fd
DS
1161 "nexthop via if %u(%u)",
1162 routedesc, nexthop->ifindex, nexthop->vrf_id);
d62a17ae 1163 }
fa713d9e
CF
1164}
1165
1166/* This function takes a nexthop as argument and
1167 * appends to the given rtattr/rtnexthop pair the
1168 * representation of the nexthop. If the nexthop
1169 * defines a preferred source, the src parameter
1170 * will be modified to point to that src, otherwise
1171 * it will be kept unmodified.
1172 *
1173 * @param routedesc: Human readable description of route type
1174 * (direct/recursive, single-/multipath)
1175 * @param bytelen: Length of addresses in bytes.
1176 * @param nexthop: Nexthop information
1177 * @param rta: rtnetlink attribute structure
1178 * @param rtnh: pointer to an rtnetlink nexthop structure
1179 * @param src: pointer pointing to a location where
1180 * the prefsrc should be stored.
1181 */
d62a17ae 1182static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
1183 struct nexthop *nexthop,
1184 struct rtattr *rta,
1185 struct rtnexthop *rtnh,
1186 struct rtmsg *rtmsg,
1187 union g_addr **src)
fa713d9e 1188{
8ecdb26e 1189 struct mpls_label_stack *nh_label;
d62a17ae 1190 mpls_lse_t out_lse[MPLS_MAX_LABELS];
fa712963 1191 int num_labels = 0;
9a62e84b 1192 char label_buf[256];
d62a17ae 1193
1194 rtnh->rtnh_len = sizeof(*rtnh);
1195 rtnh->rtnh_flags = 0;
1196 rtnh->rtnh_hops = 0;
1197 rta->rta_len += rtnh->rtnh_len;
1198
1199 /*
1200 * label_buf is *only* currently used within debugging.
1201 * As such when we assign it we are guarding it inside
1202 * a debug test. If you want to change this make sure
1203 * you fix this assumption
1204 */
1205 label_buf[0] = '\0';
d62a17ae 1206
fa712963
RW
1207 assert(nexthop);
1208 for (struct nexthop *nh = nexthop; nh; nh = nh->rparent) {
d62a17ae 1209 char label_buf1[20];
1210
fa712963
RW
1211 nh_label = nh->nh_label;
1212 if (!nh_label || !nh_label->num_labels)
1213 continue;
1214
1215 for (int i = 0; i < nh_label->num_labels; i++) {
1216 if (nh_label->label[i] == MPLS_LABEL_IMPLICIT_NULL)
1217 continue;
1218
1219 if (IS_ZEBRA_DEBUG_KERNEL) {
1220 if (!num_labels)
1221 sprintf(label_buf, "label %u",
1222 nh_label->label[i]);
1223 else {
1224 sprintf(label_buf1, "/%u",
1225 nh_label->label[i]);
1226 strlcat(label_buf, label_buf1,
1227 sizeof(label_buf));
d62a17ae 1228 }
d62a17ae 1229 }
fa712963
RW
1230
1231 out_lse[num_labels] =
1232 mpls_lse_encode(nh_label->label[i], 0, 0, 0);
1233 num_labels++;
d62a17ae 1234 }
fa712963
RW
1235 }
1236
1237 if (num_labels) {
1238 /* Set the BoS bit */
1239 out_lse[num_labels - 1] |= htonl(1 << MPLS_LS_S_SHIFT);
1240
1241 if (rtmsg->rtm_family == AF_MPLS) {
1242 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_NEWDST,
1243 &out_lse,
1244 num_labels * sizeof(mpls_lse_t));
1245 rtnh->rtnh_len +=
1246 RTA_LENGTH(num_labels * sizeof(mpls_lse_t));
1247 } else {
1248 struct rtattr *nest;
d7c0a89a 1249 uint16_t encap = LWTUNNEL_ENCAP_MPLS;
fa712963
RW
1250 int len = rta->rta_len;
1251
1252 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_ENCAP_TYPE,
d7c0a89a 1253 &encap, sizeof(uint16_t));
fa712963
RW
1254 nest = rta_nest(rta, NL_PKT_BUF_SIZE, RTA_ENCAP);
1255 rta_addattr_l(rta, NL_PKT_BUF_SIZE, MPLS_IPTUNNEL_DST,
1256 &out_lse,
1257 num_labels * sizeof(mpls_lse_t));
1258 rta_nest_end(rta, nest);
1259 rtnh->rtnh_len += rta->rta_len - len;
66d42727 1260 }
d62a17ae 1261 }
1262
1263 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1264 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1265
1266 if (rtmsg->rtm_family == AF_INET
1267 && (nexthop->type == NEXTHOP_TYPE_IPV6
1268 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) {
1269 bytelen = 4;
1270 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1271 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_GATEWAY, &ipv4_ll,
1272 bytelen);
1273 rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
1274 rtnh->rtnh_ifindex = nexthop->ifindex;
1275
1276 if (nexthop->rmap_src.ipv4.s_addr)
1277 *src = &nexthop->rmap_src;
1278 else if (nexthop->src.ipv4.s_addr)
1279 *src = &nexthop->src;
1280
1281 if (IS_ZEBRA_DEBUG_KERNEL)
1282 zlog_debug(
1283 " 5549: netlink_route_build_multipath() (%s): "
1284 "nexthop via %s %s if %u",
1285 routedesc, ipv4_ll_buf, label_buf,
1286 nexthop->ifindex);
1287 return;
1288 }
1289
1290 if (nexthop->type == NEXTHOP_TYPE_IPV4
1291 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
1292 _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET,
1293 rta, rtnh, NL_PKT_BUF_SIZE,
1294 bytelen, nexthop);
1295 if (nexthop->rmap_src.ipv4.s_addr)
1296 *src = &nexthop->rmap_src;
1297 else if (nexthop->src.ipv4.s_addr)
1298 *src = &nexthop->src;
1299
1300 if (IS_ZEBRA_DEBUG_KERNEL)
1301 zlog_debug(
1302 "netlink_route_multipath() (%s): "
1303 "nexthop via %s %s if %u",
1304 routedesc, inet_ntoa(nexthop->gate.ipv4),
1305 label_buf, nexthop->ifindex);
1306 }
1307 if (nexthop->type == NEXTHOP_TYPE_IPV6
1308 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
1309 _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET6,
1310 rta, rtnh, NL_PKT_BUF_SIZE,
1311 bytelen, nexthop);
1312
1313 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
1314 *src = &nexthop->rmap_src;
1315 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
1316 *src = &nexthop->src;
1317
1318 if (IS_ZEBRA_DEBUG_KERNEL)
1319 zlog_debug(
1320 "netlink_route_multipath() (%s): "
1321 "nexthop via %s %s if %u",
1322 routedesc, inet6_ntoa(nexthop->gate.ipv6),
1323 label_buf, nexthop->ifindex);
1324 }
5e210522
DS
1325
1326 /*
1327 * We have figured out the ifindex so we should always send it
1328 * This is especially useful if we are doing route
1329 * leaking.
1330 */
1331 if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
1332 rtnh->rtnh_ifindex = nexthop->ifindex;
1333
d62a17ae 1334 /* ifindex */
1335 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1336 || nexthop->type == NEXTHOP_TYPE_IFINDEX) {
d62a17ae 1337 if (nexthop->rmap_src.ipv4.s_addr)
1338 *src = &nexthop->rmap_src;
1339 else if (nexthop->src.ipv4.s_addr)
1340 *src = &nexthop->src;
1341
1342 if (IS_ZEBRA_DEBUG_KERNEL)
1343 zlog_debug(
1344 "netlink_route_multipath() (%s): "
1345 "nexthop via if %u",
1346 routedesc, nexthop->ifindex);
d62a17ae 1347 }
fa713d9e
CF
1348}
1349
d62a17ae 1350static inline void _netlink_mpls_build_singlepath(const char *routedesc,
1351 zebra_nhlfe_t *nhlfe,
1352 struct nlmsghdr *nlmsg,
1353 struct rtmsg *rtmsg,
1354 size_t req_size, int cmd)
40c7bdb0 1355{
d62a17ae 1356 int bytelen;
d7c0a89a 1357 uint8_t family;
40c7bdb0 1358
d62a17ae 1359 family = NHLFE_FAMILY(nhlfe);
1360 bytelen = (family == AF_INET ? 4 : 16);
1361 _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop,
1362 nlmsg, rtmsg, req_size, cmd);
40c7bdb0 1363}
1364
1365
1366static inline void
d62a17ae 1367_netlink_mpls_build_multipath(const char *routedesc, zebra_nhlfe_t *nhlfe,
1368 struct rtattr *rta, struct rtnexthop *rtnh,
1369 struct rtmsg *rtmsg, union g_addr **src)
40c7bdb0 1370{
d62a17ae 1371 int bytelen;
d7c0a89a 1372 uint8_t family;
40c7bdb0 1373
d62a17ae 1374 family = NHLFE_FAMILY(nhlfe);
1375 bytelen = (family == AF_INET ? 4 : 16);
1376 _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop, rta,
1377 rtnh, rtmsg, src);
40c7bdb0 1378}
1379
1380
fa713d9e
CF
1381/* Log debug information for netlink_route_multipath
1382 * if debug logging is enabled.
1383 *
1384 * @param cmd: Netlink command which is to be processed
1385 * @param p: Prefix for which the change is due
fa713d9e 1386 * @param family: Address family which the change concerns
45df4e96
DS
1387 * @param zvrf: The vrf we are in
1388 * @param tableid: The table we are working on
fa713d9e 1389 */
86391e56
MS
1390static void _netlink_route_debug(int cmd, const struct prefix *p,
1391 int family, vrf_id_t vrfid,
7556c3fd 1392 uint32_t tableid)
fa713d9e 1393{
d62a17ae 1394 if (IS_ZEBRA_DEBUG_KERNEL) {
1395 char buf[PREFIX_STRLEN];
1396 zlog_debug(
45df4e96
DS
1397 "netlink_route_multipath(): %s %s vrf %u(%u)",
1398 nl_msg_type_to_str(cmd),
1399 prefix2str(p, buf, sizeof(buf)),
86391e56 1400 vrfid, tableid);
d62a17ae 1401 }
1402}
1403
d7c0a89a 1404static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc)
40c7bdb0 1405{
d62a17ae 1406 if (IS_ZEBRA_DEBUG_KERNEL)
1407 zlog_debug("netlink_mpls_multipath() (%s): %s %u/20", routedesc,
1408 nl_msg_type_to_str(cmd), label);
fa713d9e
CF
1409}
1410
d62a17ae 1411static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
5895d33f 1412 int llalen, ns_id_t ns_id)
5c610faf 1413{
d62a17ae 1414 struct {
1415 struct nlmsghdr n;
1416 struct ndmsg ndm;
1417 char buf[256];
1418 } req;
5c610faf 1419
5895d33f 1420 struct zebra_ns *zns = zebra_ns_lookup(ns_id);
8f7d9fc0 1421
5605ecfc 1422 memset(&req, 0, sizeof(req));
5c610faf 1423
d62a17ae 1424 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1425 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1426 req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
1427 req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
a55ba23f 1428
d62a17ae 1429 req.ndm.ndm_family = AF_INET;
1430 req.ndm.ndm_state = NUD_PERMANENT;
1431 req.ndm.ndm_ifindex = ifindex;
1432 req.ndm.ndm_type = RTN_UNICAST;
5c610faf 1433
d62a17ae 1434 addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
1435 addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
5c610faf 1436
d62a17ae 1437 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
1438 0);
5c610faf
DS
1439}
1440
718e3744 1441/* Routing table change via netlink interface. */
6ae24471 1442/* Update flag indicates whether this is a "replace" or not. */
86391e56
MS
1443static int netlink_route_multipath(int cmd, const struct prefix *p,
1444 const struct prefix *src_p,
1445 struct route_entry *re,
d62a17ae 1446 int update)
718e3744 1447{
d62a17ae 1448 int bytelen;
1449 struct sockaddr_nl snl;
1450 struct nexthop *nexthop = NULL;
1451 unsigned int nexthop_num;
d62a17ae 1452 int family = PREFIX_FAMILY(p);
1453 const char *routedesc;
1454 int setsrc = 0;
1455 union g_addr src;
1456
1457 struct {
1458 struct nlmsghdr n;
1459 struct rtmsg r;
1460 char buf[NL_PKT_BUF_SIZE];
1461 } req;
1462
9a76375f 1463 struct zebra_ns *zns;
d62a17ae 1464 struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
1465
009f8ad5 1466 zns = zvrf->zns;
d62a17ae 1467 memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE);
1468
1469 bytelen = (family == AF_INET ? 4 : 16);
1470
1471 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1472 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1473 if ((cmd == RTM_NEWROUTE) && update)
1474 req.n.nlmsg_flags |= NLM_F_REPLACE;
1475 req.n.nlmsg_type = cmd;
1476 req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
1477
1478 req.r.rtm_family = family;
1479 req.r.rtm_dst_len = p->prefixlen;
1480 req.r.rtm_src_len = src_p ? src_p->prefixlen : 0;
915902cb 1481 req.r.rtm_protocol = zebra2proto(re->type);
d62a17ae 1482 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
c766824c
DS
1483
1484 /*
1485 * blackhole routes are not RTN_UNICAST, they are
1486 * RTN_ BLACKHOLE|UNREACHABLE|PROHIBIT
1487 * so setting this value as a RTN_UNICAST would
1488 * cause the route lookup of just the prefix
1489 * to fail. So no need to specify this for
1490 * the RTM_DELROUTE case
1491 */
1492 if (cmd != RTM_DELROUTE)
1493 req.r.rtm_type = RTN_UNICAST;
d62a17ae 1494
d62a17ae 1495 addattr_l(&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1496 if (src_p)
1497 addattr_l(&req.n, sizeof req, RTA_SRC, &src_p->u.prefix,
1498 bytelen);
1499
1500 /* Metric. */
1501 /* Hardcode the metric for all routes coming from zebra. Metric isn't
1502 * used
1503 * either by the kernel or by zebra. Its purely for calculating best
1504 * path(s)
1505 * by the routing protocol and for communicating with protocol peers.
1506 */
1507 addattr32(&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
4e40b6d6
KK
1508#if defined(SUPPORT_REALMS)
1509 if (re->tag > 0 && re->tag <= 255)
1510 addattr32(&req.n, sizeof req, RTA_FLOW, re->tag);
1511#endif
d62a17ae 1512 /* Table corresponding to this route. */
1513 if (re->table < 256)
1514 req.r.rtm_table = re->table;
1515 else {
1516 req.r.rtm_table = RT_TABLE_UNSPEC;
1517 addattr32(&req.n, sizeof req, RTA_TABLE, re->table);
0aabccc0 1518 }
718e3744 1519
86391e56 1520 _netlink_route_debug(cmd, p, family, zvrf_id(zvrf), re->table);
45df4e96 1521
c1d63a93
DS
1522 /*
1523 * If we are not updating the route and we have received
1524 * a route delete, then all we need to fill in is the
1525 * prefix information to tell the kernel to schwack
1526 * it.
1527 */
1528 if (!update && cmd == RTM_DELROUTE)
a8309422
DL
1529 goto skip;
1530
d62a17ae 1531 if (re->mtu || re->nexthop_mtu) {
1532 char buf[NL_PKT_BUF_SIZE];
1533 struct rtattr *rta = (void *)buf;
d7c0a89a 1534 uint32_t mtu = re->mtu;
d62a17ae 1535 if (!mtu || (re->nexthop_mtu && re->nexthop_mtu < mtu))
1536 mtu = re->nexthop_mtu;
1537 rta->rta_type = RTA_METRICS;
1538 rta->rta_len = RTA_LENGTH(0);
1539 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu);
1540 addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA(rta),
1541 RTA_PAYLOAD(rta));
1542 }
1543
d62a17ae 1544 /* Count overall nexthops so we can decide whether to use singlepath
1545 * or multipath case. */
1546 nexthop_num = 0;
7ee30f28 1547 for (ALL_NEXTHOPS(re->ng, nexthop)) {
d62a17ae 1548 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1549 continue;
996c9314 1550 if (cmd == RTM_NEWROUTE && !NEXTHOP_IS_ACTIVE(nexthop->flags))
d62a17ae 1551 continue;
1552 if (cmd == RTM_DELROUTE
1553 && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
1554 continue;
1555
1556 nexthop_num++;
1557 }
1558
1559 /* Singlepath case. */
1560 if (nexthop_num == 1 || multipath_num == 1) {
1561 nexthop_num = 0;
7ee30f28 1562 for (ALL_NEXTHOPS(re->ng, nexthop)) {
1f1d24a8
DS
1563 /*
1564 * So we want to cover 2 types of blackhole
1565 * routes here:
1566 * 1) A normal blackhole route( ala from a static
1567 * install.
1568 * 2) A recursively resolved blackhole route
1569 */
1570 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
1571 switch (nexthop->bh_type) {
1572 case BLACKHOLE_ADMINPROHIB:
1573 req.r.rtm_type = RTN_PROHIBIT;
1574 break;
1575 case BLACKHOLE_REJECT:
1576 req.r.rtm_type = RTN_UNREACHABLE;
1577 break;
1578 default:
1579 req.r.rtm_type = RTN_BLACKHOLE;
1580 break;
1581 }
1582 goto skip;
1583 }
d62a17ae 1584 if (CHECK_FLAG(nexthop->flags,
1585 NEXTHOP_FLAG_RECURSIVE)) {
1586 if (!setsrc) {
1587 if (family == AF_INET) {
1588 if (nexthop->rmap_src.ipv4
1589 .s_addr
1590 != 0) {
1591 src.ipv4 =
1592 nexthop->rmap_src
1593 .ipv4;
1594 setsrc = 1;
1595 } else if (nexthop->src.ipv4
1596 .s_addr
1597 != 0) {
1598 src.ipv4 =
1599 nexthop->src
1600 .ipv4;
1601 setsrc = 1;
1602 }
1603 } else if (family == AF_INET6) {
1604 if (!IN6_IS_ADDR_UNSPECIFIED(
1605 &nexthop->rmap_src
1606 .ipv6)) {
1607 src.ipv6 =
1608 nexthop->rmap_src
1609 .ipv6;
1610 setsrc = 1;
1611 } else if (
1612 !IN6_IS_ADDR_UNSPECIFIED(
1613 &nexthop->src
1614 .ipv6)) {
1615 src.ipv6 =
1616 nexthop->src
1617 .ipv6;
1618 setsrc = 1;
1619 }
1620 }
1621 }
1622 continue;
1623 }
1624
1625 if ((cmd == RTM_NEWROUTE
25b9cb0c 1626 && NEXTHOP_IS_ACTIVE(nexthop->flags))
d62a17ae 1627 || (cmd == RTM_DELROUTE
1628 && CHECK_FLAG(nexthop->flags,
1629 NEXTHOP_FLAG_FIB))) {
1630 routedesc = nexthop->rparent
8b1450b9
RW
1631 ? "recursive, single-path"
1632 : "single-path";
d62a17ae 1633
d62a17ae 1634 _netlink_route_build_singlepath(
1635 routedesc, bytelen, nexthop, &req.n,
1636 &req.r, sizeof req, cmd);
1637 nexthop_num++;
1638 break;
1639 }
1640 }
1641 if (setsrc && (cmd == RTM_NEWROUTE)) {
1642 if (family == AF_INET)
1643 addattr_l(&req.n, sizeof req, RTA_PREFSRC,
1644 &src.ipv4, bytelen);
1645 else if (family == AF_INET6)
1646 addattr_l(&req.n, sizeof req, RTA_PREFSRC,
1647 &src.ipv6, bytelen);
1648 }
1649 } else {
1650 char buf[NL_PKT_BUF_SIZE];
1651 struct rtattr *rta = (void *)buf;
1652 struct rtnexthop *rtnh;
1653 union g_addr *src1 = NULL;
1654
1655 rta->rta_type = RTA_MULTIPATH;
1656 rta->rta_len = RTA_LENGTH(0);
1657 rtnh = RTA_DATA(rta);
1658
1659 nexthop_num = 0;
7ee30f28 1660 for (ALL_NEXTHOPS(re->ng, nexthop)) {
d62a17ae 1661 if (nexthop_num >= multipath_num)
1662 break;
1663
1664 if (CHECK_FLAG(nexthop->flags,
1665 NEXTHOP_FLAG_RECURSIVE)) {
1666 /* This only works for IPv4 now */
1667 if (!setsrc) {
1668 if (family == AF_INET) {
1669 if (nexthop->rmap_src.ipv4
1670 .s_addr
1671 != 0) {
1672 src.ipv4 =
1673 nexthop->rmap_src
1674 .ipv4;
1675 setsrc = 1;
1676 } else if (nexthop->src.ipv4
1677 .s_addr
1678 != 0) {
1679 src.ipv4 =
1680 nexthop->src
1681 .ipv4;
1682 setsrc = 1;
1683 }
1684 } else if (family == AF_INET6) {
1685 if (!IN6_IS_ADDR_UNSPECIFIED(
1686 &nexthop->rmap_src
1687 .ipv6)) {
1688 src.ipv6 =
1689 nexthop->rmap_src
1690 .ipv6;
1691 setsrc = 1;
1692 } else if (
1693 !IN6_IS_ADDR_UNSPECIFIED(
1694 &nexthop->src
1695 .ipv6)) {
1696 src.ipv6 =
1697 nexthop->src
1698 .ipv6;
1699 setsrc = 1;
1700 }
1701 }
1702 }
1703 continue;
1704 }
1705
1706 if ((cmd == RTM_NEWROUTE
25b9cb0c 1707 && NEXTHOP_IS_ACTIVE(nexthop->flags))
d62a17ae 1708 || (cmd == RTM_DELROUTE
1709 && CHECK_FLAG(nexthop->flags,
1710 NEXTHOP_FLAG_FIB))) {
1711 routedesc = nexthop->rparent
8b1450b9
RW
1712 ? "recursive, multipath"
1713 : "multipath";
d62a17ae 1714 nexthop_num++;
1715
d62a17ae 1716 _netlink_route_build_multipath(
1717 routedesc, bytelen, nexthop, rta, rtnh,
1718 &req.r, &src1);
1719 rtnh = RTNH_NEXT(rtnh);
1720
1721 if (!setsrc && src1) {
1722 if (family == AF_INET)
1723 src.ipv4 = src1->ipv4;
1724 else if (family == AF_INET6)
1725 src.ipv6 = src1->ipv6;
1726
1727 setsrc = 1;
1728 }
1729 }
1730 }
1731 if (setsrc && (cmd == RTM_NEWROUTE)) {
1732 if (family == AF_INET)
1733 addattr_l(&req.n, sizeof req, RTA_PREFSRC,
1734 &src.ipv4, bytelen);
1735 else if (family == AF_INET6)
1736 addattr_l(&req.n, sizeof req, RTA_PREFSRC,
1737 &src.ipv6, bytelen);
1738 if (IS_ZEBRA_DEBUG_KERNEL)
1739 zlog_debug("Setting source");
1740 }
1741
1742 if (rta->rta_len > RTA_LENGTH(0))
1743 addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH,
1744 RTA_DATA(rta), RTA_PAYLOAD(rta));
1745 }
718e3744 1746
d62a17ae 1747 /* If there is no useful nexthop then return. */
1748 if (nexthop_num == 0) {
1749 if (IS_ZEBRA_DEBUG_KERNEL)
1750 zlog_debug(
1751 "netlink_route_multipath(): No useful nexthop.");
1752 return 0;
1753 }
718e3744 1754
7021c425 1755skip:
718e3744 1756
d62a17ae 1757 /* Destination netlink address. */
1758 memset(&snl, 0, sizeof snl);
1759 snl.nl_family = AF_NETLINK;
718e3744 1760
d62a17ae 1761 /* Talk to netlink socket. */
1762 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
1763 0);
718e3744 1764}
1765
43b5cc5e 1766int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
e3be0432 1767{
d62a17ae 1768 int suc = 0;
1769 struct mcast_route_data *mr = (struct mcast_route_data *)in;
bd8b9272
DS
1770 struct {
1771 struct nlmsghdr n;
1772 struct ndmsg ndm;
1773 char buf[256];
1774 } req;
e3be0432 1775
d62a17ae 1776 mroute = mr;
5895d33f 1777 struct zebra_ns *zns;
bd8b9272 1778
009f8ad5 1779 zns = zvrf->zns;
5605ecfc 1780 memset(&req, 0, sizeof(req));
bd8b9272
DS
1781
1782 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1783 req.n.nlmsg_flags = NLM_F_REQUEST;
1784 req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
1785
1786 req.ndm.ndm_family = RTNL_FAMILY_IPMR;
1787 req.n.nlmsg_type = RTM_GETROUTE;
1788
1789 addattr_l(&req.n, sizeof(req), RTA_IIF, &mroute->ifindex, 4);
1790 addattr_l(&req.n, sizeof(req), RTA_OIF, &mroute->ifindex, 4);
1791 addattr_l(&req.n, sizeof(req), RTA_SRC, &mroute->sg.src.s_addr, 4);
1792 addattr_l(&req.n, sizeof(req), RTA_DST, &mroute->sg.grp.s_addr, 4);
1793 addattr_l(&req.n, sizeof(req), RTA_TABLE, &zvrf->table_id, 4);
e3be0432 1794
bd8b9272
DS
1795 suc = netlink_talk(netlink_route_change_read_multicast, &req.n,
1796 &zns->netlink_cmd, zns, 0);
e3be0432 1797
bd8b9272 1798 mroute = NULL;
d62a17ae 1799 return suc;
e3be0432
DS
1800}
1801
1e885672 1802enum dp_req_result kernel_route_rib(struct route_node *rn,
86391e56
MS
1803 const struct prefix *p,
1804 const struct prefix *src_p,
215181cb
DS
1805 struct route_entry *old,
1806 struct route_entry *new)
718e3744 1807{
0c555cc6
DS
1808 int ret = 0;
1809
0af35d90
RW
1810 assert(old || new);
1811
0c555cc6 1812 if (new) {
6b093863 1813 if (p->family == AF_INET || v6_rr_semantics)
0c555cc6
DS
1814 ret = netlink_route_multipath(RTM_NEWROUTE, p, src_p,
1815 new, (old) ? 1 : 0);
1816 else {
1817 /*
1818 * So v6 route replace semantics are not in
1819 * the kernel at this point as I understand it.
1820 * So let's do a delete than an add.
1821 * In the future once v6 route replace semantics
1822 * are in we can figure out what to do here to
1823 * allow working with old and new kernels.
1824 *
1825 * I'm also intentionally ignoring the failure case
1826 * of the route delete. If that happens yeah we're
1827 * screwed.
1828 */
1829 if (old)
996c9314
LB
1830 netlink_route_multipath(RTM_DELROUTE, p, src_p,
1831 old, 0);
1832 ret = netlink_route_multipath(RTM_NEWROUTE, p, src_p,
1833 new, 0);
0c555cc6 1834 }
7d974ba3 1835 kernel_route_rib_pass_fail(rn, p, new,
215181cb
DS
1836 (!ret) ? DP_INSTALL_SUCCESS
1837 : DP_INSTALL_FAILURE);
1e885672 1838 return DP_REQUEST_SUCCESS;
0c555cc6 1839 }
718e3744 1840
0c555cc6
DS
1841 if (old) {
1842 ret = netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0);
e7fcb843 1843
7d974ba3 1844 kernel_route_rib_pass_fail(rn, p, old,
215181cb
DS
1845 (!ret) ? DP_DELETE_SUCCESS
1846 : DP_DELETE_FAILURE);
0c555cc6 1847 }
215181cb 1848
1e885672 1849 return DP_REQUEST_SUCCESS;
718e3744 1850}
1851
d62a17ae 1852int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
5895d33f 1853 int llalen, ns_id_t ns_id)
6b8a5694 1854{
d62a17ae 1855 return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex,
5895d33f 1856 addr, lla, llalen, ns_id);
6b8a5694 1857}
718e3744 1858
13d60d35 1859/*
1860 * Add remote VTEP to the flood list for this VxLAN interface (VNI). This
1861 * is done by adding an FDB entry with a MAC of 00:00:00:00:00:00.
1862 */
d62a17ae 1863static int netlink_vxlan_flood_list_update(struct interface *ifp,
1864 struct in_addr *vtep_ip, int cmd)
13d60d35 1865{
5895d33f 1866 struct zebra_ns *zns;
d62a17ae 1867 struct {
1868 struct nlmsghdr n;
1869 struct ndmsg ndm;
1870 char buf[256];
1871 } req;
d7c0a89a 1872 uint8_t dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
009f8ad5 1873 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
d62a17ae 1874
009f8ad5 1875 zns = zvrf->zns;
5605ecfc 1876 memset(&req, 0, sizeof(req));
d62a17ae 1877
1878 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1879 req.n.nlmsg_flags = NLM_F_REQUEST;
1880 if (cmd == RTM_NEWNEIGH)
1881 req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_APPEND);
1882 req.n.nlmsg_type = cmd;
1883 req.ndm.ndm_family = PF_BRIDGE;
1884 req.ndm.ndm_state = NUD_NOARP | NUD_PERMANENT;
1885 req.ndm.ndm_flags |= NTF_SELF; // Handle by "self", not "master"
1886
1887
1888 addattr_l(&req.n, sizeof(req), NDA_LLADDR, &dst_mac, 6);
1889 req.ndm.ndm_ifindex = ifp->ifindex;
1890 addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip->s_addr, 4);
1891
1892 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
1893 0);
13d60d35 1894}
1895
1896/*
d62a17ae 1897 * Add remote VTEP for this VxLAN interface (VNI). In Linux, this involves
1898 * adding
13d60d35 1899 * a "flood" MAC FDB entry.
1900 */
d62a17ae 1901int kernel_add_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
13d60d35 1902{
d62a17ae 1903 if (IS_ZEBRA_DEBUG_VXLAN)
1904 zlog_debug("Install %s into flood list for VNI %u intf %s(%u)",
1905 inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex);
13d60d35 1906
d62a17ae 1907 return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_NEWNEIGH);
13d60d35 1908}
1909
1910/*
1911 * Remove remote VTEP for this VxLAN interface (VNI). In Linux, this involves
1912 * deleting the "flood" MAC FDB entry.
1913 */
d62a17ae 1914int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
13d60d35 1915{
d62a17ae 1916 if (IS_ZEBRA_DEBUG_VXLAN)
1917 zlog_debug(
1918 "Uninstall %s from flood list for VNI %u intf %s(%u)",
1919 inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex);
13d60d35 1920
d62a17ae 1921 return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_DELNEIGH);
13d60d35 1922}
1923
2232a77c 1924#ifndef NDA_RTA
d62a17ae 1925#define NDA_RTA(r) \
1926 ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
2232a77c 1927#endif
1928
2414abd3 1929static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
2232a77c 1930{
d62a17ae 1931 struct ndmsg *ndm;
1932 struct interface *ifp;
1933 struct zebra_if *zif;
d62a17ae 1934 struct rtattr *tb[NDA_MAX + 1];
1935 struct interface *br_if;
1936 struct ethaddr mac;
1937 vlanid_t vid = 0;
1938 struct prefix vtep_ip;
1939 int vid_present = 0, dst_present = 0;
1940 char buf[ETHER_ADDR_STRLEN];
1941 char vid_buf[20];
1942 char dst_buf[30];
d7c0a89a 1943 uint8_t sticky = 0;
d62a17ae 1944
1945 ndm = NLMSG_DATA(h);
1946
2853fed6 1947 /* We only process macfdb notifications if EVPN is enabled */
1948 if (!is_evpn_enabled())
1949 return 0;
1950
d62a17ae 1951 /* The interface should exist. */
5895d33f 1952 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
d62a17ae 1953 ndm->ndm_ifindex);
2853fed6 1954 if (!ifp || !ifp->info)
d62a17ae 1955 return 0;
1956
1957 /* The interface should be something we're interested in. */
1958 if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
1959 return 0;
1960
1961 /* Drop "permanent" entries. */
1962 if (ndm->ndm_state & NUD_PERMANENT)
1963 return 0;
1964
1965 zif = (struct zebra_if *)ifp->info;
1966 if ((br_if = zif->brslave_info.br_if) == NULL) {
9df414fe
QY
1967 zlog_debug("%s family %s IF %s(%u) brIF %u - no bridge master",
1968 nl_msg_type_to_str(h->nlmsg_type),
1969 nl_family_to_str(ndm->ndm_family), ifp->name,
1970 ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex);
d62a17ae 1971 return 0;
1972 }
1973
1974 /* Parse attributes and extract fields of interest. */
1975 memset(tb, 0, sizeof tb);
1976 netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
1977
1978 if (!tb[NDA_LLADDR]) {
9df414fe
QY
1979 zlog_debug("%s family %s IF %s(%u) brIF %u - no LLADDR",
1980 nl_msg_type_to_str(h->nlmsg_type),
1981 nl_family_to_str(ndm->ndm_family), ifp->name,
1982 ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex);
d62a17ae 1983 return 0;
1984 }
1985
ff8b7eb8 1986 if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
9df414fe 1987 zlog_debug(
df0b13cf 1988 "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %lu",
d62a17ae 1989 nl_msg_type_to_str(h->nlmsg_type),
1990 nl_family_to_str(ndm->ndm_family), ifp->name,
1991 ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex,
df0b13cf 1992 (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR]));
d62a17ae 1993 return 0;
1994 }
1995
ff8b7eb8 1996 memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETH_ALEN);
d62a17ae 1997
1998 if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN]) {
1999 vid_present = 1;
d7c0a89a 2000 vid = *(uint16_t *)RTA_DATA(tb[NDA_VLAN]);
d62a17ae 2001 sprintf(vid_buf, " VLAN %u", vid);
2002 }
2003
2004 if (tb[NDA_DST]) {
2005 /* TODO: Only IPv4 supported now. */
2006 dst_present = 1;
2007 vtep_ip.family = AF_INET;
2008 vtep_ip.prefixlen = IPV4_MAX_BITLEN;
2009 memcpy(&(vtep_ip.u.prefix4.s_addr), RTA_DATA(tb[NDA_DST]),
2010 IPV4_MAX_BYTELEN);
2011 sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip.u.prefix4));
2012 }
2013
2014 sticky = (ndm->ndm_state & NUD_NOARP) ? 1 : 0;
2015
2016 if (IS_ZEBRA_DEBUG_KERNEL)
2017 zlog_debug("Rx %s family %s IF %s(%u)%s %sMAC %s%s",
2018 nl_msg_type_to_str(h->nlmsg_type),
2019 nl_family_to_str(ndm->ndm_family), ifp->name,
2020 ndm->ndm_ifindex, vid_present ? vid_buf : "",
2021 sticky ? "sticky " : "",
2022 prefix_mac2str(&mac, buf, sizeof(buf)),
2023 dst_present ? dst_buf : "");
2024
2025 if (filter_vlan && vid != filter_vlan)
2026 return 0;
2027
2028 /* If add or update, do accordingly if learnt on a "local" interface; if
2029 * the notification is over VxLAN, this has to be related to
2030 * multi-homing,
2031 * so perform an implicit delete of any local entry (if it exists).
2032 */
2033 if (h->nlmsg_type == RTM_NEWNEIGH) {
2034 /* Drop "permanent" entries. */
2035 if (ndm->ndm_state & NUD_PERMANENT)
2036 return 0;
2037
2038 if (IS_ZEBRA_IF_VXLAN(ifp))
2039 return zebra_vxlan_check_del_local_mac(ifp, br_if, &mac,
2040 vid);
2041
2042 return zebra_vxlan_local_mac_add_update(ifp, br_if, &mac, vid,
2043 sticky);
2044 }
2045
2046 /* This is a delete notification.
2047 * 1. For a MAC over VxLan, check if it needs to be refreshed(readded)
2048 * 2. For a MAC over "local" interface, delete the mac
2049 * Note: We will get notifications from both bridge driver and VxLAN
2050 * driver.
2051 * Ignore the notification from VxLan driver as it is also generated
2052 * when mac moves from remote to local.
2053 */
2054 if (dst_present)
2055 return 0;
2056
2057 if (IS_ZEBRA_IF_VXLAN(ifp))
2058 return zebra_vxlan_check_readd_remote_mac(ifp, br_if, &mac,
2059 vid);
2060
2061 return zebra_vxlan_local_mac_del(ifp, br_if, &mac, vid);
2232a77c 2062}
2063
2414abd3 2064static int netlink_macfdb_table(struct nlmsghdr *h, ns_id_t ns_id, int startup)
2232a77c 2065{
d62a17ae 2066 int len;
2067 struct ndmsg *ndm;
2232a77c 2068
d62a17ae 2069 if (h->nlmsg_type != RTM_NEWNEIGH)
2070 return 0;
2232a77c 2071
d62a17ae 2072 /* Length validity. */
2073 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
2074 if (len < 0)
2075 return -1;
2232a77c 2076
d62a17ae 2077 /* We are interested only in AF_BRIDGE notifications. */
2078 ndm = NLMSG_DATA(h);
2079 if (ndm->ndm_family != AF_BRIDGE)
2080 return 0;
2232a77c 2081
2414abd3 2082 return netlink_macfdb_change(h, len, ns_id);
2232a77c 2083}
2084
2085/* Request for MAC FDB information from the kernel */
d62a17ae 2086static int netlink_request_macs(struct zebra_ns *zns, int family, int type,
2087 ifindex_t master_ifindex)
2232a77c 2088{
d62a17ae 2089 struct {
2090 struct nlmsghdr n;
2091 struct ifinfomsg ifm;
2092 char buf[256];
2093 } req;
2094
2095 /* Form the request, specifying filter (rtattr) if needed. */
2096 memset(&req, 0, sizeof(req));
2097 req.n.nlmsg_type = type;
2098 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
2099 req.ifm.ifi_family = family;
2100 if (master_ifindex)
2101 addattr32(&req.n, sizeof(req), IFLA_MASTER, master_ifindex);
2102
2103 return netlink_request(&zns->netlink_cmd, &req.n);
2232a77c 2104}
2105
2106/*
2107 * MAC forwarding database read using netlink interface. This is invoked
2108 * at startup.
2109 */
d62a17ae 2110int netlink_macfdb_read(struct zebra_ns *zns)
2232a77c 2111{
d62a17ae 2112 int ret;
2113
2114 /* Get bridge FDB table. */
2115 ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH, 0);
2116 if (ret < 0)
2117 return ret;
2118 /* We are reading entire table. */
2119 filter_vlan = 0;
2120 ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns,
2121 0, 1);
2122
2123 return ret;
2232a77c 2124}
2125
2126/*
2127 * MAC forwarding database read using netlink interface. This is for a
2128 * specific bridge and matching specific access VLAN (if VLAN-aware bridge).
2129 */
d62a17ae 2130int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
2131 struct interface *br_if)
2232a77c 2132{
d62a17ae 2133 struct zebra_if *br_zif;
2134 struct zebra_if *zif;
2135 struct zebra_l2info_vxlan *vxl;
2136 int ret = 0;
2137
2138
2139 /* Save VLAN we're filtering on, if needed. */
2140 br_zif = (struct zebra_if *)br_if->info;
2141 zif = (struct zebra_if *)ifp->info;
2142 vxl = &zif->l2info.vxl;
2143 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
2144 filter_vlan = vxl->access_vlan;
2145
2146 /* Get bridge FDB table for specific bridge - we do the VLAN filtering.
2147 */
2148 ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH,
2149 br_if->ifindex);
2150 if (ret < 0)
2151 return ret;
2152 ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns,
2153 0, 0);
2154
2155 /* Reset VLAN filter. */
2156 filter_vlan = 0;
2157 return ret;
2232a77c 2158}
2159
d62a17ae 2160static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
2161 struct ethaddr *mac, struct in_addr vtep_ip,
d7c0a89a 2162 int local, int cmd, uint8_t sticky)
2232a77c 2163{
5895d33f 2164 struct zebra_ns *zns;
d62a17ae 2165 struct {
2166 struct nlmsghdr n;
2167 struct ndmsg ndm;
2168 char buf[256];
2169 } req;
2170 int dst_alen;
2171 struct zebra_if *zif;
2172 struct interface *br_if;
2173 struct zebra_if *br_zif;
2174 char buf[ETHER_ADDR_STRLEN];
2175 int vid_present = 0, dst_present = 0;
2176 char vid_buf[20];
2177 char dst_buf[30];
009f8ad5 2178 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
d62a17ae 2179
009f8ad5 2180 zns = zvrf->zns;
d62a17ae 2181 zif = ifp->info;
2182 if ((br_if = zif->brslave_info.br_if) == NULL) {
9df414fe
QY
2183 zlog_debug("MAC %s on IF %s(%u) - no mapping to bridge",
2184 (cmd == RTM_NEWNEIGH) ? "add" : "del", ifp->name,
2185 ifp->ifindex);
d62a17ae 2186 return -1;
2187 }
2188
5605ecfc 2189 memset(&req, 0, sizeof(req));
d62a17ae 2190
2191 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
2192 req.n.nlmsg_flags = NLM_F_REQUEST;
2193 if (cmd == RTM_NEWNEIGH)
2194 req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
2195 req.n.nlmsg_type = cmd;
2196 req.ndm.ndm_family = AF_BRIDGE;
2197 req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
2198 req.ndm.ndm_state = NUD_REACHABLE;
2199
2200 if (sticky)
2201 req.ndm.ndm_state |= NUD_NOARP;
2202 else
2203 req.ndm.ndm_flags |= NTF_EXT_LEARNED;
2204
2205 addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
2206 req.ndm.ndm_ifindex = ifp->ifindex;
2207 if (!local) {
2208 dst_alen = 4; // TODO: hardcoded
2209 addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen);
2210 dst_present = 1;
2211 sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip));
2212 }
2213 br_zif = (struct zebra_if *)br_if->info;
2214 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) {
2215 addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
2216 vid_present = 1;
2217 sprintf(vid_buf, " VLAN %u", vid);
2218 }
2219 addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
2220
2221 if (IS_ZEBRA_DEBUG_KERNEL)
2222 zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
2223 nl_msg_type_to_str(cmd),
2224 nl_family_to_str(req.ndm.ndm_family), ifp->name,
2225 ifp->ifindex, vid_present ? vid_buf : "",
2226 sticky ? "sticky " : "",
2227 prefix_mac2str(mac, buf, sizeof(buf)),
2228 dst_present ? dst_buf : "");
2229
2230 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
2231 0);
2232a77c 2232}
2233
d62a17ae 2234#define NUD_VALID \
2235 (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE \
2236 | NUD_DELAY)
2232a77c 2237
2414abd3 2238static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
2232a77c 2239{
d62a17ae 2240 struct ndmsg *ndm;
2241 struct interface *ifp;
2242 struct zebra_if *zif;
d62a17ae 2243 struct rtattr *tb[NDA_MAX + 1];
2244 struct interface *link_if;
2245 struct ethaddr mac;
2246 struct ipaddr ip;
2247 char buf[ETHER_ADDR_STRLEN];
2248 char buf2[INET6_ADDRSTRLEN];
2249 int mac_present = 0;
d7c0a89a 2250 uint8_t ext_learned;
68e33151 2251 uint8_t router_flag;
d62a17ae 2252
2253 ndm = NLMSG_DATA(h);
2254
2255 /* The interface should exist. */
5895d33f 2256 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
d62a17ae 2257 ndm->ndm_ifindex);
2853fed6 2258 if (!ifp || !ifp->info)
d62a17ae 2259 return 0;
2260
20089ae2
DS
2261 zif = (struct zebra_if *)ifp->info;
2262
2263 /* Parse attributes and extract fields of interest. */
2264 memset(tb, 0, sizeof tb);
2265 netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
2266
2267 if (!tb[NDA_DST]) {
9df414fe
QY
2268 zlog_debug("%s family %s IF %s(%u) - no DST",
2269 nl_msg_type_to_str(h->nlmsg_type),
2270 nl_family_to_str(ndm->ndm_family), ifp->name,
2271 ndm->ndm_ifindex);
d62a17ae 2272 return 0;
20089ae2
DS
2273 }
2274
2275 memset(&ip, 0, sizeof(struct ipaddr));
2276 ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6;
2277 memcpy(&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
2278
2279 /* Drop some "permanent" entries. */
2280 if (ndm->ndm_state & NUD_PERMANENT) {
c683bd44 2281 char b[16] = "169.254.0.1";
20089ae2
DS
2282 struct in_addr ipv4_ll;
2283
2284 if (ndm->ndm_family != AF_INET)
2285 return 0;
2286
2287 if (!zif->v6_2_v4_ll_neigh_entry)
2288 return 0;
2289
2290 if (h->nlmsg_type != RTM_DELNEIGH)
2291 return 0;
2292
c683bd44 2293 inet_pton(AF_INET, b, &ipv4_ll);
20089ae2
DS
2294 if (ipv4_ll.s_addr != ip.ip._v4_addr.s_addr)
2295 return 0;
2296
2297 if_nbr_ipv6ll_to_ipv4ll_neigh_update(
2298 ifp, &zif->v6_2_v4_ll_addr6, true);
2299 return 0;
2300 }
d62a17ae 2301
d62a17ae 2302 /* The neighbor is present on an SVI. From this, we locate the
2303 * underlying
2304 * bridge because we're only interested in neighbors on a VxLAN bridge.
2305 * The bridge is located based on the nature of the SVI:
2306 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN
2307 * interface
2308 * and is linked to the bridge
2309 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge
2310 * inteface
2311 * itself
2312 */
2313 if (IS_ZEBRA_IF_VLAN(ifp)) {
5895d33f 2314 link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
71349e03 2315 zif->link_ifindex);
d62a17ae 2316 if (!link_if)
2317 return 0;
2318 } else if (IS_ZEBRA_IF_BRIDGE(ifp))
2319 link_if = ifp;
2320 else
2321 return 0;
2322
d62a17ae 2323 memset(&mac, 0, sizeof(struct ethaddr));
d62a17ae 2324 if (h->nlmsg_type == RTM_NEWNEIGH) {
2325 if (tb[NDA_LLADDR]) {
ff8b7eb8 2326 if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
9df414fe 2327 zlog_debug(
df0b13cf 2328 "%s family %s IF %s(%u) - LLADDR is not MAC, len %lu",
d62a17ae 2329 nl_msg_type_to_str(h->nlmsg_type),
2330 nl_family_to_str(ndm->ndm_family),
2331 ifp->name, ndm->ndm_ifindex,
996c9314
LB
2332 (unsigned long)RTA_PAYLOAD(
2333 tb[NDA_LLADDR]));
d62a17ae 2334 return 0;
2335 }
2336
2337 mac_present = 1;
ff8b7eb8 2338 memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETH_ALEN);
d62a17ae 2339 }
2340
2341 ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0;
68e33151 2342 router_flag = (ndm->ndm_flags & NTF_ROUTER) ? 1 : 0;
d62a17ae 2343
2344 if (IS_ZEBRA_DEBUG_KERNEL)
2345 zlog_debug(
2346 "Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x",
2347 nl_msg_type_to_str(h->nlmsg_type),
2348 nl_family_to_str(ndm->ndm_family), ifp->name,
2349 ndm->ndm_ifindex,
2350 ipaddr2str(&ip, buf2, sizeof(buf2)),
2351 mac_present
2352 ? prefix_mac2str(&mac, buf, sizeof(buf))
2353 : "",
2354 ndm->ndm_state, ndm->ndm_flags);
2355
2356 /* If the neighbor state is valid for use, process as an add or
2357 * update
2358 * else process as a delete. Note that the delete handling may
2359 * result
2360 * in re-adding the neighbor if it is a valid "remote" neighbor.
2361 */
2362 if (ndm->ndm_state & NUD_VALID)
ee69da27 2363 return zebra_vxlan_handle_kernel_neigh_update(
d62a17ae 2364 ifp, link_if, &ip, &mac, ndm->ndm_state,
68e33151 2365 ext_learned, router_flag);
d62a17ae 2366
ee69da27 2367 return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
d62a17ae 2368 }
2369
2370 if (IS_ZEBRA_DEBUG_KERNEL)
2371 zlog_debug("Rx %s family %s IF %s(%u) IP %s",
2372 nl_msg_type_to_str(h->nlmsg_type),
2373 nl_family_to_str(ndm->ndm_family), ifp->name,
2374 ndm->ndm_ifindex,
2375 ipaddr2str(&ip, buf2, sizeof(buf2)));
2376
2377 /* Process the delete - it may result in re-adding the neighbor if it is
2378 * a valid "remote" neighbor.
2379 */
ee69da27 2380 return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
2232a77c 2381}
2382
2414abd3 2383static int netlink_neigh_table(struct nlmsghdr *h, ns_id_t ns_id, int startup)
2232a77c 2384{
d62a17ae 2385 int len;
2386 struct ndmsg *ndm;
2232a77c 2387
d62a17ae 2388 if (h->nlmsg_type != RTM_NEWNEIGH)
2389 return 0;
2232a77c 2390
d62a17ae 2391 /* Length validity. */
2392 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
2393 if (len < 0)
2394 return -1;
2232a77c 2395
d62a17ae 2396 /* We are interested only in AF_INET or AF_INET6 notifications. */
2397 ndm = NLMSG_DATA(h);
2398 if (ndm->ndm_family != AF_INET && ndm->ndm_family != AF_INET6)
2399 return 0;
2232a77c 2400
2414abd3 2401 return netlink_neigh_change(h, len);
2232a77c 2402}
2403
2404/* Request for IP neighbor information from the kernel */
d62a17ae 2405static int netlink_request_neigh(struct zebra_ns *zns, int family, int type,
2406 ifindex_t ifindex)
2232a77c 2407{
d62a17ae 2408 struct {
2409 struct nlmsghdr n;
2410 struct ndmsg ndm;
2411 char buf[256];
2412 } req;
2413
2414 /* Form the request, specifying filter (rtattr) if needed. */
2415 memset(&req, 0, sizeof(req));
2416 req.n.nlmsg_type = type;
2417 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
2418 req.ndm.ndm_family = family;
2419 if (ifindex)
2420 addattr32(&req.n, sizeof(req), NDA_IFINDEX, ifindex);
2421
2422 return netlink_request(&zns->netlink_cmd, &req.n);
2232a77c 2423}
2424
2425/*
2426 * IP Neighbor table read using netlink interface. This is invoked
2427 * at startup.
2428 */
d62a17ae 2429int netlink_neigh_read(struct zebra_ns *zns)
2232a77c 2430{
d62a17ae 2431 int ret;
2232a77c 2432
d62a17ae 2433 /* Get IP neighbor table. */
2434 ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH, 0);
2435 if (ret < 0)
2436 return ret;
2437 ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0,
2438 1);
2232a77c 2439
d62a17ae 2440 return ret;
2232a77c 2441}
2442
2443/*
2444 * IP Neighbor table read using netlink interface. This is for a specific
2445 * VLAN device.
2446 */
d62a17ae 2447int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
2232a77c 2448{
d62a17ae 2449 int ret = 0;
2232a77c 2450
d62a17ae 2451 ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH,
2452 vlan_if->ifindex);
2453 if (ret < 0)
2454 return ret;
2455 ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0,
2456 0);
2232a77c 2457
d62a17ae 2458 return ret;
2232a77c 2459}
2460
2414abd3 2461int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
2232a77c 2462{
d62a17ae 2463 int len;
2464 struct ndmsg *ndm;
2232a77c 2465
d62a17ae 2466 if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH))
2467 return 0;
2232a77c 2468
d62a17ae 2469 /* Length validity. */
2470 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
9bdf8618
DS
2471 if (len < 0) {
2472 zlog_err("%s: Message received from netlink is of a broken size %d %zu",
2473 __PRETTY_FUNCTION__, h->nlmsg_len,
2474 (size_t)NLMSG_LENGTH(sizeof(struct ndmsg)));
d62a17ae 2475 return -1;
9bdf8618 2476 }
2232a77c 2477
d62a17ae 2478 /* Is this a notification for the MAC FDB or IP neighbor table? */
2479 ndm = NLMSG_DATA(h);
2480 if (ndm->ndm_family == AF_BRIDGE)
2414abd3 2481 return netlink_macfdb_change(h, len, ns_id);
2232a77c 2482
d62a17ae 2483 if (ndm->ndm_type != RTN_UNICAST)
2484 return 0;
2232a77c 2485
d62a17ae 2486 if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6)
2414abd3 2487 return netlink_ipneigh_change(h, len, ns_id);
8a1b681c 2488 else {
9df414fe 2489 flog_warn(
e914ccbe 2490 EC_ZEBRA_UNKNOWN_FAMILY,
87b5d1b0
DS
2491 "Invalid address family: %u received from kernel neighbor change: %s",
2492 ndm->ndm_family, nl_msg_type_to_str(h->nlmsg_type));
8a1b681c
SW
2493 return 0;
2494 }
2232a77c 2495
d62a17ae 2496 return 0;
2232a77c 2497}
2498
d62a17ae 2499static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
68e33151
CS
2500 struct ethaddr *mac, uint8_t flags,
2501 uint16_t state, int cmd)
2232a77c 2502{
d62a17ae 2503 struct {
2504 struct nlmsghdr n;
2505 struct ndmsg ndm;
2506 char buf[256];
2507 } req;
2508 int ipa_len;
2509
5895d33f 2510 struct zebra_ns *zns;
d62a17ae 2511 char buf[INET6_ADDRSTRLEN];
2512 char buf2[ETHER_ADDR_STRLEN];
009f8ad5 2513 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
d62a17ae 2514
009f8ad5 2515 zns = zvrf->zns;
5605ecfc 2516 memset(&req, 0, sizeof(req));
d62a17ae 2517
2518 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
2519 req.n.nlmsg_flags = NLM_F_REQUEST;
2520 if (cmd == RTM_NEWNEIGH)
2521 req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
2522 req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
2523 req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
68e33151 2524 req.ndm.ndm_state = state;
d62a17ae 2525 req.ndm.ndm_ifindex = ifp->ifindex;
2526 req.ndm.ndm_type = RTN_UNICAST;
68e33151 2527 req.ndm.ndm_flags = flags;
d62a17ae 2528
2529 ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
2530 addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
2531 if (mac)
2532 addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
2533
2534 if (IS_ZEBRA_DEBUG_KERNEL)
68e33151 2535 zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s flags 0x%x",
d62a17ae 2536 nl_msg_type_to_str(cmd),
2537 nl_family_to_str(req.ndm.ndm_family), ifp->name,
2538 ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)),
2539 mac ? prefix_mac2str(mac, buf2, sizeof(buf2))
68e33151 2540 : "null", flags);
d62a17ae 2541
2542 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
2543 0);
2232a77c 2544}
2545
d62a17ae 2546int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
d7c0a89a 2547 struct in_addr vtep_ip, uint8_t sticky)
2232a77c 2548{
d62a17ae 2549 return netlink_macfdb_update(ifp, vid, mac, vtep_ip, 0, RTM_NEWNEIGH,
2550 sticky);
2232a77c 2551}
2552
d62a17ae 2553int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
2554 struct in_addr vtep_ip, int local)
2232a77c 2555{
d62a17ae 2556 return netlink_macfdb_update(ifp, vid, mac, vtep_ip, local,
2557 RTM_DELNEIGH, 0);
2232a77c 2558}
2559
d62a17ae 2560int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
68e33151 2561 struct ethaddr *mac, uint8_t flags)
2232a77c 2562{
68e33151
CS
2563 return netlink_neigh_update2(ifp, ip, mac, flags,
2564 NUD_NOARP, RTM_NEWNEIGH);
2232a77c 2565}
2566
d62a17ae 2567int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip)
2232a77c 2568{
68e33151 2569 return netlink_neigh_update2(ifp, ip, NULL, 0, 0, RTM_DELNEIGH);
2232a77c 2570}
2571
40c7bdb0 2572/*
2573 * MPLS label forwarding table change via netlink interface.
2574 */
d62a17ae 2575int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
40c7bdb0 2576{
d62a17ae 2577 mpls_lse_t lse;
2578 zebra_nhlfe_t *nhlfe;
2579 struct nexthop *nexthop = NULL;
2580 unsigned int nexthop_num;
2581 const char *routedesc;
2582 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
805444ce 2583 int route_type;
d62a17ae 2584
2585 struct {
2586 struct nlmsghdr n;
2587 struct rtmsg r;
2588 char buf[NL_PKT_BUF_SIZE];
2589 } req;
2590
2591 memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE);
2592
d62a17ae 2593 /*
2594 * Count # nexthops so we can decide whether to use singlepath
2595 * or multipath case.
2596 */
2597 nexthop_num = 0;
2598 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
2599 nexthop = nhlfe->nexthop;
2600 if (!nexthop)
2601 continue;
2602 if (cmd == RTM_NEWROUTE) {
2603 /* Count all selected NHLFEs */
2604 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
2605 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
2606 nexthop_num++;
2607 } else /* DEL */
2608 {
2609 /* Count all installed NHLFEs */
2610 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)
2611 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
2612 nexthop_num++;
2613 }
2614 }
2615
8dc8a4b6 2616 if ((nexthop_num == 0) || (!lsp->best_nhlfe && (cmd != RTM_DELROUTE)))
d62a17ae 2617 return 0;
2618
2619 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
2620 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
2621 req.n.nlmsg_type = cmd;
2622 req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
2623
2624 req.r.rtm_family = AF_MPLS;
2625 req.r.rtm_table = RT_TABLE_MAIN;
2626 req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
d62a17ae 2627 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
2628 req.r.rtm_type = RTN_UNICAST;
2629
8dc8a4b6 2630 if (cmd == RTM_NEWROUTE) {
d62a17ae 2631 /* We do a replace to handle update. */
2632 req.n.nlmsg_flags |= NLM_F_REPLACE;
2633
8dc8a4b6
DS
2634 /* set the protocol value if installing */
2635 route_type = re_type_from_lsp_type(lsp->best_nhlfe->type);
2636 req.r.rtm_protocol = zebra2proto(route_type);
2637 }
2638
d62a17ae 2639 /* Fill destination */
2640 lse = mpls_lse_encode(lsp->ile.in_label, 0, 0, 1);
2641 addattr_l(&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t));
2642
2643 /* Fill nexthops (paths) based on single-path or multipath. The paths
2644 * chosen depend on the operation.
2645 */
2646 if (nexthop_num == 1 || multipath_num == 1) {
8b1450b9 2647 routedesc = "single-path";
d62a17ae 2648 _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
2649
2650 nexthop_num = 0;
2651 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
2652 nexthop = nhlfe->nexthop;
2653 if (!nexthop)
2654 continue;
2655
2656 if ((cmd == RTM_NEWROUTE
2657 && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
2658 && CHECK_FLAG(nexthop->flags,
2659 NEXTHOP_FLAG_ACTIVE)))
2660 || (cmd == RTM_DELROUTE
2661 && (CHECK_FLAG(nhlfe->flags,
2662 NHLFE_FLAG_INSTALLED)
2663 && CHECK_FLAG(nexthop->flags,
2664 NEXTHOP_FLAG_FIB)))) {
2665 /* Add the gateway */
2666 _netlink_mpls_build_singlepath(routedesc, nhlfe,
2667 &req.n, &req.r,
2668 sizeof req, cmd);
d62a17ae 2669 nexthop_num++;
2670 break;
2671 }
2672 }
2673 } else /* Multipath case */
2674 {
2675 char buf[NL_PKT_BUF_SIZE];
2676 struct rtattr *rta = (void *)buf;
2677 struct rtnexthop *rtnh;
2678 union g_addr *src1 = NULL;
2679
2680 rta->rta_type = RTA_MULTIPATH;
2681 rta->rta_len = RTA_LENGTH(0);
2682 rtnh = RTA_DATA(rta);
2683
8b1450b9 2684 routedesc = "multipath";
d62a17ae 2685 _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
2686
2687 nexthop_num = 0;
2688 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
2689 nexthop = nhlfe->nexthop;
2690 if (!nexthop)
2691 continue;
2692
2693 if (nexthop_num >= multipath_num)
2694 break;
2695
2696 if ((cmd == RTM_NEWROUTE
2697 && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
2698 && CHECK_FLAG(nexthop->flags,
2699 NEXTHOP_FLAG_ACTIVE)))
2700 || (cmd == RTM_DELROUTE
2701 && (CHECK_FLAG(nhlfe->flags,
2702 NHLFE_FLAG_INSTALLED)
2703 && CHECK_FLAG(nexthop->flags,
2704 NEXTHOP_FLAG_FIB)))) {
2705 nexthop_num++;
2706
2707 /* Build the multipath */
2708 _netlink_mpls_build_multipath(routedesc, nhlfe,
2709 rta, rtnh, &req.r,
2710 &src1);
2711 rtnh = RTNH_NEXT(rtnh);
d62a17ae 2712 }
2713 }
2714
2715 /* Add the multipath */
2716 if (rta->rta_len > RTA_LENGTH(0))
2717 addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH,
2718 RTA_DATA(rta), RTA_PAYLOAD(rta));
2719 }
2720
2721 /* Talk to netlink socket. */
2722 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
2723 0);
40c7bdb0 2724}
ddfeb486 2725#endif /* HAVE_NETLINK */