]> git.proxmox.com Git - mirror_frr.git/blob - zebra/rt_netlink.c
Merge branch '-isisd-simpl' into stable/2.0
[mirror_frr.git] / zebra / rt_netlink.c
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 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22 #include <zebra.h>
23 #include <net/if_arp.h>
24
25 /* Hack for GNU libc version 2. */
26 #ifndef MSG_TRUNC
27 #define MSG_TRUNC 0x20
28 #endif /* MSG_TRUNC */
29
30 #include "linklist.h"
31 #include "if.h"
32 #include "log.h"
33 #include "prefix.h"
34 #include "connected.h"
35 #include "table.h"
36 #include "memory.h"
37 #include "zebra_memory.h"
38 #include "rib.h"
39 #include "thread.h"
40 #include "privs.h"
41 #include "nexthop.h"
42 #include "vrf.h"
43 #include "mpls.h"
44
45 #include "zebra/zserv.h"
46 #include "zebra/zebra_ns.h"
47 #include "zebra/zebra_vrf.h"
48 #include "zebra/rt.h"
49 #include "zebra/redistribute.h"
50 #include "zebra/interface.h"
51 #include "zebra/debug.h"
52 #include "zebra/rtadv.h"
53 #include "zebra/zebra_ptm.h"
54 #include "zebra/zebra_mpls.h"
55 #include "zebra/kernel_netlink.h"
56 #include "zebra/rt_netlink.h"
57
58 /* TODO - Temporary definitions, need to refine. */
59 #ifndef AF_MPLS
60 #define AF_MPLS 28
61 #endif
62
63 #ifndef RTA_VIA
64 #define RTA_VIA 18
65 #endif
66
67 #ifndef RTA_NEWDST
68 #define RTA_NEWDST 19
69 #endif
70
71 #ifndef RTA_ENCAP_TYPE
72 #define RTA_ENCAP_TYPE 21
73 #endif
74
75 #ifndef RTA_ENCAP
76 #define RTA_ENCAP 22
77 #endif
78
79 #ifndef LWTUNNEL_ENCAP_MPLS
80 #define LWTUNNEL_ENCAP_MPLS 1
81 #endif
82
83 #ifndef MPLS_IPTUNNEL_DST
84 #define MPLS_IPTUNNEL_DST 1
85 #endif
86 /* End of temporary definitions */
87
88 struct gw_family_t
89 {
90 u_int16_t filler;
91 u_int16_t family;
92 union g_addr gate;
93 };
94
95 /*
96 Pending: create an efficient table_id (in a tree/hash) based lookup)
97 */
98 static vrf_id_t
99 vrf_lookup_by_table (u_int32_t table_id)
100 {
101 struct vrf *vrf;
102 struct zebra_vrf *zvrf;
103
104 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
105 {
106 if ((zvrf = vrf->info) == NULL ||
107 (zvrf->table_id != table_id))
108 continue;
109
110 return zvrf_id (zvrf);
111 }
112
113 return VRF_DEFAULT;
114 }
115
116 /* Looking up routing table by netlink interface. */
117 static int
118 netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
119 ns_id_t ns_id)
120 {
121 int len;
122 struct rtmsg *rtm;
123 struct rtattr *tb[RTA_MAX + 1];
124 u_char flags = 0;
125 struct prefix p;
126 vrf_id_t vrf_id = VRF_DEFAULT;
127
128 char anyaddr[16] = { 0 };
129
130 int index;
131 int table;
132 int metric;
133 u_int32_t mtu = 0;
134
135 void *dest;
136 void *gate;
137 void *src;
138
139 rtm = NLMSG_DATA (h);
140
141 if (h->nlmsg_type != RTM_NEWROUTE)
142 return 0;
143 if (rtm->rtm_type != RTN_UNICAST)
144 return 0;
145
146 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
147 if (len < 0)
148 return -1;
149
150 memset (tb, 0, sizeof tb);
151 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
152
153 if (rtm->rtm_flags & RTM_F_CLONED)
154 return 0;
155 if (rtm->rtm_protocol == RTPROT_REDIRECT)
156 return 0;
157 if (rtm->rtm_protocol == RTPROT_KERNEL)
158 return 0;
159
160 if (rtm->rtm_src_len != 0)
161 return 0;
162
163 /* We don't care about change notifications for the MPLS table. */
164 /* TODO: Revisit this. */
165 if (rtm->rtm_family == AF_MPLS)
166 return 0;
167
168 /* Table corresponding to route. */
169 if (tb[RTA_TABLE])
170 table = *(int *) RTA_DATA (tb[RTA_TABLE]);
171 else
172 table = rtm->rtm_table;
173
174 /* Map to VRF */
175 vrf_id = vrf_lookup_by_table(table);
176 if (vrf_id == VRF_DEFAULT)
177 {
178 if (!is_zebra_valid_kernel_table(table) &&
179 !is_zebra_main_routing_table(table))
180 return 0;
181 }
182
183 /* Route which inserted by Zebra. */
184 if (rtm->rtm_protocol == RTPROT_ZEBRA)
185 flags |= ZEBRA_FLAG_SELFROUTE;
186
187 index = 0;
188 metric = 0;
189 dest = NULL;
190 gate = NULL;
191 src = NULL;
192
193 if (tb[RTA_OIF])
194 index = *(int *) RTA_DATA (tb[RTA_OIF]);
195
196 if (tb[RTA_DST])
197 dest = RTA_DATA (tb[RTA_DST]);
198 else
199 dest = anyaddr;
200
201 if (tb[RTA_PREFSRC])
202 src = RTA_DATA (tb[RTA_PREFSRC]);
203
204 if (tb[RTA_GATEWAY])
205 gate = RTA_DATA (tb[RTA_GATEWAY]);
206
207 if (tb[RTA_PRIORITY])
208 metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
209
210 if (tb[RTA_METRICS])
211 {
212 struct rtattr *mxrta[RTAX_MAX+1];
213
214 memset (mxrta, 0, sizeof mxrta);
215 netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
216 RTA_PAYLOAD(tb[RTA_METRICS]));
217
218 if (mxrta[RTAX_MTU])
219 mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
220 }
221
222 if (rtm->rtm_family == AF_INET)
223 {
224 p.family = AF_INET;
225 memcpy (&p.u.prefix4, dest, 4);
226 p.prefixlen = rtm->rtm_dst_len;
227
228 if (!tb[RTA_MULTIPATH])
229 rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
230 0, flags, &p, gate, src, index,
231 table, metric, mtu, 0);
232 else
233 {
234 /* This is a multipath route */
235
236 struct rib *rib;
237 struct rtnexthop *rtnh =
238 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
239
240 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
241
242 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
243 rib->type = ZEBRA_ROUTE_KERNEL;
244 rib->distance = 0;
245 rib->flags = flags;
246 rib->metric = metric;
247 rib->mtu = mtu;
248 rib->vrf_id = vrf_id;
249 rib->table = table;
250 rib->nexthop_num = 0;
251 rib->uptime = time (NULL);
252
253 for (;;)
254 {
255 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
256 break;
257
258 index = rtnh->rtnh_ifindex;
259 gate = 0;
260 if (rtnh->rtnh_len > sizeof (*rtnh))
261 {
262 memset (tb, 0, sizeof (tb));
263 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
264 rtnh->rtnh_len - sizeof (*rtnh));
265 if (tb[RTA_GATEWAY])
266 gate = RTA_DATA (tb[RTA_GATEWAY]);
267 }
268
269 if (gate)
270 {
271 if (index)
272 rib_nexthop_ipv4_ifindex_add (rib, gate, src, index);
273 else
274 rib_nexthop_ipv4_add (rib, gate, src);
275 }
276 else
277 rib_nexthop_ifindex_add (rib, index);
278
279 len -= NLMSG_ALIGN(rtnh->rtnh_len);
280 rtnh = RTNH_NEXT(rtnh);
281 }
282
283 zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
284 rib->nexthop_num);
285 if (rib->nexthop_num == 0)
286 XFREE (MTYPE_RIB, rib);
287 else
288 rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, rib);
289 }
290 }
291 if (rtm->rtm_family == AF_INET6)
292 {
293 p.family = AF_INET6;
294 memcpy (&p.u.prefix6, dest, 16);
295 p.prefixlen = rtm->rtm_dst_len;
296
297 rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
298 0, flags, &p, gate, src, index,
299 table, metric, mtu, 0);
300 }
301
302 return 0;
303 }
304
305 /* Routing information change from the kernel. */
306 int
307 netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
308 ns_id_t ns_id)
309 {
310 int len;
311 struct rtmsg *rtm;
312 struct rtattr *tb[RTA_MAX + 1];
313 u_char zebra_flags = 0;
314 struct prefix p;
315 vrf_id_t vrf_id = VRF_DEFAULT;
316
317 char anyaddr[16] = { 0 };
318
319 int index;
320 int table;
321 int metric;
322 u_int32_t mtu = 0;
323
324 void *dest;
325 void *gate;
326 void *src;
327
328 rtm = NLMSG_DATA (h);
329
330 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
331 {
332 /* If this is not route add/delete message print warning. */
333 zlog_warn ("Kernel message: %d", h->nlmsg_type);
334 return 0;
335 }
336
337 /* Connected route. */
338 if (IS_ZEBRA_DEBUG_KERNEL)
339 zlog_debug ("%s %s %s proto %s",
340 h->nlmsg_type ==
341 RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
342 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
343 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
344 nl_rtproto_to_str (rtm->rtm_protocol));
345
346 if (rtm->rtm_type != RTN_UNICAST)
347 {
348 return 0;
349 }
350
351 /* We don't care about change notifications for the MPLS table. */
352 /* TODO: Revisit this. */
353 if (rtm->rtm_family == AF_MPLS)
354 return 0;
355
356 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
357 if (len < 0)
358 return -1;
359
360 memset (tb, 0, sizeof tb);
361 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
362
363 if (rtm->rtm_flags & RTM_F_CLONED)
364 return 0;
365 if (rtm->rtm_protocol == RTPROT_REDIRECT)
366 return 0;
367 if (rtm->rtm_protocol == RTPROT_KERNEL)
368 return 0;
369
370 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
371 return 0;
372 if (rtm->rtm_protocol == RTPROT_ZEBRA)
373 SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE);
374
375 if (rtm->rtm_src_len != 0)
376 {
377 zlog_warn ("netlink_route_change(): no src len");
378 return 0;
379 }
380
381 /* Table corresponding to route. */
382 if (tb[RTA_TABLE])
383 table = *(int *) RTA_DATA (tb[RTA_TABLE]);
384 else
385 table = rtm->rtm_table;
386
387 /* Map to VRF */
388 vrf_id = vrf_lookup_by_table(table);
389 if (vrf_id == VRF_DEFAULT)
390 {
391 if (!is_zebra_valid_kernel_table(table) &&
392 !is_zebra_main_routing_table(table))
393 return 0;
394 }
395
396 index = 0;
397 metric = 0;
398 dest = NULL;
399 gate = NULL;
400 src = NULL;
401
402 if (tb[RTA_OIF])
403 index = *(int *) RTA_DATA (tb[RTA_OIF]);
404
405 if (tb[RTA_DST])
406 dest = RTA_DATA (tb[RTA_DST]);
407 else
408 dest = anyaddr;
409
410 if (tb[RTA_GATEWAY])
411 gate = RTA_DATA (tb[RTA_GATEWAY]);
412
413 if (tb[RTA_PREFSRC])
414 src = RTA_DATA (tb[RTA_PREFSRC]);
415
416 if (h->nlmsg_type == RTM_NEWROUTE)
417 {
418 if (tb[RTA_PRIORITY])
419 metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
420
421 if (tb[RTA_METRICS])
422 {
423 struct rtattr *mxrta[RTAX_MAX+1];
424
425 memset (mxrta, 0, sizeof mxrta);
426 netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
427 RTA_PAYLOAD(tb[RTA_METRICS]));
428
429 if (mxrta[RTAX_MTU])
430 mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
431 }
432 }
433
434 if (rtm->rtm_family == AF_INET)
435 {
436 p.family = AF_INET;
437 memcpy (&p.u.prefix4, dest, 4);
438 p.prefixlen = rtm->rtm_dst_len;
439
440 if (IS_ZEBRA_DEBUG_KERNEL)
441 {
442 char buf[PREFIX_STRLEN];
443 zlog_debug ("%s %s vrf %u",
444 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
445 prefix2str (&p, buf, sizeof(buf)), vrf_id);
446 }
447
448 if (h->nlmsg_type == RTM_NEWROUTE)
449 {
450 if (!tb[RTA_MULTIPATH])
451 rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
452 0, 0, &p, gate, src, index,
453 table, metric, mtu, 0);
454 else
455 {
456 /* This is a multipath route */
457
458 struct rib *rib;
459 struct rtnexthop *rtnh =
460 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
461
462 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
463
464 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
465 rib->type = ZEBRA_ROUTE_KERNEL;
466 rib->distance = 0;
467 rib->flags = 0;
468 rib->metric = metric;
469 rib->mtu = mtu;
470 rib->vrf_id = vrf_id;
471 rib->table = table;
472 rib->nexthop_num = 0;
473 rib->uptime = time (NULL);
474
475 for (;;)
476 {
477 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
478 break;
479
480 index = rtnh->rtnh_ifindex;
481 gate = 0;
482 if (rtnh->rtnh_len > sizeof (*rtnh))
483 {
484 memset (tb, 0, sizeof (tb));
485 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
486 rtnh->rtnh_len - sizeof (*rtnh));
487 if (tb[RTA_GATEWAY])
488 gate = RTA_DATA (tb[RTA_GATEWAY]);
489 }
490
491 if (gate)
492 {
493 if (index)
494 rib_nexthop_ipv4_ifindex_add (rib, gate, src, index);
495 else
496 rib_nexthop_ipv4_add (rib, gate, src);
497 }
498 else
499 rib_nexthop_ifindex_add (rib, index);
500
501 len -= NLMSG_ALIGN(rtnh->rtnh_len);
502 rtnh = RTNH_NEXT(rtnh);
503 }
504
505 zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
506 rib->nexthop_num);
507
508 if (rib->nexthop_num == 0)
509 XFREE (MTYPE_RIB, rib);
510 else
511 rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, rib);
512 }
513 }
514 else
515 rib_delete (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, zebra_flags,
516 &p, gate, index, table);
517 }
518
519 if (rtm->rtm_family == AF_INET6)
520 {
521 struct prefix p;
522
523 p.family = AF_INET6;
524 memcpy (&p.u.prefix6, dest, 16);
525 p.prefixlen = rtm->rtm_dst_len;
526
527 if (IS_ZEBRA_DEBUG_KERNEL)
528 {
529 char buf[PREFIX_STRLEN];
530 zlog_debug ("%s %s vrf %u",
531 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
532 prefix2str (&p, buf, sizeof(buf)), vrf_id);
533 }
534
535 if (h->nlmsg_type == RTM_NEWROUTE)
536 rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
537 0, 0, &p, gate, src, index,
538 table, metric, mtu, 0);
539 else
540 rib_delete (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
541 0, zebra_flags, &p, gate, index, table);
542 }
543
544 return 0;
545 }
546
547 /* Routing table read function using netlink interface. Only called
548 bootstrap time. */
549 int
550 netlink_route_read (struct zebra_ns *zns)
551 {
552 int ret;
553
554 /* Get IPv4 routing table. */
555 ret = netlink_request (AF_INET, RTM_GETROUTE, &zns->netlink_cmd);
556 if (ret < 0)
557 return ret;
558 ret = netlink_parse_info (netlink_routing_table, &zns->netlink_cmd, zns, 0);
559 if (ret < 0)
560 return ret;
561
562 #ifdef HAVE_IPV6
563 /* Get IPv6 routing table. */
564 ret = netlink_request (AF_INET6, RTM_GETROUTE, &zns->netlink_cmd);
565 if (ret < 0)
566 return ret;
567 ret = netlink_parse_info (netlink_routing_table, &zns->netlink_cmd, zns, 0);
568 if (ret < 0)
569 return ret;
570 #endif /* HAVE_IPV6 */
571
572 return 0;
573 }
574
575 static void
576 _netlink_route_nl_add_gateway_info (u_char route_family, u_char gw_family,
577 struct nlmsghdr *nlmsg,
578 size_t req_size, int bytelen,
579 struct nexthop *nexthop)
580 {
581 if (route_family == AF_MPLS)
582 {
583 struct gw_family_t gw_fam;
584
585 gw_fam.family = gw_family;
586 if (gw_family == AF_INET)
587 memcpy (&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
588 else
589 memcpy (&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
590 addattr_l (nlmsg, req_size, RTA_VIA, &gw_fam.family, bytelen+2);
591 }
592 else
593 {
594 if (gw_family == AF_INET)
595 addattr_l (nlmsg, req_size, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen);
596 else
597 addattr_l (nlmsg, req_size, RTA_GATEWAY, &nexthop->gate.ipv6, bytelen);
598 }
599 }
600
601 static void
602 _netlink_route_rta_add_gateway_info (u_char route_family, u_char gw_family,
603 struct rtattr *rta, struct rtnexthop *rtnh,
604 size_t req_size, int bytelen,
605 struct nexthop *nexthop)
606 {
607 if (route_family == AF_MPLS)
608 {
609 struct gw_family_t gw_fam;
610
611 gw_fam.family = gw_family;
612 if (gw_family == AF_INET)
613 memcpy (&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
614 else
615 memcpy (&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
616 rta_addattr_l (rta, req_size, RTA_VIA, &gw_fam.family, bytelen+2);
617 rtnh->rtnh_len += RTA_LENGTH (bytelen + 2);
618 }
619 else
620 {
621 if (gw_family == AF_INET)
622 rta_addattr_l (rta, req_size, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen);
623 else
624 rta_addattr_l (rta, req_size, RTA_GATEWAY, &nexthop->gate.ipv6, bytelen);
625 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
626 }
627 }
628
629 /* This function takes a nexthop as argument and adds
630 * the appropriate netlink attributes to an existing
631 * netlink message.
632 *
633 * @param routedesc: Human readable description of route type
634 * (direct/recursive, single-/multipath)
635 * @param bytelen: Length of addresses in bytes.
636 * @param nexthop: Nexthop information
637 * @param nlmsg: nlmsghdr structure to fill in.
638 * @param req_size: The size allocated for the message.
639 */
640 static void
641 _netlink_route_build_singlepath(
642 const char *routedesc,
643 int bytelen,
644 struct nexthop *nexthop,
645 struct nlmsghdr *nlmsg,
646 struct rtmsg *rtmsg,
647 size_t req_size,
648 int cmd)
649 {
650 struct nexthop_label *nh_label;
651 mpls_lse_t out_lse[MPLS_MAX_LABELS];
652 char label_buf[100];
653
654 if (rtmsg->rtm_family == AF_INET &&
655 (nexthop->type == NEXTHOP_TYPE_IPV6
656 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX))
657 {
658 char buf[16] = "169.254.0.1";
659 struct in_addr ipv4_ll;
660
661 inet_pton (AF_INET, buf, &ipv4_ll);
662 rtmsg->rtm_flags |= RTNH_F_ONLINK;
663 addattr_l (nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4);
664 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
665
666 if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
667 addattr_l (nlmsg, req_size, RTA_PREFSRC,
668 &nexthop->rmap_src.ipv4, bytelen);
669 else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
670 addattr_l (nlmsg, req_size, RTA_PREFSRC,
671 &nexthop->src.ipv4, bytelen);
672
673 if (IS_ZEBRA_DEBUG_KERNEL)
674 zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): "
675 "nexthop via %s if %u",
676 routedesc, buf, nexthop->ifindex);
677 return;
678 }
679
680 label_buf[0] = '\0';
681 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
682 * (in the case of LER)
683 */
684 nh_label = nexthop->nh_label;
685 if (rtmsg->rtm_family == AF_MPLS)
686 {
687 assert (nh_label);
688 assert (nh_label->num_labels == 1);
689 }
690
691 if (nh_label && nh_label->num_labels)
692 {
693 int i, num_labels = 0;
694 u_int32_t bos;
695 char label_buf1[20];
696
697 for (i = 0; i < nh_label->num_labels; i++)
698 {
699 if (nh_label->label[i] != MPLS_IMP_NULL_LABEL)
700 {
701 bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0);
702 out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos);
703 if (!num_labels)
704 sprintf (label_buf, "label %d", nh_label->label[i]);
705 else
706 {
707 sprintf (label_buf1, "/%d", nh_label->label[i]);
708 strcat (label_buf, label_buf1);
709 }
710 num_labels++;
711 }
712 }
713 if (num_labels)
714 {
715 if (rtmsg->rtm_family == AF_MPLS)
716 addattr_l (nlmsg, req_size, RTA_NEWDST,
717 &out_lse, num_labels * sizeof(mpls_lse_t));
718 else
719 {
720 struct rtattr *nest;
721 u_int16_t encap = LWTUNNEL_ENCAP_MPLS;
722
723 addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE,
724 &encap, sizeof (u_int16_t));
725 nest = addattr_nest(nlmsg, req_size, RTA_ENCAP);
726 addattr_l (nlmsg, req_size, MPLS_IPTUNNEL_DST,
727 &out_lse, num_labels * sizeof(mpls_lse_t));
728 addattr_nest_end(nlmsg, nest);
729 }
730 }
731 }
732
733 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
734 rtmsg->rtm_flags |= RTNH_F_ONLINK;
735
736 if (nexthop->type == NEXTHOP_TYPE_IPV4
737 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
738 {
739 _netlink_route_nl_add_gateway_info (rtmsg->rtm_family, AF_INET, nlmsg,
740 req_size, bytelen, nexthop);
741
742 if (cmd == RTM_NEWROUTE)
743 {
744 if (nexthop->rmap_src.ipv4.s_addr)
745 addattr_l (nlmsg, req_size, RTA_PREFSRC,
746 &nexthop->rmap_src.ipv4, bytelen);
747 else if (nexthop->src.ipv4.s_addr)
748 addattr_l (nlmsg, req_size, RTA_PREFSRC,
749 &nexthop->src.ipv4, bytelen);
750 }
751
752 if (IS_ZEBRA_DEBUG_KERNEL)
753 zlog_debug("netlink_route_multipath() (%s): "
754 "nexthop via %s %s if %u",
755 routedesc,
756 inet_ntoa (nexthop->gate.ipv4),
757 label_buf, nexthop->ifindex);
758 }
759 if (nexthop->type == NEXTHOP_TYPE_IPV6
760 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
761 {
762 _netlink_route_nl_add_gateway_info (rtmsg->rtm_family, AF_INET6, nlmsg,
763 req_size, bytelen, nexthop);
764
765 if (cmd == RTM_NEWROUTE)
766 {
767 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
768 addattr_l (nlmsg, req_size, RTA_PREFSRC,
769 &nexthop->rmap_src.ipv6, bytelen);
770 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
771 addattr_l (nlmsg, req_size, RTA_PREFSRC,
772 &nexthop->src.ipv6, bytelen);
773 }
774
775 if (IS_ZEBRA_DEBUG_KERNEL)
776 zlog_debug("netlink_route_multipath() (%s): "
777 "nexthop via %s %s if %u",
778 routedesc,
779 inet6_ntoa (nexthop->gate.ipv6),
780 label_buf, nexthop->ifindex);
781 }
782 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
783 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
784 {
785 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
786
787 if (cmd == RTM_NEWROUTE)
788 {
789 if (nexthop->rmap_src.ipv4.s_addr)
790 addattr_l (nlmsg, req_size, RTA_PREFSRC,
791 &nexthop->rmap_src.ipv4, bytelen);
792 else if (nexthop->src.ipv4.s_addr)
793 addattr_l (nlmsg, req_size, RTA_PREFSRC,
794 &nexthop->src.ipv4, bytelen);
795 }
796
797 if (IS_ZEBRA_DEBUG_KERNEL)
798 zlog_debug("netlink_route_multipath() (%s): "
799 "nexthop via if %u", routedesc, nexthop->ifindex);
800 }
801
802 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
803 {
804 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
805
806 if (cmd == RTM_NEWROUTE)
807 {
808 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
809 addattr_l (nlmsg, req_size, RTA_PREFSRC,
810 &nexthop->rmap_src.ipv6, bytelen);
811 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
812 addattr_l (nlmsg, req_size, RTA_PREFSRC,
813 &nexthop->src.ipv6, bytelen);
814 }
815
816 if (IS_ZEBRA_DEBUG_KERNEL)
817 zlog_debug("netlink_route_multipath() (%s): "
818 "nexthop via if %u", routedesc, nexthop->ifindex);
819 }
820 }
821
822 /* This function takes a nexthop as argument and
823 * appends to the given rtattr/rtnexthop pair the
824 * representation of the nexthop. If the nexthop
825 * defines a preferred source, the src parameter
826 * will be modified to point to that src, otherwise
827 * it will be kept unmodified.
828 *
829 * @param routedesc: Human readable description of route type
830 * (direct/recursive, single-/multipath)
831 * @param bytelen: Length of addresses in bytes.
832 * @param nexthop: Nexthop information
833 * @param rta: rtnetlink attribute structure
834 * @param rtnh: pointer to an rtnetlink nexthop structure
835 * @param src: pointer pointing to a location where
836 * the prefsrc should be stored.
837 */
838 static void
839 _netlink_route_build_multipath(
840 const char *routedesc,
841 int bytelen,
842 struct nexthop *nexthop,
843 struct rtattr *rta,
844 struct rtnexthop *rtnh,
845 struct rtmsg *rtmsg,
846 union g_addr **src)
847 {
848 struct nexthop_label *nh_label;
849 mpls_lse_t out_lse[MPLS_MAX_LABELS];
850 char label_buf[100];
851
852 rtnh->rtnh_len = sizeof (*rtnh);
853 rtnh->rtnh_flags = 0;
854 rtnh->rtnh_hops = 0;
855 rta->rta_len += rtnh->rtnh_len;
856
857 if (rtmsg->rtm_family == AF_INET &&
858 (nexthop->type == NEXTHOP_TYPE_IPV6
859 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX))
860 {
861 char buf[16] = "169.254.0.1";
862 struct in_addr ipv4_ll;
863
864 inet_pton (AF_INET, buf, &ipv4_ll);
865 bytelen = 4;
866 rtnh->rtnh_flags |= RTNH_F_ONLINK;
867 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
868 &ipv4_ll, bytelen);
869 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
870 rtnh->rtnh_ifindex = nexthop->ifindex;
871
872 if (nexthop->rmap_src.ipv4.s_addr)
873 *src = &nexthop->rmap_src;
874 else if (nexthop->src.ipv4.s_addr)
875 *src = &nexthop->src;
876
877 if (IS_ZEBRA_DEBUG_KERNEL)
878 zlog_debug(" 5549: netlink_route_build_multipath() (%s): "
879 "nexthop via %s if %u",
880 routedesc, buf, nexthop->ifindex);
881 return;
882 }
883
884 label_buf[0] = '\0';
885 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
886 * (in the case of LER)
887 */
888 nh_label = nexthop->nh_label;
889 if (rtmsg->rtm_family == AF_MPLS)
890 {
891 assert (nh_label);
892 assert (nh_label->num_labels == 1);
893 }
894
895 if (nh_label && nh_label->num_labels)
896 {
897 int i, num_labels = 0;
898 u_int32_t bos;
899 char label_buf1[20];
900
901 for (i = 0; i < nh_label->num_labels; i++)
902 {
903 if (nh_label->label[i] != MPLS_IMP_NULL_LABEL)
904 {
905 bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0);
906 out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos);
907 if (!num_labels)
908 sprintf (label_buf, "label %d", nh_label->label[i]);
909 else
910 {
911 sprintf (label_buf1, "/%d", nh_label->label[i]);
912 strcat (label_buf, label_buf1);
913 }
914 num_labels++;
915 }
916 }
917 if (num_labels)
918 {
919 if (rtmsg->rtm_family == AF_MPLS)
920 {
921 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_NEWDST,
922 &out_lse, num_labels * sizeof(mpls_lse_t));
923 rtnh->rtnh_len += RTA_LENGTH (num_labels * sizeof(mpls_lse_t));
924 }
925 else
926 {
927 struct rtattr *nest;
928 u_int16_t encap = LWTUNNEL_ENCAP_MPLS;
929 int len = rta->rta_len;
930
931 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_ENCAP_TYPE,
932 &encap, sizeof (u_int16_t));
933 nest = rta_nest(rta, NL_PKT_BUF_SIZE, RTA_ENCAP);
934 rta_addattr_l (rta, NL_PKT_BUF_SIZE, MPLS_IPTUNNEL_DST,
935 &out_lse, num_labels * sizeof(mpls_lse_t));
936 rta_nest_end(rta, nest);
937 rtnh->rtnh_len += rta->rta_len - len;
938 }
939 }
940 }
941
942 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
943 rtnh->rtnh_flags |= RTNH_F_ONLINK;
944
945 if (nexthop->type == NEXTHOP_TYPE_IPV4
946 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
947 {
948 _netlink_route_rta_add_gateway_info (rtmsg->rtm_family, AF_INET, rta,
949 rtnh, NL_PKT_BUF_SIZE, bytelen, nexthop);
950 if (nexthop->rmap_src.ipv4.s_addr)
951 *src = &nexthop->rmap_src;
952 else if (nexthop->src.ipv4.s_addr)
953 *src = &nexthop->src;
954
955 if (IS_ZEBRA_DEBUG_KERNEL)
956 zlog_debug("netlink_route_multipath() (%s): "
957 "nexthop via %s %s if %u",
958 routedesc,
959 inet_ntoa (nexthop->gate.ipv4),
960 label_buf, nexthop->ifindex);
961 }
962 if (nexthop->type == NEXTHOP_TYPE_IPV6
963 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
964 {
965 _netlink_route_rta_add_gateway_info (rtmsg->rtm_family, AF_INET6, rta,
966 rtnh, NL_PKT_BUF_SIZE, bytelen, nexthop);
967
968 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
969 *src = &nexthop->rmap_src;
970 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
971 *src = &nexthop->src;
972
973 if (IS_ZEBRA_DEBUG_KERNEL)
974 zlog_debug("netlink_route_multipath() (%s): "
975 "nexthop via %s %s if %u",
976 routedesc,
977 inet6_ntoa (nexthop->gate.ipv6),
978 label_buf, nexthop->ifindex);
979 }
980 /* ifindex */
981 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
982 || nexthop->type == NEXTHOP_TYPE_IFINDEX)
983 {
984 rtnh->rtnh_ifindex = nexthop->ifindex;
985
986 if (nexthop->rmap_src.ipv4.s_addr)
987 *src = &nexthop->rmap_src;
988 else if (nexthop->src.ipv4.s_addr)
989 *src = &nexthop->src;
990
991 if (IS_ZEBRA_DEBUG_KERNEL)
992 zlog_debug("netlink_route_multipath() (%s): "
993 "nexthop via if %u", routedesc, nexthop->ifindex);
994 }
995 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
996 {
997 rtnh->rtnh_ifindex = nexthop->ifindex;
998
999 if (IS_ZEBRA_DEBUG_KERNEL)
1000 zlog_debug("netlink_route_multipath() (%s): "
1001 "nexthop via if %u", routedesc, nexthop->ifindex);
1002 }
1003 else
1004 {
1005 rtnh->rtnh_ifindex = 0;
1006 }
1007 }
1008
1009 static inline void
1010 _netlink_mpls_build_singlepath(
1011 const char *routedesc,
1012 zebra_nhlfe_t *nhlfe,
1013 struct nlmsghdr *nlmsg,
1014 struct rtmsg *rtmsg,
1015 size_t req_size,
1016 int cmd)
1017 {
1018 int bytelen;
1019 u_char family;
1020
1021 family = NHLFE_FAMILY (nhlfe);
1022 bytelen = (family == AF_INET ? 4 : 16);
1023 _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop,
1024 nlmsg, rtmsg, req_size, cmd);
1025 }
1026
1027
1028 static inline void
1029 _netlink_mpls_build_multipath(
1030 const char *routedesc,
1031 zebra_nhlfe_t *nhlfe,
1032 struct rtattr *rta,
1033 struct rtnexthop *rtnh,
1034 struct rtmsg *rtmsg,
1035 union g_addr **src)
1036 {
1037 int bytelen;
1038 u_char family;
1039
1040 family = NHLFE_FAMILY (nhlfe);
1041 bytelen = (family == AF_INET ? 4 : 16);
1042 _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop,
1043 rta, rtnh, rtmsg, src);
1044 }
1045
1046
1047 /* Log debug information for netlink_route_multipath
1048 * if debug logging is enabled.
1049 *
1050 * @param cmd: Netlink command which is to be processed
1051 * @param p: Prefix for which the change is due
1052 * @param nexthop: Nexthop which is currently processed
1053 * @param routedesc: Semantic annotation for nexthop
1054 * (recursive, multipath, etc.)
1055 * @param family: Address family which the change concerns
1056 */
1057 static void
1058 _netlink_route_debug(
1059 int cmd,
1060 struct prefix *p,
1061 struct nexthop *nexthop,
1062 const char *routedesc,
1063 int family,
1064 struct zebra_vrf *zvrf)
1065 {
1066 if (IS_ZEBRA_DEBUG_KERNEL)
1067 {
1068 char buf[PREFIX_STRLEN];
1069 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
1070 routedesc,
1071 nl_msg_type_to_str (cmd),
1072 prefix2str (p, buf, sizeof(buf)), zvrf_id (zvrf),
1073 (nexthop) ? nexthop_type_to_str (nexthop->type) : "UNK");
1074 }
1075 }
1076
1077 static void
1078 _netlink_mpls_debug(
1079 int cmd,
1080 u_int32_t label,
1081 const char *routedesc)
1082 {
1083 if (IS_ZEBRA_DEBUG_KERNEL)
1084 zlog_debug ("netlink_mpls_multipath() (%s): %s %u/20",
1085 routedesc, nl_msg_type_to_str (cmd), label);
1086 }
1087
1088 static int
1089 netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen)
1090 {
1091 struct {
1092 struct nlmsghdr n;
1093 struct ndmsg ndm;
1094 char buf[256];
1095 } req;
1096
1097 struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
1098
1099 memset(&req.n, 0, sizeof(req.n));
1100 memset(&req.ndm, 0, sizeof(req.ndm));
1101
1102 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1103 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1104 req.n.nlmsg_type = cmd; //RTM_NEWNEIGH or RTM_DELNEIGH
1105 req.ndm.ndm_family = AF_INET;
1106 req.ndm.ndm_state = NUD_PERMANENT;
1107 req.ndm.ndm_ifindex = ifindex;
1108 req.ndm.ndm_type = RTN_UNICAST;
1109
1110 addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
1111 addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
1112
1113 return netlink_talk (&req.n, &zns->netlink_cmd, zns);
1114 }
1115
1116 /* Routing table change via netlink interface. */
1117 /* Update flag indicates whether this is a "replace" or not. */
1118 static int
1119 netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
1120 int update)
1121 {
1122 int bytelen;
1123 struct sockaddr_nl snl;
1124 struct nexthop *nexthop = NULL, *tnexthop;
1125 int recursing;
1126 int nexthop_num;
1127 int discard;
1128 int family = PREFIX_FAMILY(p);
1129 const char *routedesc;
1130 int setsrc = 0;
1131 union g_addr src;
1132
1133 struct
1134 {
1135 struct nlmsghdr n;
1136 struct rtmsg r;
1137 char buf[NL_PKT_BUF_SIZE];
1138 } req;
1139
1140 struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
1141 struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id);
1142
1143 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
1144
1145 bytelen = (family == AF_INET ? 4 : 16);
1146
1147 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1148 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1149 if ((cmd == RTM_NEWROUTE) && update)
1150 req.n.nlmsg_flags |= NLM_F_REPLACE;
1151 req.n.nlmsg_type = cmd;
1152 req.r.rtm_family = family;
1153 req.r.rtm_dst_len = p->prefixlen;
1154 req.r.rtm_protocol = RTPROT_ZEBRA;
1155 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1156
1157 if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
1158 discard = 1;
1159 else
1160 discard = 0;
1161
1162 if (cmd == RTM_NEWROUTE)
1163 {
1164 if (discard)
1165 {
1166 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1167 req.r.rtm_type = RTN_BLACKHOLE;
1168 else if (rib->flags & ZEBRA_FLAG_REJECT)
1169 req.r.rtm_type = RTN_UNREACHABLE;
1170 else
1171 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1172 }
1173 else
1174 req.r.rtm_type = RTN_UNICAST;
1175 }
1176
1177 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1178
1179 /* Metric. */
1180 /* Hardcode the metric for all routes coming from zebra. Metric isn't used
1181 * either by the kernel or by zebra. Its purely for calculating best path(s)
1182 * by the routing protocol and for communicating with protocol peers.
1183 */
1184 addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
1185
1186 /* Table corresponding to this route. */
1187 if (rib->table < 256)
1188 req.r.rtm_table = rib->table;
1189 else
1190 {
1191 req.r.rtm_table = RT_TABLE_UNSPEC;
1192 addattr32(&req.n, sizeof req, RTA_TABLE, rib->table);
1193 }
1194
1195 if (rib->mtu || rib->nexthop_mtu)
1196 {
1197 char buf[NL_PKT_BUF_SIZE];
1198 struct rtattr *rta = (void *) buf;
1199 u_int32_t mtu = rib->mtu;
1200 if (!mtu || (rib->nexthop_mtu && rib->nexthop_mtu < mtu))
1201 mtu = rib->nexthop_mtu;
1202 rta->rta_type = RTA_METRICS;
1203 rta->rta_len = RTA_LENGTH(0);
1204 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu);
1205 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta),
1206 RTA_PAYLOAD (rta));
1207 }
1208
1209 if (discard)
1210 {
1211 if (cmd == RTM_NEWROUTE)
1212 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1213 {
1214 /* We shouldn't encounter recursive nexthops on discard routes,
1215 * but it is probably better to handle that case correctly anyway.
1216 */
1217 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1218 continue;
1219 }
1220 goto skip;
1221 }
1222
1223 /* Count overall nexthops so we can decide whether to use singlepath
1224 * or multipath case. */
1225 nexthop_num = 0;
1226 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1227 {
1228 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1229 continue;
1230 if (cmd == RTM_NEWROUTE && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1231 continue;
1232 if (cmd == RTM_DELROUTE && !CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1233 continue;
1234
1235 nexthop_num++;
1236 }
1237
1238 /* Singlepath case. */
1239 if (nexthop_num == 1 || MULTIPATH_NUM == 1)
1240 {
1241 nexthop_num = 0;
1242 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1243 {
1244 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1245 {
1246 if (!setsrc)
1247 {
1248 if (family == AF_INET)
1249 {
1250 if (nexthop->rmap_src.ipv4.s_addr != 0)
1251 {
1252 src.ipv4 = nexthop->rmap_src.ipv4;
1253 setsrc = 1;
1254 }
1255 else if (nexthop->src.ipv4.s_addr != 0)
1256 {
1257 src.ipv4 = nexthop->src.ipv4;
1258 setsrc = 1;
1259 }
1260 }
1261 else if (family == AF_INET6)
1262 {
1263 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
1264 {
1265 src.ipv6 = nexthop->rmap_src.ipv6;
1266 setsrc = 1;
1267 }
1268 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
1269 {
1270 src.ipv6 = nexthop->src.ipv6;
1271 setsrc = 1;
1272 }
1273 }
1274 }
1275 continue;
1276 }
1277
1278 if ((cmd == RTM_NEWROUTE
1279 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1280 || (cmd == RTM_DELROUTE
1281 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1282 {
1283 routedesc = recursing ? "recursive, 1 hop" : "single hop";
1284
1285 _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf);
1286 _netlink_route_build_singlepath(routedesc, bytelen,
1287 nexthop, &req.n, &req.r,
1288 sizeof req, cmd);
1289 nexthop_num++;
1290 break;
1291 }
1292 }
1293 if (setsrc && (cmd == RTM_NEWROUTE))
1294 {
1295 if (family == AF_INET)
1296 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen);
1297 else if (family == AF_INET6)
1298 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen);
1299 }
1300 }
1301 else
1302 {
1303 char buf[NL_PKT_BUF_SIZE];
1304 struct rtattr *rta = (void *) buf;
1305 struct rtnexthop *rtnh;
1306 union g_addr *src1 = NULL;
1307
1308 rta->rta_type = RTA_MULTIPATH;
1309 rta->rta_len = RTA_LENGTH (0);
1310 rtnh = RTA_DATA (rta);
1311
1312 nexthop_num = 0;
1313 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1314 {
1315 if (nexthop_num >= MULTIPATH_NUM)
1316 break;
1317
1318 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1319 {
1320 /* This only works for IPv4 now */
1321 if (!setsrc)
1322 {
1323 if (family == AF_INET)
1324 {
1325 if (nexthop->rmap_src.ipv4.s_addr != 0)
1326 {
1327 src.ipv4 = nexthop->rmap_src.ipv4;
1328 setsrc = 1;
1329 }
1330 else if (nexthop->src.ipv4.s_addr != 0)
1331 {
1332 src.ipv4 = nexthop->src.ipv4;
1333 setsrc = 1;
1334 }
1335 }
1336 else if (family == AF_INET6)
1337 {
1338 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
1339 {
1340 src.ipv6 = nexthop->rmap_src.ipv6;
1341 setsrc = 1;
1342 }
1343 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
1344 {
1345 src.ipv6 = nexthop->src.ipv6;
1346 setsrc = 1;
1347 }
1348 }
1349 }
1350 continue;
1351 }
1352
1353 if ((cmd == RTM_NEWROUTE
1354 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1355 || (cmd == RTM_DELROUTE
1356 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1357 {
1358 routedesc = recursing ? "recursive, multihop" : "multihop";
1359 nexthop_num++;
1360
1361 _netlink_route_debug(cmd, p, nexthop,
1362 routedesc, family, zvrf);
1363 _netlink_route_build_multipath(routedesc, bytelen,
1364 nexthop, rta, rtnh, &req.r, &src1);
1365 rtnh = RTNH_NEXT (rtnh);
1366
1367 if (!setsrc && src1)
1368 {
1369 if (family == AF_INET)
1370 src.ipv4 = src1->ipv4;
1371 else if (family == AF_INET6)
1372 src.ipv6 = src1->ipv6;
1373
1374 setsrc = 1;
1375 }
1376 }
1377 }
1378 if (setsrc && (cmd == RTM_NEWROUTE))
1379 {
1380 if (family == AF_INET)
1381 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen);
1382 else if (family == AF_INET6)
1383 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen);
1384 if (IS_ZEBRA_DEBUG_KERNEL)
1385 zlog_debug("Setting source");
1386 }
1387
1388 if (rta->rta_len > RTA_LENGTH (0))
1389 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
1390 RTA_PAYLOAD (rta));
1391 }
1392
1393 /* If there is no useful nexthop then return. */
1394 if (nexthop_num == 0)
1395 {
1396 if (IS_ZEBRA_DEBUG_KERNEL)
1397 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
1398 return 0;
1399 }
1400
1401 skip:
1402
1403 /* Destination netlink address. */
1404 memset (&snl, 0, sizeof snl);
1405 snl.nl_family = AF_NETLINK;
1406
1407 /* Talk to netlink socket. */
1408 return netlink_talk (&req.n, &zns->netlink_cmd, zns);
1409 }
1410
1411 int
1412 kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new)
1413 {
1414 if (!old && new)
1415 return netlink_route_multipath (RTM_NEWROUTE, p, new, 0);
1416 if (old && !new)
1417 return netlink_route_multipath (RTM_DELROUTE, p, old, 0);
1418
1419 return netlink_route_multipath (RTM_NEWROUTE, p, new, 1);
1420 }
1421
1422 int
1423 kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen)
1424 {
1425 return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex, addr,
1426 lla, llalen);
1427 }
1428
1429 /*
1430 * MPLS label forwarding table change via netlink interface.
1431 */
1432 int
1433 netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp)
1434 {
1435 mpls_lse_t lse;
1436 zebra_nhlfe_t *nhlfe;
1437 struct nexthop *nexthop = NULL;
1438 int nexthop_num;
1439 const char *routedesc;
1440 struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
1441
1442 struct
1443 {
1444 struct nlmsghdr n;
1445 struct rtmsg r;
1446 char buf[NL_PKT_BUF_SIZE];
1447 } req;
1448
1449 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
1450
1451
1452 /*
1453 * Count # nexthops so we can decide whether to use singlepath
1454 * or multipath case.
1455 */
1456 nexthop_num = 0;
1457 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
1458 {
1459 nexthop = nhlfe->nexthop;
1460 if (!nexthop)
1461 continue;
1462 if (cmd == RTM_NEWROUTE)
1463 {
1464 /* Count all selected NHLFEs */
1465 if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) &&
1466 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1467 nexthop_num++;
1468 }
1469 else /* DEL */
1470 {
1471 /* Count all installed NHLFEs */
1472 if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) &&
1473 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1474 nexthop_num++;
1475 }
1476 }
1477
1478 if (nexthop_num == 0) // unexpected
1479 return 0;
1480
1481 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1482 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1483 req.n.nlmsg_type = cmd;
1484 req.r.rtm_family = AF_MPLS;
1485 req.r.rtm_table = RT_TABLE_MAIN;
1486 req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
1487 req.r.rtm_protocol = RTPROT_ZEBRA;
1488 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1489 req.r.rtm_type = RTN_UNICAST;
1490
1491 if (cmd == RTM_NEWROUTE)
1492 /* We do a replace to handle update. */
1493 req.n.nlmsg_flags |= NLM_F_REPLACE;
1494
1495 /* Fill destination */
1496 lse = mpls_lse_encode (lsp->ile.in_label, 0, 0, 1);
1497 addattr_l (&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t));
1498
1499 /* Fill nexthops (paths) based on single-path or multipath. The paths
1500 * chosen depend on the operation.
1501 */
1502 if (nexthop_num == 1 || MULTIPATH_NUM == 1)
1503 {
1504 routedesc = "single hop";
1505 _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
1506
1507 nexthop_num = 0;
1508 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
1509 {
1510 nexthop = nhlfe->nexthop;
1511 if (!nexthop)
1512 continue;
1513
1514 if ((cmd == RTM_NEWROUTE &&
1515 (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) &&
1516 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) ||
1517 (cmd == RTM_DELROUTE &&
1518 (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) &&
1519 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))))
1520 {
1521 /* Add the gateway */
1522 _netlink_mpls_build_singlepath(routedesc, nhlfe,
1523 &req.n, &req.r, sizeof req, cmd);
1524 if (cmd == RTM_NEWROUTE)
1525 {
1526 SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
1527 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1528 }
1529 else
1530 {
1531 UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
1532 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1533 }
1534 nexthop_num++;
1535 break;
1536 }
1537 }
1538 }
1539 else /* Multipath case */
1540 {
1541 char buf[NL_PKT_BUF_SIZE];
1542 struct rtattr *rta = (void *) buf;
1543 struct rtnexthop *rtnh;
1544 union g_addr *src1 = NULL;
1545
1546 rta->rta_type = RTA_MULTIPATH;
1547 rta->rta_len = RTA_LENGTH (0);
1548 rtnh = RTA_DATA (rta);
1549
1550 routedesc = "multihop";
1551 _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
1552
1553 nexthop_num = 0;
1554 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
1555 {
1556 nexthop = nhlfe->nexthop;
1557 if (!nexthop)
1558 continue;
1559
1560 if (MULTIPATH_NUM != 0 && nexthop_num >= MULTIPATH_NUM)
1561 break;
1562
1563 if ((cmd == RTM_NEWROUTE &&
1564 (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) &&
1565 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) ||
1566 (cmd == RTM_DELROUTE &&
1567 (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) &&
1568 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))))
1569 {
1570 nexthop_num++;
1571
1572 /* Build the multipath */
1573 _netlink_mpls_build_multipath(routedesc, nhlfe, rta,
1574 rtnh, &req.r, &src1);
1575 rtnh = RTNH_NEXT (rtnh);
1576
1577 if (cmd == RTM_NEWROUTE)
1578 {
1579 SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
1580 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1581 }
1582 else
1583 {
1584 UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
1585 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1586 }
1587
1588 }
1589 }
1590
1591 /* Add the multipath */
1592 if (rta->rta_len > RTA_LENGTH (0))
1593 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
1594 RTA_PAYLOAD (rta));
1595 }
1596
1597 /* Talk to netlink socket. */
1598 return netlink_talk (&req.n, &zns->netlink_cmd, zns);
1599 }
1600
1601 /*
1602 * Handle failure in LSP install, clear flags for NHLFE.
1603 */
1604 void
1605 clear_nhlfe_installed (zebra_lsp_t *lsp)
1606 {
1607 zebra_nhlfe_t *nhlfe;
1608 struct nexthop *nexthop;
1609
1610 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
1611 {
1612 nexthop = nhlfe->nexthop;
1613 if (!nexthop)
1614 continue;
1615
1616 UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
1617 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1618 }
1619 }