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