]> git.proxmox.com Git - mirror_frr.git/blame - zebra/rt_netlink.c
*: fix assorted issues detected by Coverity Scan
[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;
0af35d90
RW
561 strlcpy(sbuf, inet_ntoa(m->sg.src), sizeof(sbuf));
562 strlcpy(gbuf, inet_ntoa(m->sg.grp), sizeof(gbuf));
d62a17ae 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{
0af35d90
RW
1556 assert(old || new);
1557
d62a17ae 1558 if (!old && new)
1559 return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 0);
1560 if (old && !new)
1561 return netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0);
718e3744 1562
d62a17ae 1563 return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 1);
718e3744 1564}
1565
d62a17ae 1566int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
1567 int llalen)
6b8a5694 1568{
d62a17ae 1569 return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex,
1570 addr, lla, llalen);
6b8a5694 1571}
718e3744 1572
13d60d35 1573/*
1574 * Add remote VTEP to the flood list for this VxLAN interface (VNI). This
1575 * is done by adding an FDB entry with a MAC of 00:00:00:00:00:00.
1576 */
d62a17ae 1577static int netlink_vxlan_flood_list_update(struct interface *ifp,
1578 struct in_addr *vtep_ip, int cmd)
13d60d35 1579{
d62a17ae 1580 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
1581 struct {
1582 struct nlmsghdr n;
1583 struct ndmsg ndm;
1584 char buf[256];
1585 } req;
1586 u_char dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
1587
1588 memset(&req.n, 0, sizeof(req.n));
1589 memset(&req.ndm, 0, sizeof(req.ndm));
1590
1591 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1592 req.n.nlmsg_flags = NLM_F_REQUEST;
1593 if (cmd == RTM_NEWNEIGH)
1594 req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_APPEND);
1595 req.n.nlmsg_type = cmd;
1596 req.ndm.ndm_family = PF_BRIDGE;
1597 req.ndm.ndm_state = NUD_NOARP | NUD_PERMANENT;
1598 req.ndm.ndm_flags |= NTF_SELF; // Handle by "self", not "master"
1599
1600
1601 addattr_l(&req.n, sizeof(req), NDA_LLADDR, &dst_mac, 6);
1602 req.ndm.ndm_ifindex = ifp->ifindex;
1603 addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip->s_addr, 4);
1604
1605 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
1606 0);
13d60d35 1607}
1608
1609/*
d62a17ae 1610 * Add remote VTEP for this VxLAN interface (VNI). In Linux, this involves
1611 * adding
13d60d35 1612 * a "flood" MAC FDB entry.
1613 */
d62a17ae 1614int kernel_add_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
13d60d35 1615{
d62a17ae 1616 if (IS_ZEBRA_DEBUG_VXLAN)
1617 zlog_debug("Install %s into flood list for VNI %u intf %s(%u)",
1618 inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex);
13d60d35 1619
d62a17ae 1620 return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_NEWNEIGH);
13d60d35 1621}
1622
1623/*
1624 * Remove remote VTEP for this VxLAN interface (VNI). In Linux, this involves
1625 * deleting the "flood" MAC FDB entry.
1626 */
d62a17ae 1627int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
13d60d35 1628{
d62a17ae 1629 if (IS_ZEBRA_DEBUG_VXLAN)
1630 zlog_debug(
1631 "Uninstall %s from flood list for VNI %u intf %s(%u)",
1632 inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex);
13d60d35 1633
d62a17ae 1634 return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_DELNEIGH);
13d60d35 1635}
1636
2232a77c 1637#ifndef NDA_RTA
d62a17ae 1638#define NDA_RTA(r) \
1639 ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
2232a77c 1640#endif
1641
d62a17ae 1642static int netlink_macfdb_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
1643 int len)
2232a77c 1644{
d62a17ae 1645 struct ndmsg *ndm;
1646 struct interface *ifp;
1647 struct zebra_if *zif;
1648 struct zebra_vrf *zvrf;
1649 struct rtattr *tb[NDA_MAX + 1];
1650 struct interface *br_if;
1651 struct ethaddr mac;
1652 vlanid_t vid = 0;
1653 struct prefix vtep_ip;
1654 int vid_present = 0, dst_present = 0;
1655 char buf[ETHER_ADDR_STRLEN];
1656 char vid_buf[20];
1657 char dst_buf[30];
1658 u_char sticky = 0;
1659
1660 ndm = NLMSG_DATA(h);
1661
1662 /* The interface should exist. */
1663 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
1664 ndm->ndm_ifindex);
1665 if (!ifp)
1666 return 0;
1667
1668 /* Locate VRF corresponding to interface. We only process MAC
1669 * notifications
1670 * if EVPN is enabled on this VRF.
1671 */
1672 zvrf = vrf_info_lookup(ifp->vrf_id);
1673 if (!zvrf || !EVPN_ENABLED(zvrf))
1674 return 0;
1675 if (!ifp->info)
1676 return 0;
1677
1678 /* The interface should be something we're interested in. */
1679 if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
1680 return 0;
1681
1682 /* Drop "permanent" entries. */
1683 if (ndm->ndm_state & NUD_PERMANENT)
1684 return 0;
1685
1686 zif = (struct zebra_if *)ifp->info;
1687 if ((br_if = zif->brslave_info.br_if) == NULL) {
1688 zlog_warn("%s family %s IF %s(%u) brIF %u - no bridge master",
1689 nl_msg_type_to_str(h->nlmsg_type),
1690 nl_family_to_str(ndm->ndm_family), ifp->name,
1691 ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex);
1692 return 0;
1693 }
1694
1695 /* Parse attributes and extract fields of interest. */
1696 memset(tb, 0, sizeof tb);
1697 netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
1698
1699 if (!tb[NDA_LLADDR]) {
1700 zlog_warn("%s family %s IF %s(%u) brIF %u - no LLADDR",
1701 nl_msg_type_to_str(h->nlmsg_type),
1702 nl_family_to_str(ndm->ndm_family), ifp->name,
1703 ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex);
1704 return 0;
1705 }
1706
ff8b7eb8 1707 if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
d62a17ae 1708 zlog_warn(
df0b13cf 1709 "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %lu",
d62a17ae 1710 nl_msg_type_to_str(h->nlmsg_type),
1711 nl_family_to_str(ndm->ndm_family), ifp->name,
1712 ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex,
df0b13cf 1713 (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR]));
d62a17ae 1714 return 0;
1715 }
1716
ff8b7eb8 1717 memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETH_ALEN);
d62a17ae 1718
1719 if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN]) {
1720 vid_present = 1;
1721 vid = *(u_int16_t *)RTA_DATA(tb[NDA_VLAN]);
1722 sprintf(vid_buf, " VLAN %u", vid);
1723 }
1724
1725 if (tb[NDA_DST]) {
1726 /* TODO: Only IPv4 supported now. */
1727 dst_present = 1;
1728 vtep_ip.family = AF_INET;
1729 vtep_ip.prefixlen = IPV4_MAX_BITLEN;
1730 memcpy(&(vtep_ip.u.prefix4.s_addr), RTA_DATA(tb[NDA_DST]),
1731 IPV4_MAX_BYTELEN);
1732 sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip.u.prefix4));
1733 }
1734
1735 sticky = (ndm->ndm_state & NUD_NOARP) ? 1 : 0;
1736
1737 if (IS_ZEBRA_DEBUG_KERNEL)
1738 zlog_debug("Rx %s family %s IF %s(%u)%s %sMAC %s%s",
1739 nl_msg_type_to_str(h->nlmsg_type),
1740 nl_family_to_str(ndm->ndm_family), ifp->name,
1741 ndm->ndm_ifindex, vid_present ? vid_buf : "",
1742 sticky ? "sticky " : "",
1743 prefix_mac2str(&mac, buf, sizeof(buf)),
1744 dst_present ? dst_buf : "");
1745
1746 if (filter_vlan && vid != filter_vlan)
1747 return 0;
1748
1749 /* If add or update, do accordingly if learnt on a "local" interface; if
1750 * the notification is over VxLAN, this has to be related to
1751 * multi-homing,
1752 * so perform an implicit delete of any local entry (if it exists).
1753 */
1754 if (h->nlmsg_type == RTM_NEWNEIGH) {
1755 /* Drop "permanent" entries. */
1756 if (ndm->ndm_state & NUD_PERMANENT)
1757 return 0;
1758
1759 if (IS_ZEBRA_IF_VXLAN(ifp))
1760 return zebra_vxlan_check_del_local_mac(ifp, br_if, &mac,
1761 vid);
1762
1763 return zebra_vxlan_local_mac_add_update(ifp, br_if, &mac, vid,
1764 sticky);
1765 }
1766
1767 /* This is a delete notification.
1768 * 1. For a MAC over VxLan, check if it needs to be refreshed(readded)
1769 * 2. For a MAC over "local" interface, delete the mac
1770 * Note: We will get notifications from both bridge driver and VxLAN
1771 * driver.
1772 * Ignore the notification from VxLan driver as it is also generated
1773 * when mac moves from remote to local.
1774 */
1775 if (dst_present)
1776 return 0;
1777
1778 if (IS_ZEBRA_IF_VXLAN(ifp))
1779 return zebra_vxlan_check_readd_remote_mac(ifp, br_if, &mac,
1780 vid);
1781
1782 return zebra_vxlan_local_mac_del(ifp, br_if, &mac, vid);
2232a77c 1783}
1784
d62a17ae 1785static int netlink_macfdb_table(struct sockaddr_nl *snl, struct nlmsghdr *h,
1786 ns_id_t ns_id, int startup)
2232a77c 1787{
d62a17ae 1788 int len;
1789 struct ndmsg *ndm;
2232a77c 1790
d62a17ae 1791 if (h->nlmsg_type != RTM_NEWNEIGH)
1792 return 0;
2232a77c 1793
d62a17ae 1794 /* Length validity. */
1795 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
1796 if (len < 0)
1797 return -1;
2232a77c 1798
d62a17ae 1799 /* We are interested only in AF_BRIDGE notifications. */
1800 ndm = NLMSG_DATA(h);
1801 if (ndm->ndm_family != AF_BRIDGE)
1802 return 0;
2232a77c 1803
d62a17ae 1804 return netlink_macfdb_change(snl, h, len);
2232a77c 1805}
1806
1807/* Request for MAC FDB information from the kernel */
d62a17ae 1808static int netlink_request_macs(struct zebra_ns *zns, int family, int type,
1809 ifindex_t master_ifindex)
2232a77c 1810{
d62a17ae 1811 struct {
1812 struct nlmsghdr n;
1813 struct ifinfomsg ifm;
1814 char buf[256];
1815 } req;
1816
1817 /* Form the request, specifying filter (rtattr) if needed. */
1818 memset(&req, 0, sizeof(req));
1819 req.n.nlmsg_type = type;
1820 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1821 req.ifm.ifi_family = family;
1822 if (master_ifindex)
1823 addattr32(&req.n, sizeof(req), IFLA_MASTER, master_ifindex);
1824
1825 return netlink_request(&zns->netlink_cmd, &req.n);
2232a77c 1826}
1827
1828/*
1829 * MAC forwarding database read using netlink interface. This is invoked
1830 * at startup.
1831 */
d62a17ae 1832int netlink_macfdb_read(struct zebra_ns *zns)
2232a77c 1833{
d62a17ae 1834 int ret;
1835
1836 /* Get bridge FDB table. */
1837 ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH, 0);
1838 if (ret < 0)
1839 return ret;
1840 /* We are reading entire table. */
1841 filter_vlan = 0;
1842 ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns,
1843 0, 1);
1844
1845 return ret;
2232a77c 1846}
1847
1848/*
1849 * MAC forwarding database read using netlink interface. This is for a
1850 * specific bridge and matching specific access VLAN (if VLAN-aware bridge).
1851 */
d62a17ae 1852int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
1853 struct interface *br_if)
2232a77c 1854{
d62a17ae 1855 struct zebra_if *br_zif;
1856 struct zebra_if *zif;
1857 struct zebra_l2info_vxlan *vxl;
1858 int ret = 0;
1859
1860
1861 /* Save VLAN we're filtering on, if needed. */
1862 br_zif = (struct zebra_if *)br_if->info;
1863 zif = (struct zebra_if *)ifp->info;
1864 vxl = &zif->l2info.vxl;
1865 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
1866 filter_vlan = vxl->access_vlan;
1867
1868 /* Get bridge FDB table for specific bridge - we do the VLAN filtering.
1869 */
1870 ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH,
1871 br_if->ifindex);
1872 if (ret < 0)
1873 return ret;
1874 ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns,
1875 0, 0);
1876
1877 /* Reset VLAN filter. */
1878 filter_vlan = 0;
1879 return ret;
2232a77c 1880}
1881
d62a17ae 1882static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
1883 struct ethaddr *mac, struct in_addr vtep_ip,
1884 int local, int cmd, u_char sticky)
2232a77c 1885{
d62a17ae 1886 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
1887 struct {
1888 struct nlmsghdr n;
1889 struct ndmsg ndm;
1890 char buf[256];
1891 } req;
1892 int dst_alen;
1893 struct zebra_if *zif;
1894 struct interface *br_if;
1895 struct zebra_if *br_zif;
1896 char buf[ETHER_ADDR_STRLEN];
1897 int vid_present = 0, dst_present = 0;
1898 char vid_buf[20];
1899 char dst_buf[30];
1900
1901 zif = ifp->info;
1902 if ((br_if = zif->brslave_info.br_if) == NULL) {
1903 zlog_warn("MAC %s on IF %s(%u) - no mapping to bridge",
1904 (cmd == RTM_NEWNEIGH) ? "add" : "del", ifp->name,
1905 ifp->ifindex);
1906 return -1;
1907 }
1908
1909 memset(&req.n, 0, sizeof(req.n));
1910 memset(&req.ndm, 0, sizeof(req.ndm));
1911
1912 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1913 req.n.nlmsg_flags = NLM_F_REQUEST;
1914 if (cmd == RTM_NEWNEIGH)
1915 req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
1916 req.n.nlmsg_type = cmd;
1917 req.ndm.ndm_family = AF_BRIDGE;
1918 req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
1919 req.ndm.ndm_state = NUD_REACHABLE;
1920
1921 if (sticky)
1922 req.ndm.ndm_state |= NUD_NOARP;
1923 else
1924 req.ndm.ndm_flags |= NTF_EXT_LEARNED;
1925
1926 addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
1927 req.ndm.ndm_ifindex = ifp->ifindex;
1928 if (!local) {
1929 dst_alen = 4; // TODO: hardcoded
1930 addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen);
1931 dst_present = 1;
1932 sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip));
1933 }
1934 br_zif = (struct zebra_if *)br_if->info;
1935 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) {
1936 addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
1937 vid_present = 1;
1938 sprintf(vid_buf, " VLAN %u", vid);
1939 }
1940 addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
1941
1942 if (IS_ZEBRA_DEBUG_KERNEL)
1943 zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
1944 nl_msg_type_to_str(cmd),
1945 nl_family_to_str(req.ndm.ndm_family), ifp->name,
1946 ifp->ifindex, vid_present ? vid_buf : "",
1947 sticky ? "sticky " : "",
1948 prefix_mac2str(mac, buf, sizeof(buf)),
1949 dst_present ? dst_buf : "");
1950
1951 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
1952 0);
2232a77c 1953}
1954
d62a17ae 1955#define NUD_VALID \
1956 (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE \
1957 | NUD_DELAY)
2232a77c 1958
d62a17ae 1959static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
1960 int len)
2232a77c 1961{
d62a17ae 1962 struct ndmsg *ndm;
1963 struct interface *ifp;
1964 struct zebra_if *zif;
1965 struct zebra_vrf *zvrf;
1966 struct rtattr *tb[NDA_MAX + 1];
1967 struct interface *link_if;
1968 struct ethaddr mac;
1969 struct ipaddr ip;
1970 char buf[ETHER_ADDR_STRLEN];
1971 char buf2[INET6_ADDRSTRLEN];
1972 int mac_present = 0;
1973 u_char ext_learned;
1974
1975 ndm = NLMSG_DATA(h);
1976
1977 /* The interface should exist. */
1978 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
1979 ndm->ndm_ifindex);
1980 if (!ifp)
1981 return 0;
1982
1983 /* Locate VRF corresponding to interface. We only process neigh
1984 * notifications
1985 * if EVPN is enabled on this VRF.
1986 */
1987 zvrf = vrf_info_lookup(ifp->vrf_id);
1988 if (!zvrf || !EVPN_ENABLED(zvrf))
1989 return 0;
1990 if (!ifp->info)
1991 return 0;
1992
1993 /* Drop "permanent" entries. */
1994 if (ndm->ndm_state & NUD_PERMANENT)
1995 return 0;
1996
1997 zif = (struct zebra_if *)ifp->info;
1998 /* The neighbor is present on an SVI. From this, we locate the
1999 * underlying
2000 * bridge because we're only interested in neighbors on a VxLAN bridge.
2001 * The bridge is located based on the nature of the SVI:
2002 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN
2003 * interface
2004 * and is linked to the bridge
2005 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge
2006 * inteface
2007 * itself
2008 */
2009 if (IS_ZEBRA_IF_VLAN(ifp)) {
2010 link_if = zif->link;
2011 if (!link_if)
2012 return 0;
2013 } else if (IS_ZEBRA_IF_BRIDGE(ifp))
2014 link_if = ifp;
2015 else
2016 return 0;
2017
2018 /* Parse attributes and extract fields of interest. */
2019 memset(tb, 0, sizeof tb);
2020 netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
2021
2022 if (!tb[NDA_DST]) {
2023 zlog_warn("%s family %s IF %s(%u) - no DST",
2024 nl_msg_type_to_str(h->nlmsg_type),
2025 nl_family_to_str(ndm->ndm_family), ifp->name,
2026 ndm->ndm_ifindex);
2027 return 0;
2028 }
2029 memset(&mac, 0, sizeof(struct ethaddr));
2030 memset(&ip, 0, sizeof(struct ipaddr));
2031 ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6;
2032 memcpy(&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
2033
2034 if (h->nlmsg_type == RTM_NEWNEIGH) {
2035 if (tb[NDA_LLADDR]) {
ff8b7eb8 2036 if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
d62a17ae 2037 zlog_warn(
df0b13cf 2038 "%s family %s IF %s(%u) - LLADDR is not MAC, len %lu",
d62a17ae 2039 nl_msg_type_to_str(h->nlmsg_type),
2040 nl_family_to_str(ndm->ndm_family),
2041 ifp->name, ndm->ndm_ifindex,
df0b13cf 2042 (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR]));
d62a17ae 2043 return 0;
2044 }
2045
2046 mac_present = 1;
ff8b7eb8 2047 memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETH_ALEN);
d62a17ae 2048 }
2049
2050 ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0;
2051
2052 if (IS_ZEBRA_DEBUG_KERNEL)
2053 zlog_debug(
2054 "Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x",
2055 nl_msg_type_to_str(h->nlmsg_type),
2056 nl_family_to_str(ndm->ndm_family), ifp->name,
2057 ndm->ndm_ifindex,
2058 ipaddr2str(&ip, buf2, sizeof(buf2)),
2059 mac_present
2060 ? prefix_mac2str(&mac, buf, sizeof(buf))
2061 : "",
2062 ndm->ndm_state, ndm->ndm_flags);
2063
2064 /* If the neighbor state is valid for use, process as an add or
2065 * update
2066 * else process as a delete. Note that the delete handling may
2067 * result
2068 * in re-adding the neighbor if it is a valid "remote" neighbor.
2069 */
2070 if (ndm->ndm_state & NUD_VALID)
2071 return zebra_vxlan_local_neigh_add_update(
2072 ifp, link_if, &ip, &mac, ndm->ndm_state,
2073 ext_learned);
2074
2075 return zebra_vxlan_local_neigh_del(ifp, link_if, &ip);
2076 }
2077
2078 if (IS_ZEBRA_DEBUG_KERNEL)
2079 zlog_debug("Rx %s family %s IF %s(%u) IP %s",
2080 nl_msg_type_to_str(h->nlmsg_type),
2081 nl_family_to_str(ndm->ndm_family), ifp->name,
2082 ndm->ndm_ifindex,
2083 ipaddr2str(&ip, buf2, sizeof(buf2)));
2084
2085 /* Process the delete - it may result in re-adding the neighbor if it is
2086 * a valid "remote" neighbor.
2087 */
2088 return zebra_vxlan_local_neigh_del(ifp, link_if, &ip);
2232a77c 2089}
2090
d62a17ae 2091static int netlink_neigh_table(struct sockaddr_nl *snl, struct nlmsghdr *h,
2092 ns_id_t ns_id, int startup)
2232a77c 2093{
d62a17ae 2094 int len;
2095 struct ndmsg *ndm;
2232a77c 2096
d62a17ae 2097 if (h->nlmsg_type != RTM_NEWNEIGH)
2098 return 0;
2232a77c 2099
d62a17ae 2100 /* Length validity. */
2101 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
2102 if (len < 0)
2103 return -1;
2232a77c 2104
d62a17ae 2105 /* We are interested only in AF_INET or AF_INET6 notifications. */
2106 ndm = NLMSG_DATA(h);
2107 if (ndm->ndm_family != AF_INET && ndm->ndm_family != AF_INET6)
2108 return 0;
2232a77c 2109
d62a17ae 2110 return netlink_neigh_change(snl, h, len);
2232a77c 2111}
2112
2113/* Request for IP neighbor information from the kernel */
d62a17ae 2114static int netlink_request_neigh(struct zebra_ns *zns, int family, int type,
2115 ifindex_t ifindex)
2232a77c 2116{
d62a17ae 2117 struct {
2118 struct nlmsghdr n;
2119 struct ndmsg ndm;
2120 char buf[256];
2121 } req;
2122
2123 /* Form the request, specifying filter (rtattr) if needed. */
2124 memset(&req, 0, sizeof(req));
2125 req.n.nlmsg_type = type;
2126 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
2127 req.ndm.ndm_family = family;
2128 if (ifindex)
2129 addattr32(&req.n, sizeof(req), NDA_IFINDEX, ifindex);
2130
2131 return netlink_request(&zns->netlink_cmd, &req.n);
2232a77c 2132}
2133
2134/*
2135 * IP Neighbor table read using netlink interface. This is invoked
2136 * at startup.
2137 */
d62a17ae 2138int netlink_neigh_read(struct zebra_ns *zns)
2232a77c 2139{
d62a17ae 2140 int ret;
2232a77c 2141
d62a17ae 2142 /* Get IP neighbor table. */
2143 ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH, 0);
2144 if (ret < 0)
2145 return ret;
2146 ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0,
2147 1);
2232a77c 2148
d62a17ae 2149 return ret;
2232a77c 2150}
2151
2152/*
2153 * IP Neighbor table read using netlink interface. This is for a specific
2154 * VLAN device.
2155 */
d62a17ae 2156int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
2232a77c 2157{
d62a17ae 2158 int ret = 0;
2232a77c 2159
d62a17ae 2160 ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH,
2161 vlan_if->ifindex);
2162 if (ret < 0)
2163 return ret;
2164 ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0,
2165 0);
2232a77c 2166
d62a17ae 2167 return ret;
2232a77c 2168}
2169
d62a17ae 2170int netlink_neigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
2171 ns_id_t ns_id)
2232a77c 2172{
d62a17ae 2173 int len;
2174 struct ndmsg *ndm;
2232a77c 2175
d62a17ae 2176 if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH))
2177 return 0;
2232a77c 2178
d62a17ae 2179 /* Length validity. */
2180 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
2181 if (len < 0)
2182 return -1;
2232a77c 2183
d62a17ae 2184 /* Is this a notification for the MAC FDB or IP neighbor table? */
2185 ndm = NLMSG_DATA(h);
2186 if (ndm->ndm_family == AF_BRIDGE)
2187 return netlink_macfdb_change(snl, h, len);
2232a77c 2188
d62a17ae 2189 if (ndm->ndm_type != RTN_UNICAST)
2190 return 0;
2232a77c 2191
d62a17ae 2192 if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6)
2193 return netlink_ipneigh_change(snl, h, len);
2232a77c 2194
d62a17ae 2195 return 0;
2232a77c 2196}
2197
d62a17ae 2198static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
2199 struct ethaddr *mac, u_int32_t flags, int cmd)
2232a77c 2200{
d62a17ae 2201 struct {
2202 struct nlmsghdr n;
2203 struct ndmsg ndm;
2204 char buf[256];
2205 } req;
2206 int ipa_len;
2207
2208 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
2209 char buf[INET6_ADDRSTRLEN];
2210 char buf2[ETHER_ADDR_STRLEN];
2211
2212 memset(&req.n, 0, sizeof(req.n));
2213 memset(&req.ndm, 0, sizeof(req.ndm));
2214
2215 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
2216 req.n.nlmsg_flags = NLM_F_REQUEST;
2217 if (cmd == RTM_NEWNEIGH)
2218 req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
2219 req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
2220 req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
2221 req.ndm.ndm_state = flags;
2222 req.ndm.ndm_ifindex = ifp->ifindex;
2223 req.ndm.ndm_type = RTN_UNICAST;
2224 req.ndm.ndm_flags = NTF_EXT_LEARNED;
2225
2226
2227 ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
2228 addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
2229 if (mac)
2230 addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
2231
2232 if (IS_ZEBRA_DEBUG_KERNEL)
2233 zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s",
2234 nl_msg_type_to_str(cmd),
2235 nl_family_to_str(req.ndm.ndm_family), ifp->name,
2236 ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)),
2237 mac ? prefix_mac2str(mac, buf2, sizeof(buf2))
2238 : "null");
2239
2240 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
2241 0);
2232a77c 2242}
2243
d62a17ae 2244int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
2245 struct in_addr vtep_ip, u_char sticky)
2232a77c 2246{
d62a17ae 2247 return netlink_macfdb_update(ifp, vid, mac, vtep_ip, 0, RTM_NEWNEIGH,
2248 sticky);
2232a77c 2249}
2250
d62a17ae 2251int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
2252 struct in_addr vtep_ip, int local)
2232a77c 2253{
d62a17ae 2254 return netlink_macfdb_update(ifp, vid, mac, vtep_ip, local,
2255 RTM_DELNEIGH, 0);
2232a77c 2256}
2257
d62a17ae 2258int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
2259 struct ethaddr *mac)
2232a77c 2260{
d62a17ae 2261 return netlink_neigh_update2(ifp, ip, mac, NUD_REACHABLE, RTM_NEWNEIGH);
2232a77c 2262}
2263
d62a17ae 2264int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip)
2232a77c 2265{
d62a17ae 2266 return netlink_neigh_update2(ifp, ip, NULL, 0, RTM_DELNEIGH);
2232a77c 2267}
2268
40c7bdb0 2269/*
2270 * MPLS label forwarding table change via netlink interface.
2271 */
d62a17ae 2272int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
40c7bdb0 2273{
d62a17ae 2274 mpls_lse_t lse;
2275 zebra_nhlfe_t *nhlfe;
2276 struct nexthop *nexthop = NULL;
2277 unsigned int nexthop_num;
2278 const char *routedesc;
2279 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
2280
2281 struct {
2282 struct nlmsghdr n;
2283 struct rtmsg r;
2284 char buf[NL_PKT_BUF_SIZE];
2285 } req;
2286
2287 memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE);
2288
2289
2290 /*
2291 * Count # nexthops so we can decide whether to use singlepath
2292 * or multipath case.
2293 */
2294 nexthop_num = 0;
2295 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
2296 nexthop = nhlfe->nexthop;
2297 if (!nexthop)
2298 continue;
2299 if (cmd == RTM_NEWROUTE) {
2300 /* Count all selected NHLFEs */
2301 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
2302 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
2303 nexthop_num++;
2304 } else /* DEL */
2305 {
2306 /* Count all installed NHLFEs */
2307 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)
2308 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
2309 nexthop_num++;
2310 }
2311 }
2312
2313 if (nexthop_num == 0) // unexpected
2314 return 0;
2315
2316 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
2317 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
2318 req.n.nlmsg_type = cmd;
2319 req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
2320
2321 req.r.rtm_family = AF_MPLS;
2322 req.r.rtm_table = RT_TABLE_MAIN;
2323 req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
2324 req.r.rtm_protocol = RTPROT_ZEBRA;
2325 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
2326 req.r.rtm_type = RTN_UNICAST;
2327
2328 if (cmd == RTM_NEWROUTE)
2329 /* We do a replace to handle update. */
2330 req.n.nlmsg_flags |= NLM_F_REPLACE;
2331
2332 /* Fill destination */
2333 lse = mpls_lse_encode(lsp->ile.in_label, 0, 0, 1);
2334 addattr_l(&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t));
2335
2336 /* Fill nexthops (paths) based on single-path or multipath. The paths
2337 * chosen depend on the operation.
2338 */
2339 if (nexthop_num == 1 || multipath_num == 1) {
2340 routedesc = "single hop";
2341 _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
2342
2343 nexthop_num = 0;
2344 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
2345 nexthop = nhlfe->nexthop;
2346 if (!nexthop)
2347 continue;
2348
2349 if ((cmd == RTM_NEWROUTE
2350 && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
2351 && CHECK_FLAG(nexthop->flags,
2352 NEXTHOP_FLAG_ACTIVE)))
2353 || (cmd == RTM_DELROUTE
2354 && (CHECK_FLAG(nhlfe->flags,
2355 NHLFE_FLAG_INSTALLED)
2356 && CHECK_FLAG(nexthop->flags,
2357 NEXTHOP_FLAG_FIB)))) {
2358 /* Add the gateway */
2359 _netlink_mpls_build_singlepath(routedesc, nhlfe,
2360 &req.n, &req.r,
2361 sizeof req, cmd);
2362 if (cmd == RTM_NEWROUTE) {
2363 SET_FLAG(nhlfe->flags,
2364 NHLFE_FLAG_INSTALLED);
2365 SET_FLAG(nexthop->flags,
2366 NEXTHOP_FLAG_FIB);
2367 } else {
2368 UNSET_FLAG(nhlfe->flags,
2369 NHLFE_FLAG_INSTALLED);
2370 UNSET_FLAG(nexthop->flags,
2371 NEXTHOP_FLAG_FIB);
2372 }
2373 nexthop_num++;
2374 break;
2375 }
2376 }
2377 } else /* Multipath case */
2378 {
2379 char buf[NL_PKT_BUF_SIZE];
2380 struct rtattr *rta = (void *)buf;
2381 struct rtnexthop *rtnh;
2382 union g_addr *src1 = NULL;
2383
2384 rta->rta_type = RTA_MULTIPATH;
2385 rta->rta_len = RTA_LENGTH(0);
2386 rtnh = RTA_DATA(rta);
2387
2388 routedesc = "multihop";
2389 _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
2390
2391 nexthop_num = 0;
2392 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
2393 nexthop = nhlfe->nexthop;
2394 if (!nexthop)
2395 continue;
2396
2397 if (nexthop_num >= multipath_num)
2398 break;
2399
2400 if ((cmd == RTM_NEWROUTE
2401 && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
2402 && CHECK_FLAG(nexthop->flags,
2403 NEXTHOP_FLAG_ACTIVE)))
2404 || (cmd == RTM_DELROUTE
2405 && (CHECK_FLAG(nhlfe->flags,
2406 NHLFE_FLAG_INSTALLED)
2407 && CHECK_FLAG(nexthop->flags,
2408 NEXTHOP_FLAG_FIB)))) {
2409 nexthop_num++;
2410
2411 /* Build the multipath */
2412 _netlink_mpls_build_multipath(routedesc, nhlfe,
2413 rta, rtnh, &req.r,
2414 &src1);
2415 rtnh = RTNH_NEXT(rtnh);
2416
2417 if (cmd == RTM_NEWROUTE) {
2418 SET_FLAG(nhlfe->flags,
2419 NHLFE_FLAG_INSTALLED);
2420 SET_FLAG(nexthop->flags,
2421 NEXTHOP_FLAG_FIB);
2422 } else {
2423 UNSET_FLAG(nhlfe->flags,
2424 NHLFE_FLAG_INSTALLED);
2425 UNSET_FLAG(nexthop->flags,
2426 NEXTHOP_FLAG_FIB);
2427 }
2428 }
2429 }
2430
2431 /* Add the multipath */
2432 if (rta->rta_len > RTA_LENGTH(0))
2433 addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH,
2434 RTA_DATA(rta), RTA_PAYLOAD(rta));
2435 }
2436
2437 /* Talk to netlink socket. */
2438 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
2439 0);
40c7bdb0 2440}
2441
2442/*
2443 * Handle failure in LSP install, clear flags for NHLFE.
2444 */
d62a17ae 2445void clear_nhlfe_installed(zebra_lsp_t *lsp)
40c7bdb0 2446{
d62a17ae 2447 zebra_nhlfe_t *nhlfe;
2448 struct nexthop *nexthop;
2449
2450 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
2451 nexthop = nhlfe->nexthop;
2452 if (!nexthop)
2453 continue;
2454
2455 UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
2456 UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
2457 }
40c7bdb0 2458}
ddfeb486
DL
2459
2460#endif /* HAVE_NETLINK */