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