Annotation of embedaddon/quagga/zebra/zebra_rib.c, revision 1.1.1.4
1.1 misho 1: /* Routing Information Base.
2: * Copyright (C) 1997, 98, 99, 2001 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:
24: #include "prefix.h"
25: #include "table.h"
26: #include "memory.h"
27: #include "str.h"
28: #include "command.h"
29: #include "if.h"
30: #include "log.h"
31: #include "sockunion.h"
32: #include "linklist.h"
33: #include "thread.h"
34: #include "workqueue.h"
35: #include "prefix.h"
36: #include "routemap.h"
1.1.1.4 ! misho 37: #include "vrf.h"
1.1 misho 38:
39: #include "zebra/rib.h"
40: #include "zebra/rt.h"
41: #include "zebra/zserv.h"
42: #include "zebra/redistribute.h"
43: #include "zebra/debug.h"
1.1.1.3 misho 44: #include "zebra/zebra_fpm.h"
1.1 misho 45:
46: /* Default rtm_table for all clients */
47: extern struct zebra_t zebrad;
48:
49: /* Hold time for RIB process, should be very minimal.
50: * it is useful to able to set it otherwise for testing, hence exported
51: * as global here for test-rig code.
52: */
53: int rib_process_hold_time = 10;
54:
55: /* Each route type's string and default distance value. */
56: static const struct
57: {
58: int key;
59: int distance;
1.1.1.2 misho 60: } route_info[ZEBRA_ROUTE_MAX] =
1.1 misho 61: {
1.1.1.2 misho 62: [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0},
63: [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0},
64: [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0},
65: [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1},
66: [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120},
67: [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120},
68: [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110},
69: [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110},
70: [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115},
71: [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */},
72: [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 95},
73: /* no entry/default: 150 */
1.1 misho 74: };
75:
1.1.1.4 ! misho 76: /* RPF lookup behaviour */
! 77: static enum multicast_mode ipv4_multicast_mode = MCAST_NO_CONFIG;
1.1 misho 78:
1.1.1.4 ! misho 79: static void __attribute__((format (printf, 4, 5)))
! 80: _rnode_zlog(const char *_func, struct route_node *rn, int priority,
! 81: const char *msgfmt, ...)
1.1 misho 82: {
1.1.1.4 ! misho 83: char prefix[PREFIX_STRLEN], buf[256];
! 84: char msgbuf[512];
! 85: va_list ap;
1.1 misho 86:
1.1.1.4 ! misho 87: va_start(ap, msgfmt);
! 88: vsnprintf(msgbuf, sizeof(msgbuf), msgfmt, ap);
! 89: va_end(ap);
1.1 misho 90:
1.1.1.4 ! misho 91: if (rn)
! 92: {
! 93: rib_table_info_t *info = rn->table->info;
1.1 misho 94:
1.1.1.4 ! misho 95: snprintf(buf, sizeof(buf), "%s%s vrf %u",
! 96: prefix2str(&rn->p, prefix, sizeof(prefix)),
! 97: info->safi == SAFI_MULTICAST ? " (MRIB)" : "",
! 98: info->zvrf->vrf_id);
! 99: }
! 100: else
! 101: {
! 102: snprintf(buf, sizeof(buf), "{(route_node *) NULL}");
! 103: }
1.1.1.3 misho 104:
1.1.1.4 ! misho 105: zlog (NULL, priority, "%s: %s: %s", _func, buf, msgbuf);
1.1 misho 106: }
107:
1.1.1.4 ! misho 108: #define rnode_debug(node, ...) \
! 109: _rnode_zlog(__func__, node, LOG_DEBUG, __VA_ARGS__)
! 110: #define rnode_info(node, ...) \
! 111: _rnode_zlog(__func__, node, LOG_INFO, __VA_ARGS__)
1.1.1.3 misho 112:
113: /*
114: * nexthop_type_to_str
115: */
116: const char *
117: nexthop_type_to_str (enum nexthop_types_t nh_type)
118: {
119: static const char *desc[] = {
120: "none",
121: "Directly connected",
122: "Interface route",
123: "IPv4 nexthop",
124: "IPv4 nexthop with ifindex",
125: "IPv4 nexthop with ifname",
126: "IPv6 nexthop",
127: "IPv6 nexthop with ifindex",
128: "IPv6 nexthop with ifname",
129: "Null0 nexthop",
130: };
131:
132: if (nh_type >= ZEBRA_NUM_OF (desc))
133: return "<Invalid nh type>";
134:
135: return desc[nh_type];
136: }
137:
1.1.1.4 ! misho 138: /* Add nexthop to the end of a nexthop list. */
1.1 misho 139: static void
1.1.1.4 ! misho 140: _nexthop_add (struct nexthop **target, struct nexthop *nexthop)
1.1 misho 141: {
142: struct nexthop *last;
143:
1.1.1.4 ! misho 144: for (last = *target; last && last->next; last = last->next)
1.1 misho 145: ;
146: if (last)
147: last->next = nexthop;
148: else
1.1.1.4 ! misho 149: *target = nexthop;
1.1 misho 150: nexthop->prev = last;
1.1.1.4 ! misho 151: }
1.1 misho 152:
1.1.1.4 ! misho 153: /* Add nexthop to the end of a rib node's nexthop list */
! 154: static void
! 155: nexthop_add (struct rib *rib, struct nexthop *nexthop)
! 156: {
! 157: _nexthop_add(&rib->nexthop, nexthop);
1.1 misho 158: rib->nexthop_num++;
159: }
160:
161: /* Delete specified nexthop from the list. */
162: static void
163: nexthop_delete (struct rib *rib, struct nexthop *nexthop)
164: {
165: if (nexthop->next)
166: nexthop->next->prev = nexthop->prev;
167: if (nexthop->prev)
168: nexthop->prev->next = nexthop->next;
169: else
170: rib->nexthop = nexthop->next;
171: rib->nexthop_num--;
172: }
173:
1.1.1.4 ! misho 174: static void nexthops_free(struct nexthop *nexthop);
! 175:
1.1 misho 176: /* Free nexthop. */
177: static void
178: nexthop_free (struct nexthop *nexthop)
179: {
180: if (nexthop->ifname)
181: XFREE (0, nexthop->ifname);
1.1.1.4 ! misho 182: if (nexthop->resolved)
! 183: nexthops_free(nexthop->resolved);
1.1 misho 184: XFREE (MTYPE_NEXTHOP, nexthop);
185: }
186:
1.1.1.4 ! misho 187: /* Frees a list of nexthops */
! 188: static void
! 189: nexthops_free (struct nexthop *nexthop)
! 190: {
! 191: struct nexthop *nh, *next;
! 192:
! 193: for (nh = nexthop; nh; nh = next)
! 194: {
! 195: next = nh->next;
! 196: nexthop_free (nh);
! 197: }
! 198: }
! 199:
1.1 misho 200: struct nexthop *
1.1.1.4 ! misho 201: nexthop_ifindex_add (struct rib *rib, ifindex_t ifindex)
1.1 misho 202: {
203: struct nexthop *nexthop;
204:
205: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
206: nexthop->type = NEXTHOP_TYPE_IFINDEX;
207: nexthop->ifindex = ifindex;
208:
209: nexthop_add (rib, nexthop);
210:
211: return nexthop;
212: }
213:
214: struct nexthop *
215: nexthop_ifname_add (struct rib *rib, char *ifname)
216: {
217: struct nexthop *nexthop;
218:
219: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
220: nexthop->type = NEXTHOP_TYPE_IFNAME;
221: nexthop->ifname = XSTRDUP (0, ifname);
222:
223: nexthop_add (rib, nexthop);
224:
225: return nexthop;
226: }
227:
228: struct nexthop *
229: nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
230: {
231: struct nexthop *nexthop;
232:
233: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
234: nexthop->type = NEXTHOP_TYPE_IPV4;
235: nexthop->gate.ipv4 = *ipv4;
236: if (src)
237: nexthop->src.ipv4 = *src;
238:
239: nexthop_add (rib, nexthop);
240:
241: return nexthop;
242: }
243:
1.1.1.2 misho 244: struct nexthop *
1.1 misho 245: nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
1.1.1.4 ! misho 246: struct in_addr *src, ifindex_t ifindex)
1.1 misho 247: {
248: struct nexthop *nexthop;
249:
250: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
251: nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
252: nexthop->gate.ipv4 = *ipv4;
253: if (src)
254: nexthop->src.ipv4 = *src;
255: nexthop->ifindex = ifindex;
256:
257: nexthop_add (rib, nexthop);
258:
259: return nexthop;
260: }
261:
262: struct nexthop *
263: nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
264: {
265: struct nexthop *nexthop;
266:
267: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
268: nexthop->type = NEXTHOP_TYPE_IPV6;
269: nexthop->gate.ipv6 = *ipv6;
270:
271: nexthop_add (rib, nexthop);
272:
273: return nexthop;
274: }
275:
276: static struct nexthop *
277: nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
278: char *ifname)
279: {
280: struct nexthop *nexthop;
281:
282: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
283: nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
284: nexthop->gate.ipv6 = *ipv6;
285: nexthop->ifname = XSTRDUP (0, ifname);
286:
287: nexthop_add (rib, nexthop);
288:
289: return nexthop;
290: }
291:
292: static struct nexthop *
293: nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
1.1.1.4 ! misho 294: ifindex_t ifindex)
1.1 misho 295: {
296: struct nexthop *nexthop;
297:
298: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
299: nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
300: nexthop->gate.ipv6 = *ipv6;
301: nexthop->ifindex = ifindex;
302:
303: nexthop_add (rib, nexthop);
304:
305: return nexthop;
306: }
307:
308: struct nexthop *
309: nexthop_blackhole_add (struct rib *rib)
310: {
311: struct nexthop *nexthop;
312:
313: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
314: nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
315: SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
316:
317: nexthop_add (rib, nexthop);
318:
319: return nexthop;
320: }
321:
1.1.1.4 ! misho 322: /* This method checks whether a recursive nexthop has at
! 323: * least one resolved nexthop in the fib.
! 324: */
! 325: int
! 326: nexthop_has_fib_child(struct nexthop *nexthop)
! 327: {
! 328: struct nexthop *nh;
! 329:
! 330: if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
! 331: return 0;
! 332:
! 333: for (nh = nexthop->resolved; nh; nh = nh->next)
! 334: if (CHECK_FLAG (nh->flags, NEXTHOP_FLAG_FIB))
! 335: return 1;
! 336:
! 337: return 0;
! 338: }
! 339:
1.1 misho 340: /* If force flag is not set, do not modify falgs at all for uninstall
341: the route from FIB. */
342: static int
343: nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
344: struct route_node *top)
345: {
346: struct prefix_ipv4 p;
347: struct route_table *table;
348: struct route_node *rn;
349: struct rib *match;
1.1.1.4 ! misho 350: int resolved;
1.1 misho 351: struct nexthop *newhop;
1.1.1.4 ! misho 352: struct nexthop *resolved_hop;
1.1 misho 353:
354: if (nexthop->type == NEXTHOP_TYPE_IPV4)
355: nexthop->ifindex = 0;
356:
357: if (set)
1.1.1.4 ! misho 358: {
! 359: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
! 360: nexthops_free(nexthop->resolved);
! 361: nexthop->resolved = NULL;
! 362: rib->nexthop_mtu = 0;
! 363: }
1.1 misho 364:
365: /* Make lookup prefix. */
366: memset (&p, 0, sizeof (struct prefix_ipv4));
367: p.family = AF_INET;
368: p.prefixlen = IPV4_MAX_PREFIXLEN;
369: p.prefix = nexthop->gate.ipv4;
370:
371: /* Lookup table. */
1.1.1.4 ! misho 372: table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, rib->vrf_id);
1.1 misho 373: if (! table)
374: return 0;
375:
376: rn = route_node_match (table, (struct prefix *) &p);
377: while (rn)
378: {
379: route_unlock_node (rn);
380:
381: /* If lookup self prefix return immediately. */
382: if (rn == top)
383: return 0;
384:
385: /* Pick up selected route. */
1.1.1.3 misho 386: RNODE_FOREACH_RIB (rn, match)
1.1 misho 387: {
388: if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
389: continue;
1.1.1.4 ! misho 390: if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
1.1 misho 391: break;
392: }
393:
394: /* If there is no selected route or matched route is EGP, go up
395: tree. */
396: if (! match
397: || match->type == ZEBRA_ROUTE_BGP)
398: {
399: do {
400: rn = rn->parent;
401: } while (rn && rn->info == NULL);
402: if (rn)
403: route_lock_node (rn);
404: }
405: else
406: {
1.1.1.4 ! misho 407: /* If the longest prefix match for the nexthop yields
! 408: * a blackhole, mark it as inactive. */
! 409: if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
! 410: || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
! 411: return 0;
! 412:
1.1 misho 413: if (match->type == ZEBRA_ROUTE_CONNECT)
414: {
415: /* Directly point connected route. */
416: newhop = match->nexthop;
417: if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
418: nexthop->ifindex = newhop->ifindex;
419:
420: return 1;
421: }
422: else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
423: {
1.1.1.4 ! misho 424: resolved = 0;
1.1 misho 425: for (newhop = match->nexthop; newhop; newhop = newhop->next)
426: if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
427: && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
428: {
429: if (set)
430: {
431: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
1.1.1.4 ! misho 432:
! 433: resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
! 434: SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
! 435: /* If the resolving route specifies a gateway, use it */
! 436: if (newhop->type == NEXTHOP_TYPE_IPV4
! 437: || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX
! 438: || newhop->type == NEXTHOP_TYPE_IPV4_IFNAME)
! 439: {
! 440: resolved_hop->type = newhop->type;
! 441: resolved_hop->gate.ipv4 = newhop->gate.ipv4;
! 442: resolved_hop->ifindex = newhop->ifindex;
! 443: }
! 444:
! 445: /* If the resolving route is an interface route, it
! 446: * means the gateway we are looking up is connected
! 447: * to that interface. Therefore, the resolved route
! 448: * should have the original gateway as nexthop as it
! 449: * is directly connected. */
1.1 misho 450: if (newhop->type == NEXTHOP_TYPE_IFINDEX
1.1.1.4 ! misho 451: || newhop->type == NEXTHOP_TYPE_IFNAME)
! 452: {
! 453: resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
! 454: resolved_hop->gate.ipv4 = nexthop->gate.ipv4;
! 455: resolved_hop->ifindex = newhop->ifindex;
! 456: }
! 457:
! 458: _nexthop_add(&nexthop->resolved, resolved_hop);
1.1 misho 459: }
1.1.1.4 ! misho 460: resolved = 1;
1.1 misho 461: }
1.1.1.4 ! misho 462: if (resolved && set)
! 463: rib->nexthop_mtu = match->mtu;
! 464: return resolved;
1.1 misho 465: }
466: else
467: {
468: return 0;
469: }
470: }
471: }
472: return 0;
473: }
474:
475: /* If force flag is not set, do not modify falgs at all for uninstall
476: the route from FIB. */
477: static int
478: nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
479: struct route_node *top)
480: {
481: struct prefix_ipv6 p;
482: struct route_table *table;
483: struct route_node *rn;
484: struct rib *match;
1.1.1.4 ! misho 485: int resolved;
1.1 misho 486: struct nexthop *newhop;
1.1.1.4 ! misho 487: struct nexthop *resolved_hop;
1.1 misho 488:
489: if (nexthop->type == NEXTHOP_TYPE_IPV6)
490: nexthop->ifindex = 0;
491:
492: if (set)
1.1.1.4 ! misho 493: {
! 494: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
! 495: nexthops_free(nexthop->resolved);
! 496: nexthop->resolved = NULL;
! 497: }
1.1 misho 498:
499: /* Make lookup prefix. */
500: memset (&p, 0, sizeof (struct prefix_ipv6));
501: p.family = AF_INET6;
502: p.prefixlen = IPV6_MAX_PREFIXLEN;
503: p.prefix = nexthop->gate.ipv6;
504:
505: /* Lookup table. */
1.1.1.4 ! misho 506: table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, rib->vrf_id);
1.1 misho 507: if (! table)
508: return 0;
509:
510: rn = route_node_match (table, (struct prefix *) &p);
511: while (rn)
512: {
513: route_unlock_node (rn);
514:
515: /* If lookup self prefix return immediately. */
516: if (rn == top)
517: return 0;
518:
519: /* Pick up selected route. */
1.1.1.3 misho 520: RNODE_FOREACH_RIB (rn, match)
1.1 misho 521: {
522: if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
523: continue;
1.1.1.4 ! misho 524: if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
1.1 misho 525: break;
526: }
527:
528: /* If there is no selected route or matched route is EGP, go up
529: tree. */
530: if (! match
531: || match->type == ZEBRA_ROUTE_BGP)
532: {
533: do {
534: rn = rn->parent;
535: } while (rn && rn->info == NULL);
536: if (rn)
537: route_lock_node (rn);
538: }
539: else
540: {
1.1.1.4 ! misho 541: /* If the longest prefix match for the nexthop yields
! 542: * a blackhole, mark it as inactive. */
! 543: if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE)
! 544: || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT))
! 545: return 0;
! 546:
1.1 misho 547: if (match->type == ZEBRA_ROUTE_CONNECT)
548: {
549: /* Directly point connected route. */
550: newhop = match->nexthop;
551:
552: if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
553: nexthop->ifindex = newhop->ifindex;
554:
555: return 1;
556: }
557: else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
558: {
1.1.1.4 ! misho 559: resolved = 0;
1.1 misho 560: for (newhop = match->nexthop; newhop; newhop = newhop->next)
561: if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
562: && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
563: {
564: if (set)
565: {
566: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
1.1.1.4 ! misho 567:
! 568: resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop));
! 569: SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
! 570: /* See nexthop_active_ipv4 for a description how the
! 571: * resolved nexthop is constructed. */
1.1 misho 572: if (newhop->type == NEXTHOP_TYPE_IPV6
573: || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
574: || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1.1.1.4 ! misho 575: {
! 576: resolved_hop->type = newhop->type;
! 577: resolved_hop->gate.ipv6 = newhop->gate.ipv6;
! 578:
! 579: if (newhop->ifindex)
! 580: {
! 581: resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
! 582: resolved_hop->ifindex = newhop->ifindex;
! 583: }
! 584: }
! 585:
1.1 misho 586: if (newhop->type == NEXTHOP_TYPE_IFINDEX
1.1.1.4 ! misho 587: || newhop->type == NEXTHOP_TYPE_IFNAME)
! 588: {
! 589: resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
! 590: resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
! 591: resolved_hop->gate.ipv6 = nexthop->gate.ipv6;
! 592: resolved_hop->ifindex = newhop->ifindex;
! 593: }
! 594:
! 595: _nexthop_add(&nexthop->resolved, resolved_hop);
1.1 misho 596: }
1.1.1.4 ! misho 597: resolved = 1;
1.1 misho 598: }
1.1.1.4 ! misho 599: return resolved;
1.1 misho 600: }
601: else
602: {
603: return 0;
604: }
605: }
606: }
607: return 0;
608: }
609:
610: struct rib *
1.1.1.4 ! misho 611: rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
! 612: struct route_node **rn_out, vrf_id_t vrf_id)
1.1 misho 613: {
614: struct route_table *table;
615: struct route_node *rn;
616: struct rib *match;
1.1.1.4 ! misho 617: struct nexthop *newhop, *tnewhop;
! 618: int recursing;
1.1 misho 619:
620: /* Lookup table. */
1.1.1.4 ! misho 621: table = zebra_vrf_table (AFI_IP, safi, vrf_id);
1.1 misho 622: if (! table)
623: return 0;
624:
1.1.1.4 ! misho 625: rn = route_node_match_ipv4 (table, &addr);
1.1 misho 626:
627: while (rn)
628: {
629: route_unlock_node (rn);
1.1.1.4 ! misho 630:
1.1 misho 631: /* Pick up selected route. */
1.1.1.3 misho 632: RNODE_FOREACH_RIB (rn, match)
1.1 misho 633: {
634: if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
635: continue;
1.1.1.4 ! misho 636: if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
1.1 misho 637: break;
638: }
639:
640: /* If there is no selected route or matched route is EGP, go up
641: tree. */
1.1.1.4 ! misho 642: if (!match || (skip_bgp && (match->type == ZEBRA_ROUTE_BGP)))
1.1 misho 643: {
644: do {
645: rn = rn->parent;
646: } while (rn && rn->info == NULL);
647: if (rn)
648: route_lock_node (rn);
649: }
650: else
651: {
1.1.1.4 ! misho 652: if (match->type != ZEBRA_ROUTE_CONNECT)
1.1 misho 653: {
1.1.1.4 ! misho 654: int found = 0;
! 655: for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
1.1 misho 656: if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
1.1.1.4 ! misho 657: {
! 658: found = 1;
! 659: break;
! 660: }
! 661: if (!found)
! 662: return NULL;
1.1 misho 663: }
1.1.1.4 ! misho 664:
! 665: if (rn_out)
! 666: *rn_out = rn;
! 667: return match;
1.1 misho 668: }
669: }
670: return NULL;
671: }
672:
673: struct rib *
1.1.1.4 ! misho 674: rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out,
! 675: vrf_id_t vrf_id)
! 676: {
! 677: struct rib *rib = NULL, *mrib = NULL, *urib = NULL;
! 678: struct route_node *m_rn = NULL, *u_rn = NULL;
! 679: int skip_bgp = 0; /* bool */
! 680:
! 681: switch (ipv4_multicast_mode)
! 682: {
! 683: case MCAST_MRIB_ONLY:
! 684: return rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, rn_out,
! 685: vrf_id);
! 686: case MCAST_URIB_ONLY:
! 687: return rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, rn_out,
! 688: vrf_id);
! 689: case MCAST_NO_CONFIG:
! 690: case MCAST_MIX_MRIB_FIRST:
! 691: rib = mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
! 692: vrf_id);
! 693: if (!mrib)
! 694: rib = urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
! 695: vrf_id);
! 696: break;
! 697: case MCAST_MIX_DISTANCE:
! 698: mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
! 699: vrf_id);
! 700: urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
! 701: vrf_id);
! 702: if (mrib && urib)
! 703: rib = urib->distance < mrib->distance ? urib : mrib;
! 704: else if (mrib)
! 705: rib = mrib;
! 706: else if (urib)
! 707: rib = urib;
! 708: break;
! 709: case MCAST_MIX_PFXLEN:
! 710: mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn,
! 711: vrf_id);
! 712: urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn,
! 713: vrf_id);
! 714: if (mrib && urib)
! 715: rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib;
! 716: else if (mrib)
! 717: rib = mrib;
! 718: else if (urib)
! 719: rib = urib;
! 720: break;
! 721: }
! 722:
! 723: if (rn_out)
! 724: *rn_out = (rib == mrib) ? m_rn : u_rn;
! 725:
! 726: if (IS_ZEBRA_DEBUG_RIB)
! 727: {
! 728: char buf[BUFSIZ];
! 729: inet_ntop (AF_INET, &addr, buf, BUFSIZ);
! 730:
! 731: zlog_debug("%s: %s vrf %u: found %s, using %s",
! 732: __func__, buf, vrf_id,
! 733: mrib ? (urib ? "MRIB+URIB" : "MRIB") :
! 734: urib ? "URIB" : "nothing",
! 735: rib == urib ? "URIB" : rib == mrib ? "MRIB" : "none");
! 736: }
! 737: return rib;
! 738: }
! 739:
! 740: void
! 741: multicast_mode_ipv4_set (enum multicast_mode mode)
! 742: {
! 743: if (IS_ZEBRA_DEBUG_RIB)
! 744: zlog_debug("%s: multicast lookup mode set (%d)", __func__, mode);
! 745: ipv4_multicast_mode = mode;
! 746: }
! 747:
! 748: enum multicast_mode
! 749: multicast_mode_ipv4_get (void)
! 750: {
! 751: return ipv4_multicast_mode;
! 752: }
! 753:
! 754: struct rib *
! 755: rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id)
1.1 misho 756: {
757: struct route_table *table;
758: struct route_node *rn;
759: struct rib *match;
1.1.1.4 ! misho 760: struct nexthop *nexthop, *tnexthop;
! 761: int recursing;
1.1 misho 762:
763: /* Lookup table. */
1.1.1.4 ! misho 764: table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
1.1 misho 765: if (! table)
766: return 0;
767:
768: rn = route_node_lookup (table, (struct prefix *) p);
769:
770: /* No route for this prefix. */
771: if (! rn)
772: return NULL;
773:
774: /* Unlock node. */
775: route_unlock_node (rn);
776:
1.1.1.3 misho 777: RNODE_FOREACH_RIB (rn, match)
1.1 misho 778: {
779: if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
780: continue;
1.1.1.4 ! misho 781: if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
1.1 misho 782: break;
783: }
784:
785: if (! match || match->type == ZEBRA_ROUTE_BGP)
786: return NULL;
787:
788: if (match->type == ZEBRA_ROUTE_CONNECT)
789: return match;
790:
1.1.1.4 ! misho 791: for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
1.1 misho 792: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
793: return match;
794:
795: return NULL;
796: }
797:
798: /*
799: * This clone function, unlike its original rib_lookup_ipv4(), checks
800: * if specified IPv4 route record (prefix/mask -> gate) exists in
801: * the whole RIB and has ZEBRA_FLAG_SELECTED set.
802: *
803: * Return values:
804: * -1: error
805: * 0: exact match found
806: * 1: a match was found with a different gate
807: * 2: connected route found
808: * 3: no matches found
809: */
810: int
1.1.1.4 ! misho 811: rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate,
! 812: vrf_id_t vrf_id)
1.1 misho 813: {
814: struct route_table *table;
815: struct route_node *rn;
816: struct rib *match;
1.1.1.4 ! misho 817: struct nexthop *nexthop, *tnexthop;
! 818: int recursing;
! 819: int nexthops_active;
1.1 misho 820:
821: /* Lookup table. */
1.1.1.4 ! misho 822: table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
1.1 misho 823: if (! table)
824: return ZEBRA_RIB_LOOKUP_ERROR;
825:
826: /* Scan the RIB table for exactly matching RIB entry. */
827: rn = route_node_lookup (table, (struct prefix *) p);
828:
829: /* No route for this prefix. */
830: if (! rn)
831: return ZEBRA_RIB_NOTFOUND;
832:
833: /* Unlock node. */
834: route_unlock_node (rn);
835:
836: /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
1.1.1.3 misho 837: RNODE_FOREACH_RIB (rn, match)
1.1 misho 838: {
839: if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
840: continue;
1.1.1.4 ! misho 841: if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
1.1 misho 842: break;
843: }
844:
845: /* None such found :( */
846: if (!match)
847: return ZEBRA_RIB_NOTFOUND;
848:
849: if (match->type == ZEBRA_ROUTE_CONNECT)
850: return ZEBRA_RIB_FOUND_CONNECTED;
851:
852: /* Ok, we have a cood candidate, let's check it's nexthop list... */
1.1.1.4 ! misho 853: nexthops_active = 0;
! 854: for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
1.1 misho 855: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
856: {
1.1.1.4 ! misho 857: nexthops_active = 1;
! 858: if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate))
! 859: return ZEBRA_RIB_FOUND_EXACT;
1.1 misho 860: if (IS_ZEBRA_DEBUG_RIB)
1.1.1.4 ! misho 861: {
! 862: char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
! 863: inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
! 864: inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
! 865: zlog_debug ("%s: qgate == %s, %s == %s", __func__,
! 866: qgate_buf, recursing ? "rgate" : "gate", gate_buf);
! 867: }
1.1 misho 868: }
1.1.1.4 ! misho 869:
! 870: if (nexthops_active)
! 871: return ZEBRA_RIB_FOUND_NOGATE;
1.1 misho 872:
873: return ZEBRA_RIB_NOTFOUND;
874: }
875:
876: struct rib *
1.1.1.4 ! misho 877: rib_match_ipv6 (struct in6_addr *addr, vrf_id_t vrf_id)
1.1 misho 878: {
879: struct prefix_ipv6 p;
880: struct route_table *table;
881: struct route_node *rn;
882: struct rib *match;
1.1.1.4 ! misho 883: struct nexthop *newhop, *tnewhop;
! 884: int recursing;
1.1 misho 885:
886: /* Lookup table. */
1.1.1.4 ! misho 887: table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
1.1 misho 888: if (! table)
889: return 0;
890:
891: memset (&p, 0, sizeof (struct prefix_ipv6));
892: p.family = AF_INET6;
893: p.prefixlen = IPV6_MAX_PREFIXLEN;
894: IPV6_ADDR_COPY (&p.prefix, addr);
895:
896: rn = route_node_match (table, (struct prefix *) &p);
897:
898: while (rn)
899: {
900: route_unlock_node (rn);
901:
902: /* Pick up selected route. */
1.1.1.3 misho 903: RNODE_FOREACH_RIB (rn, match)
1.1 misho 904: {
905: if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
906: continue;
1.1.1.4 ! misho 907: if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
1.1 misho 908: break;
909: }
910:
911: /* If there is no selected route or matched route is EGP, go up
912: tree. */
913: if (! match
914: || match->type == ZEBRA_ROUTE_BGP)
915: {
916: do {
917: rn = rn->parent;
918: } while (rn && rn->info == NULL);
919: if (rn)
920: route_lock_node (rn);
921: }
922: else
923: {
924: if (match->type == ZEBRA_ROUTE_CONNECT)
925: /* Directly point connected route. */
926: return match;
927: else
928: {
1.1.1.4 ! misho 929: for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
1.1 misho 930: if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
931: return match;
932: return NULL;
933: }
934: }
935: }
936: return NULL;
937: }
938:
939: #define RIB_SYSTEM_ROUTE(R) \
940: ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
941:
942: /* This function verifies reachability of one given nexthop, which can be
943: * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
944: * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
945: * nexthop->ifindex will be updated appropriately as well.
946: * An existing route map can turn (otherwise active) nexthop into inactive, but
947: * not vice versa.
948: *
949: * The return value is the final value of 'ACTIVE' flag.
950: */
951:
952: static unsigned
953: nexthop_active_check (struct route_node *rn, struct rib *rib,
954: struct nexthop *nexthop, int set)
955: {
1.1.1.4 ! misho 956: rib_table_info_t *info = rn->table->info;
1.1 misho 957: struct interface *ifp;
958: route_map_result_t ret = RMAP_MATCH;
959: extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
960: struct route_map *rmap;
961: int family;
962:
963: family = 0;
964: switch (nexthop->type)
965: {
966: case NEXTHOP_TYPE_IFINDEX:
1.1.1.4 ! misho 967: ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id);
1.1 misho 968: if (ifp && if_is_operative(ifp))
969: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
970: else
971: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
972: break;
973: case NEXTHOP_TYPE_IPV6_IFNAME:
974: family = AFI_IP6;
975: case NEXTHOP_TYPE_IFNAME:
1.1.1.4 ! misho 976: ifp = if_lookup_by_name_vrf (nexthop->ifname, rib->vrf_id);
1.1 misho 977: if (ifp && if_is_operative(ifp))
978: {
979: if (set)
980: nexthop->ifindex = ifp->ifindex;
981: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
982: }
983: else
984: {
985: if (set)
986: nexthop->ifindex = 0;
987: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
988: }
989: break;
990: case NEXTHOP_TYPE_IPV4:
991: case NEXTHOP_TYPE_IPV4_IFINDEX:
992: family = AFI_IP;
993: if (nexthop_active_ipv4 (rib, nexthop, set, rn))
994: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
995: else
996: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
997: break;
998: case NEXTHOP_TYPE_IPV6:
999: family = AFI_IP6;
1000: if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1001: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1002: else
1003: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1004: break;
1005: case NEXTHOP_TYPE_IPV6_IFINDEX:
1006: family = AFI_IP6;
1007: if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
1008: {
1.1.1.4 ! misho 1009: ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id);
1.1 misho 1010: if (ifp && if_is_operative(ifp))
1011: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1012: else
1013: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1014: }
1015: else
1016: {
1017: if (nexthop_active_ipv6 (rib, nexthop, set, rn))
1018: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1019: else
1020: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1021: }
1022: break;
1023: case NEXTHOP_TYPE_BLACKHOLE:
1024: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1025: break;
1026: default:
1027: break;
1028: }
1029: if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1030: return 0;
1031:
1.1.1.4 ! misho 1032: /* XXX: What exactly do those checks do? Do we support
! 1033: * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
1.1 misho 1034: if (RIB_SYSTEM_ROUTE(rib) ||
1035: (family == AFI_IP && rn->p.family != AF_INET) ||
1036: (family == AFI_IP6 && rn->p.family != AF_INET6))
1037: return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1038:
1.1.1.4 ! misho 1039: /* The original code didn't determine the family correctly
! 1040: * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
! 1041: * from the rib_table_info in those cases.
! 1042: * Possibly it may be better to use only the rib_table_info
! 1043: * in every case.
! 1044: */
! 1045: if (!family)
! 1046: family = info->afi;
! 1047:
1.1 misho 1048: rmap = 0;
1049: if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
1050: proto_rm[family][rib->type])
1051: rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
1052: if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1053: rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1054: if (rmap) {
1.1.1.4 ! misho 1055: struct nexthop_vrfid nh_vrf = {nexthop, rib->vrf_id};
! 1056: ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, &nh_vrf);
1.1 misho 1057: }
1058:
1059: if (ret == RMAP_DENYMATCH)
1060: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1061: return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1062: }
1063:
1064: /* Iterate over all nexthops of the given RIB entry and refresh their
1065: * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
1066: * nexthop is found to toggle the ACTIVE flag, the whole rib structure
1.1.1.4 ! misho 1067: * is flagged with RIB_ENTRY_CHANGED. The 4th 'set' argument is
1.1 misho 1068: * transparently passed to nexthop_active_check().
1069: *
1070: * Return value is the new number of active nexthops.
1071: */
1072:
1073: static int
1074: nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
1075: {
1076: struct nexthop *nexthop;
1.1.1.4 ! misho 1077: unsigned int prev_active, new_active;
! 1078: ifindex_t prev_index;
! 1079:
1.1 misho 1080: rib->nexthop_active_num = 0;
1.1.1.4 ! misho 1081: UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED);
1.1 misho 1082:
1083: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1084: {
1085: prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
1086: prev_index = nexthop->ifindex;
1087: if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
1088: rib->nexthop_active_num++;
1089: if (prev_active != new_active ||
1090: prev_index != nexthop->ifindex)
1.1.1.4 ! misho 1091: SET_FLAG (rib->status, RIB_ENTRY_CHANGED);
1.1 misho 1092: }
1093: return rib->nexthop_active_num;
1094: }
1095:
1096:
1097:
1098: static int
1.1.1.4 ! misho 1099: rib_update_kernel (struct route_node *rn, struct rib *old, struct rib *new)
1.1 misho 1100: {
1101: int ret = 0;
1.1.1.4 ! misho 1102: struct nexthop *nexthop, *tnexthop;
! 1103: rib_table_info_t *info = rn->table->info;
! 1104: int recursing;
! 1105:
! 1106: if (info->safi != SAFI_UNICAST)
! 1107: {
! 1108: if (new)
! 1109: for (ALL_NEXTHOPS_RO(new->nexthop, nexthop, tnexthop, recursing))
! 1110: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
! 1111: if (old)
! 1112: for (ALL_NEXTHOPS_RO(old->nexthop, nexthop, tnexthop, recursing))
! 1113: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
! 1114: return 0;
! 1115: }
1.1 misho 1116:
1.1.1.3 misho 1117: /*
1118: * Make sure we update the FPM any time we send new information to
1119: * the kernel.
1120: */
1.1.1.4 ! misho 1121: zfpm_trigger_update (rn, "updating in kernel");
1.1.1.3 misho 1122:
1.1.1.4 ! misho 1123: ret = kernel_route_rib (&rn->p, old, new);
1.1 misho 1124:
1.1.1.4 ! misho 1125: /* This condition is never met, if we are using rt_socket.c */
! 1126: if (ret < 0 && new)
! 1127: for (ALL_NEXTHOPS_RO(new->nexthop, nexthop, tnexthop, recursing))
! 1128: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
! 1129:
! 1130: if (old)
! 1131: for (ALL_NEXTHOPS_RO(old->nexthop, nexthop, tnexthop, recursing))
! 1132: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1.1 misho 1133:
1134: return ret;
1135: }
1136:
1137: /* Uninstall the route from kernel. */
1138: static void
1139: rib_uninstall (struct route_node *rn, struct rib *rib)
1140: {
1.1.1.4 ! misho 1141: rib_table_info_t *info = rn->table->info;
! 1142:
! 1143: if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
1.1 misho 1144: {
1.1.1.4 ! misho 1145: if (info->safi == SAFI_UNICAST)
! 1146: zfpm_trigger_update (rn, "rib_uninstall");
1.1.1.3 misho 1147:
1.1 misho 1148: redistribute_delete (&rn->p, rib);
1149: if (! RIB_SYSTEM_ROUTE (rib))
1.1.1.4 ! misho 1150: rib_update_kernel (rn, rib, NULL);
1.1 misho 1151: UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
1152: }
1153: }
1154:
1155: static void rib_unlink (struct route_node *, struct rib *);
1156:
1.1.1.3 misho 1157: /*
1158: * rib_can_delete_dest
1159: *
1160: * Returns TRUE if the given dest can be deleted from the table.
1161: */
1162: static int
1163: rib_can_delete_dest (rib_dest_t *dest)
1164: {
1165: if (dest->routes)
1166: {
1167: return 0;
1168: }
1169:
1170: /*
1171: * Don't delete the dest if we have to update the FPM about this
1172: * prefix.
1173: */
1174: if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) ||
1175: CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM))
1176: return 0;
1177:
1178: return 1;
1179: }
1180:
1181: /*
1182: * rib_gc_dest
1183: *
1184: * Garbage collect the rib dest corresponding to the given route node
1185: * if appropriate.
1186: *
1187: * Returns TRUE if the dest was deleted, FALSE otherwise.
1188: */
1189: int
1190: rib_gc_dest (struct route_node *rn)
1191: {
1192: rib_dest_t *dest;
1193:
1194: dest = rib_dest_from_rnode (rn);
1195: if (!dest)
1196: return 0;
1197:
1198: if (!rib_can_delete_dest (dest))
1199: return 0;
1200:
1201: if (IS_ZEBRA_DEBUG_RIB)
1.1.1.4 ! misho 1202: rnode_debug (rn, "removing dest from table");
1.1.1.3 misho 1203:
1204: dest->rnode = NULL;
1205: XFREE (MTYPE_RIB_DEST, dest);
1206: rn->info = NULL;
1207:
1208: /*
1209: * Release the one reference that we keep on the route node.
1210: */
1211: route_unlock_node (rn);
1212: return 1;
1213: }
1214:
1.1.1.4 ! misho 1215: /* Check if 'alternate' RIB entry is better than 'current'. */
! 1216: static struct rib *
! 1217: rib_choose_best (struct rib *current, struct rib *alternate)
! 1218: {
! 1219: if (current == NULL)
! 1220: return alternate;
! 1221:
! 1222: /* filter route selection in following order:
! 1223: * - connected beats other types
! 1224: * - lower distance beats higher
! 1225: * - lower metric beats higher for equal distance
! 1226: * - last, hence oldest, route wins tie break.
! 1227: */
! 1228:
! 1229: /* Connected routes. Pick the last connected
! 1230: * route of the set of lowest metric connected routes.
! 1231: */
! 1232: if (alternate->type == ZEBRA_ROUTE_CONNECT)
! 1233: {
! 1234: if (current->type != ZEBRA_ROUTE_CONNECT
! 1235: || alternate->metric <= current->metric)
! 1236: return alternate;
! 1237:
! 1238: return current;
! 1239: }
! 1240:
! 1241: if (current->type == ZEBRA_ROUTE_CONNECT)
! 1242: return current;
! 1243:
! 1244: /* higher distance loses */
! 1245: if (alternate->distance < current->distance)
! 1246: return alternate;
! 1247: if (current->distance < alternate->distance)
! 1248: return current;
! 1249:
! 1250: /* metric tie-breaks equal distance */
! 1251: if (alternate->metric <= current->metric)
! 1252: return alternate;
! 1253:
! 1254: return current;
! 1255: }
! 1256:
1.1 misho 1257: /* Core function for processing routing information base. */
1258: static void
1259: rib_process (struct route_node *rn)
1260: {
1261: struct rib *rib;
1262: struct rib *next;
1.1.1.4 ! misho 1263: struct rib *old_selected = NULL;
! 1264: struct rib *new_selected = NULL;
! 1265: struct rib *old_fib = NULL;
! 1266: struct rib *new_fib = NULL;
1.1 misho 1267: int installed = 0;
1.1.1.4 ! misho 1268: struct nexthop *nexthop = NULL, *tnexthop;
! 1269: int recursing;
! 1270: rib_table_info_t *info;
! 1271:
1.1 misho 1272: assert (rn);
1273:
1.1.1.4 ! misho 1274: info = rn->table->info;
! 1275:
! 1276: RNODE_FOREACH_RIB (rn, rib)
1.1 misho 1277: {
1278: /* Currently installed rib. */
1279: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1280: {
1.1.1.4 ! misho 1281: assert (old_selected == NULL);
! 1282: old_selected = rib;
1.1 misho 1283: }
1.1.1.4 ! misho 1284: if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
1.1 misho 1285: {
1.1.1.4 ! misho 1286: assert (old_fib == NULL);
! 1287: old_fib = rib;
1.1 misho 1288: }
1.1.1.4 ! misho 1289:
! 1290: /* Skip deleted entries from selection */
! 1291: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
! 1292: continue;
1.1 misho 1293:
1294: /* Skip unreachable nexthop. */
1295: if (! nexthop_active_update (rn, rib, 0))
1296: continue;
1297:
1298: /* Infinit distance. */
1299: if (rib->distance == DISTANCE_INFINITY)
1300: continue;
1301:
1.1.1.4 ! misho 1302: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_FIB_OVERRIDE))
! 1303: new_fib = rib_choose_best(new_fib, rib);
! 1304: else
! 1305: new_selected = rib_choose_best(new_selected, rib);
1.1.1.3 misho 1306: } /* RNODE_FOREACH_RIB_SAFE */
1.1 misho 1307:
1.1.1.4 ! misho 1308: /* If no FIB override route, use the selected route also for FIB */
! 1309: if (new_fib == NULL)
! 1310: new_fib = new_selected;
! 1311:
1.1 misho 1312: /* After the cycle is finished, the following pointers will be set:
1.1.1.4 ! misho 1313: * old_selected --- RIB entry currently having SELECTED
! 1314: * new_selected --- RIB entry that is newly SELECTED
! 1315: * old_fib --- RIB entry currently in kernel FIB
! 1316: * new_fib --- RIB entry that is newly to be in kernel FIB
! 1317: *
! 1318: * new_selected will get SELECTED flag, and is going to be redistributed
! 1319: * the zclients. new_fib (which can be new_selected) will be installed in kernel.
1.1 misho 1320: */
1321:
1.1.1.4 ! misho 1322: /* Set real nexthops. */
! 1323: if (new_fib)
! 1324: nexthop_active_update (rn, new_fib, 1);
! 1325: if (new_selected && new_selected != new_fib)
! 1326: nexthop_active_update (rn, new_selected, 1);
! 1327:
! 1328: /* Update kernel if FIB entry has changed */
! 1329: if (old_fib != new_fib
! 1330: || (new_fib && CHECK_FLAG (new_fib->status, RIB_ENTRY_CHANGED)))
! 1331: {
! 1332: if (old_fib && old_fib != new_fib)
! 1333: {
! 1334: if (! RIB_SYSTEM_ROUTE (old_fib) && (! new_fib || RIB_SYSTEM_ROUTE (new_fib)))
! 1335: rib_update_kernel (rn, old_fib, NULL);
! 1336: UNSET_FLAG (old_fib->status, RIB_ENTRY_SELECTED_FIB);
! 1337: }
! 1338:
! 1339: if (new_fib)
! 1340: {
! 1341: /* Install new or replace existing FIB entry */
! 1342: SET_FLAG (new_fib->status, RIB_ENTRY_SELECTED_FIB);
! 1343: if (! RIB_SYSTEM_ROUTE (new_fib))
! 1344: rib_update_kernel (rn, old_fib, new_fib);
! 1345: }
! 1346:
! 1347: if (info->safi == SAFI_UNICAST)
! 1348: zfpm_trigger_update (rn, "updating existing route");
! 1349: }
! 1350: else if (old_fib == new_fib && new_fib && ! RIB_SYSTEM_ROUTE (new_fib))
! 1351: {
! 1352: /* Housekeeping code to deal with race conditions in kernel with
! 1353: * linux netlink reporting interface up before IPv4 or IPv6 protocol
! 1354: * is ready to add routes. This makes sure routes are IN the kernel.
! 1355: */
! 1356: for (ALL_NEXTHOPS_RO(new_fib->nexthop, nexthop, tnexthop, recursing))
! 1357: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
! 1358: {
! 1359: installed = 1;
! 1360: break;
! 1361: }
! 1362: if (! installed)
! 1363: rib_update_kernel (rn, NULL, new_fib);
! 1364: }
! 1365:
! 1366: /* Redistribute SELECTED entry */
! 1367: if (old_selected != new_selected
! 1368: || (new_selected && CHECK_FLAG (new_selected->status, RIB_ENTRY_CHANGED)))
1.1 misho 1369: {
1.1.1.4 ! misho 1370: if (old_selected)
1.1 misho 1371: {
1.1.1.4 ! misho 1372: if (! new_selected)
! 1373: redistribute_delete (&rn->p, old_selected);
! 1374: if (old_selected != new_selected)
! 1375: UNSET_FLAG (old_selected->flags, ZEBRA_FLAG_SELECTED);
1.1 misho 1376: }
1377:
1.1.1.4 ! misho 1378: if (new_selected)
! 1379: {
! 1380: /* Install new or replace existing redistributed entry */
! 1381: SET_FLAG (new_selected->flags, ZEBRA_FLAG_SELECTED);
! 1382: redistribute_add (&rn->p, new_selected);
1.1 misho 1383: }
1.1.1.4 ! misho 1384: }
1.1 misho 1385:
1.1.1.4 ! misho 1386: /* Remove all RIB entries queued for removal */
! 1387: RNODE_FOREACH_RIB_SAFE (rn, rib, next)
1.1 misho 1388: {
1.1.1.4 ! misho 1389: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
! 1390: {
! 1391: if (IS_ZEBRA_DEBUG_RIB)
! 1392: rnode_debug (rn, "rn %p, removing rib %p",
! 1393: (void *)rn, (void *)rib);
! 1394: rib_unlink (rn, rib);
! 1395: }
1.1 misho 1396: }
1397:
1398: if (IS_ZEBRA_DEBUG_RIB_Q)
1.1.1.4 ! misho 1399: rnode_debug (rn, "rn %p dequeued", (void *)rn);
1.1.1.3 misho 1400:
1401: /*
1402: * Check if the dest can be deleted now.
1403: */
1404: rib_gc_dest (rn);
1.1 misho 1405: }
1406:
1407: /* Take a list of route_node structs and return 1, if there was a record
1408: * picked from it and processed by rib_process(). Don't process more,
1409: * than one RN record; operate only in the specified sub-queue.
1410: */
1411: static unsigned int
1412: process_subq (struct list * subq, u_char qindex)
1413: {
1414: struct listnode *lnode = listhead (subq);
1415: struct route_node *rnode;
1416:
1417: if (!lnode)
1418: return 0;
1419:
1420: rnode = listgetdata (lnode);
1421: rib_process (rnode);
1422:
1.1.1.3 misho 1423: if (rnode->info)
1424: UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
1425:
1.1 misho 1426: #if 0
1427: else
1428: {
1429: zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1430: __func__, rnode, rnode->lock);
1431: zlog_backtrace(LOG_DEBUG);
1432: }
1433: #endif
1434: route_unlock_node (rnode);
1435: list_delete_node (subq, lnode);
1436: return 1;
1437: }
1438:
1439: /* Dispatch the meta queue by picking, processing and unlocking the next RN from
1440: * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
1441: * is pointed to the meta queue structure.
1442: */
1443: static wq_item_status
1444: meta_queue_process (struct work_queue *dummy, void *data)
1445: {
1446: struct meta_queue * mq = data;
1447: unsigned i;
1448:
1449: for (i = 0; i < MQ_SIZE; i++)
1450: if (process_subq (mq->subq[i], i))
1451: {
1452: mq->size--;
1453: break;
1454: }
1455: return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
1456: }
1457:
1.1.1.3 misho 1458: /*
1459: * Map from rib types to queue type (priority) in meta queue
1460: */
1.1 misho 1461: static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
1462: [ZEBRA_ROUTE_SYSTEM] = 4,
1463: [ZEBRA_ROUTE_KERNEL] = 0,
1464: [ZEBRA_ROUTE_CONNECT] = 0,
1465: [ZEBRA_ROUTE_STATIC] = 1,
1466: [ZEBRA_ROUTE_RIP] = 2,
1467: [ZEBRA_ROUTE_RIPNG] = 2,
1468: [ZEBRA_ROUTE_OSPF] = 2,
1469: [ZEBRA_ROUTE_OSPF6] = 2,
1470: [ZEBRA_ROUTE_ISIS] = 2,
1471: [ZEBRA_ROUTE_BGP] = 3,
1472: [ZEBRA_ROUTE_HSLS] = 4,
1.1.1.2 misho 1473: [ZEBRA_ROUTE_BABEL] = 2,
1.1 misho 1474: };
1475:
1476: /* Look into the RN and queue it into one or more priority queues,
1477: * increasing the size for each data push done.
1478: */
1479: static void
1480: rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
1481: {
1482: struct rib *rib;
1483:
1.1.1.3 misho 1484: RNODE_FOREACH_RIB (rn, rib)
1.1 misho 1485: {
1486: u_char qindex = meta_queue_map[rib->type];
1487:
1488: /* Invariant: at this point we always have rn->info set. */
1.1.1.3 misho 1489: if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
1490: RIB_ROUTE_QUEUED (qindex)))
1.1 misho 1491: {
1492: if (IS_ZEBRA_DEBUG_RIB_Q)
1.1.1.4 ! misho 1493: rnode_debug (rn, "rn %p is already queued in sub-queue %u",
! 1494: (void *)rn, qindex);
1.1 misho 1495: continue;
1496: }
1497:
1.1.1.3 misho 1498: SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
1.1 misho 1499: listnode_add (mq->subq[qindex], rn);
1500: route_lock_node (rn);
1501: mq->size++;
1502:
1503: if (IS_ZEBRA_DEBUG_RIB_Q)
1.1.1.4 ! misho 1504: rnode_debug (rn, "queued rn %p into sub-queue %u",
! 1505: (void *)rn, qindex);
1.1 misho 1506: }
1507: }
1508:
1509: /* Add route_node to work queue and schedule processing */
1510: static void
1511: rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
1512: {
1.1.1.2 misho 1513: assert (zebra && rn);
1514:
1515: /* Pointless to queue a route_node with no RIB entries to add or remove */
1.1.1.3 misho 1516: if (!rnode_to_ribs (rn))
1.1 misho 1517: {
1.1.1.2 misho 1518: zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
1.1.1.4 ! misho 1519: __func__, (void *)rn, rn->lock);
1.1.1.2 misho 1520: zlog_backtrace(LOG_DEBUG);
1521: return;
1522: }
1523:
1524: if (IS_ZEBRA_DEBUG_RIB_Q)
1.1.1.4 ! misho 1525: rnode_info (rn, "work queue added");
1.1 misho 1526:
1.1.1.2 misho 1527: assert (zebra);
1528:
1529: if (zebra->ribq == NULL)
1530: {
1531: zlog_err ("%s: work_queue does not exist!", __func__);
1532: return;
1.1 misho 1533: }
1534:
1535: /*
1536: * The RIB queue should normally be either empty or holding the only
1537: * work_queue_item element. In the latter case this element would
1538: * hold a pointer to the meta queue structure, which must be used to
1539: * actually queue the route nodes to process. So create the MQ
1540: * holder, if necessary, then push the work into it in any case.
1541: * This semantics was introduced after 0.99.9 release.
1542: */
1543: if (!zebra->ribq->items->count)
1544: work_queue_add (zebra->ribq, zebra->mq);
1545:
1546: rib_meta_queue_add (zebra->mq, rn);
1.1.1.2 misho 1547:
1548: if (IS_ZEBRA_DEBUG_RIB_Q)
1.1.1.4 ! misho 1549: rnode_debug (rn, "rn %p queued", (void *)rn);
1.1.1.2 misho 1550:
1551: return;
1.1 misho 1552: }
1553:
1554: /* Create new meta queue.
1555: A destructor function doesn't seem to be necessary here.
1556: */
1557: static struct meta_queue *
1558: meta_queue_new (void)
1559: {
1560: struct meta_queue *new;
1561: unsigned i;
1562:
1563: new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
1564: assert(new);
1565:
1566: for (i = 0; i < MQ_SIZE; i++)
1567: {
1568: new->subq[i] = list_new ();
1569: assert(new->subq[i]);
1570: }
1571:
1572: return new;
1573: }
1574:
1575: /* initialise zebra rib work queue */
1576: static void
1577: rib_queue_init (struct zebra_t *zebra)
1578: {
1.1.1.2 misho 1579: assert (zebra);
1580:
1.1 misho 1581: if (! (zebra->ribq = work_queue_new (zebra->master,
1582: "route_node processing")))
1583: {
1584: zlog_err ("%s: could not initialise work queue!", __func__);
1585: return;
1586: }
1587:
1588: /* fill in the work queue spec */
1589: zebra->ribq->spec.workfunc = &meta_queue_process;
1590: zebra->ribq->spec.errorfunc = NULL;
1591: /* XXX: TODO: These should be runtime configurable via vty */
1592: zebra->ribq->spec.max_retries = 3;
1593: zebra->ribq->spec.hold = rib_process_hold_time;
1594:
1595: if (!(zebra->mq = meta_queue_new ()))
1.1.1.2 misho 1596: {
1.1 misho 1597: zlog_err ("%s: could not initialise meta queue!", __func__);
1.1.1.2 misho 1598: return;
1599: }
1600: return;
1.1 misho 1601: }
1602:
1603: /* RIB updates are processed via a queue of pointers to route_nodes.
1604: *
1605: * The queue length is bounded by the maximal size of the routing table,
1606: * as a route_node will not be requeued, if already queued.
1607: *
1608: * RIBs are submitted via rib_addnode or rib_delnode which set minimal
1.1.1.4 ! misho 1609: * state, or static_install_route (when an existing RIB is updated)
1.1 misho 1610: * and then submit route_node to queue for best-path selection later.
1611: * Order of add/delete state changes are preserved for any given RIB.
1612: *
1613: * Deleted RIBs are reaped during best-path selection.
1614: *
1615: * rib_addnode
1616: * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
1617: * |-------->| | best RIB, if required
1618: * | |
1619: * static_install->|->rib_addqueue...... -> rib_process
1620: * | |
1621: * |-------->| |-> rib_unlink
1622: * |-> set RIB_ENTRY_REMOVE |
1623: * rib_delnode (RIB freed)
1624: *
1.1.1.3 misho 1625: * The 'info' pointer of a route_node points to a rib_dest_t
1626: * ('dest'). Queueing state for a route_node is kept on the dest. The
1627: * dest is created on-demand by rib_link() and is kept around at least
1628: * as long as there are ribs hanging off it (@see rib_gc_dest()).
1.1 misho 1629: *
1630: * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
1631: *
1632: * - route_nodes: refcounted by:
1.1.1.3 misho 1633: * - dest attached to route_node:
1634: * - managed by: rib_link/rib_gc_dest
1.1 misho 1635: * - route_node processing queue
1636: * - managed by: rib_addqueue, rib_process.
1637: *
1638: */
1639:
1640: /* Add RIB to head of the route node. */
1641: static void
1642: rib_link (struct route_node *rn, struct rib *rib)
1643: {
1644: struct rib *head;
1.1.1.3 misho 1645: rib_dest_t *dest;
1646:
1.1 misho 1647: assert (rib && rn);
1648:
1649: if (IS_ZEBRA_DEBUG_RIB)
1.1.1.4 ! misho 1650: rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
1.1 misho 1651:
1.1.1.3 misho 1652: dest = rib_dest_from_rnode (rn);
1653: if (!dest)
1.1 misho 1654: {
1655: if (IS_ZEBRA_DEBUG_RIB)
1.1.1.4 ! misho 1656: rnode_debug (rn, "adding dest to table");
1.1.1.3 misho 1657:
1658: dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
1659: route_lock_node (rn); /* rn route table reference */
1660: rn->info = dest;
1661: dest->rnode = rn;
1662: }
1663:
1664: head = dest->routes;
1665: if (head)
1666: {
1.1 misho 1667: head->prev = rib;
1668: }
1669: rib->next = head;
1.1.1.3 misho 1670: dest->routes = rib;
1.1 misho 1671: rib_queue_add (&zebrad, rn);
1672: }
1673:
1674: static void
1675: rib_addnode (struct route_node *rn, struct rib *rib)
1676: {
1677: /* RIB node has been un-removed before route-node is processed.
1678: * route_node must hence already be on the queue for processing..
1679: */
1680: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1681: {
1682: if (IS_ZEBRA_DEBUG_RIB)
1.1.1.4 ! misho 1683: rnode_debug (rn, "rn %p, un-removed rib %p", (void *)rn, (void *)rib);
! 1684:
1.1 misho 1685: UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1686: return;
1687: }
1688: rib_link (rn, rib);
1689: }
1690:
1.1.1.3 misho 1691: /*
1692: * rib_unlink
1693: *
1694: * Detach a rib structure from a route_node.
1695: *
1696: * Note that a call to rib_unlink() should be followed by a call to
1697: * rib_gc_dest() at some point. This allows a rib_dest_t that is no
1698: * longer required to be deleted.
1699: */
1.1 misho 1700: static void
1701: rib_unlink (struct route_node *rn, struct rib *rib)
1702: {
1.1.1.3 misho 1703: rib_dest_t *dest;
1.1 misho 1704:
1705: assert (rn && rib);
1706:
1707: if (IS_ZEBRA_DEBUG_RIB)
1.1.1.4 ! misho 1708: rnode_debug (rn, "rn %p, rib %p", (void *)rn, (void *)rib);
1.1 misho 1709:
1.1.1.3 misho 1710: dest = rib_dest_from_rnode (rn);
1711:
1.1 misho 1712: if (rib->next)
1713: rib->next->prev = rib->prev;
1714:
1715: if (rib->prev)
1716: rib->prev->next = rib->next;
1717: else
1718: {
1.1.1.3 misho 1719: dest->routes = rib->next;
1.1 misho 1720: }
1721:
1722: /* free RIB and nexthops */
1.1.1.4 ! misho 1723: nexthops_free(rib->nexthop);
1.1 misho 1724: XFREE (MTYPE_RIB, rib);
1725:
1726: }
1727:
1728: static void
1729: rib_delnode (struct route_node *rn, struct rib *rib)
1730: {
1731: if (IS_ZEBRA_DEBUG_RIB)
1.1.1.4 ! misho 1732: rnode_debug (rn, "rn %p, rib %p, removing", (void *)rn, (void *)rib);
1.1 misho 1733: SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
1734: rib_queue_add (&zebrad, rn);
1735: }
1736:
1737: int
1738: rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1739: struct in_addr *gate, struct in_addr *src,
1.1.1.4 ! misho 1740: ifindex_t ifindex, vrf_id_t vrf_id, int table_id,
! 1741: u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
1.1 misho 1742: {
1743: struct rib *rib;
1744: struct rib *same = NULL;
1745: struct route_table *table;
1746: struct route_node *rn;
1747: struct nexthop *nexthop;
1748:
1749: /* Lookup table. */
1.1.1.4 ! misho 1750: table = zebra_vrf_table (AFI_IP, safi, vrf_id);
1.1 misho 1751: if (! table)
1752: return 0;
1753:
1754: /* Make it sure prefixlen is applied to the prefix. */
1755: apply_mask_ipv4 (p);
1756:
1757: /* Set default distance by route type. */
1758: if (distance == 0)
1759: {
1.1.1.3 misho 1760: if ((unsigned)type >= array_size(route_info))
1.1.1.2 misho 1761: distance = 150;
1762: else
1763: distance = route_info[type].distance;
1.1 misho 1764:
1765: /* iBGP distance is 200. */
1766: if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1767: distance = 200;
1768: }
1769:
1770: /* Lookup route node.*/
1771: rn = route_node_get (table, (struct prefix *) p);
1772:
1773: /* If same type of route are installed, treat it as a implicit
1774: withdraw. */
1.1.1.3 misho 1775: RNODE_FOREACH_RIB (rn, rib)
1.1 misho 1776: {
1777: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1778: continue;
1779:
1780: if (rib->type != type)
1781: continue;
1782: if (rib->type != ZEBRA_ROUTE_CONNECT)
1783: {
1784: same = rib;
1785: break;
1786: }
1787: /* Duplicate connected route comes in. */
1788: else if ((nexthop = rib->nexthop) &&
1789: nexthop->type == NEXTHOP_TYPE_IFINDEX &&
1790: nexthop->ifindex == ifindex &&
1791: !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
1792: {
1793: rib->refcnt++;
1794: return 0 ;
1795: }
1796: }
1797:
1798: /* Allocate new rib structure. */
1799: rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1800: rib->type = type;
1801: rib->distance = distance;
1802: rib->flags = flags;
1803: rib->metric = metric;
1.1.1.4 ! misho 1804: rib->mtu = mtu;
! 1805: rib->vrf_id = vrf_id;
! 1806: rib->table = table_id;
1.1 misho 1807: rib->nexthop_num = 0;
1808: rib->uptime = time (NULL);
1809:
1810: /* Nexthop settings. */
1811: if (gate)
1812: {
1813: if (ifindex)
1814: nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
1815: else
1816: nexthop_ipv4_add (rib, gate, src);
1817: }
1818: else
1819: nexthop_ifindex_add (rib, ifindex);
1820:
1821: /* If this route is kernel route, set FIB flag to the route. */
1822: if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1823: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1824: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1825:
1826: /* Link new rib to node.*/
1827: if (IS_ZEBRA_DEBUG_RIB)
1.1.1.4 ! misho 1828: zlog_debug ("%s: calling rib_addnode (%p, %p)",
! 1829: __func__, (void *)rn, (void *)rib);
1.1 misho 1830: rib_addnode (rn, rib);
1831:
1832: /* Free implicit route.*/
1833: if (same)
1834: {
1835: if (IS_ZEBRA_DEBUG_RIB)
1.1.1.4 ! misho 1836: zlog_debug ("%s: calling rib_delnode (%p, %p)",
! 1837: __func__, (void *)rn, (void *)rib);
1.1 misho 1838: rib_delnode (rn, same);
1839: }
1840:
1841: route_unlock_node (rn);
1842: return 0;
1843: }
1844:
1845: /* This function dumps the contents of a given RIB entry into
1846: * standard debug log. Calling function name and IP prefix in
1847: * question are passed as 1st and 2nd arguments.
1848: */
1849:
1.1.1.4 ! misho 1850: void _rib_dump (const char * func,
! 1851: union prefix46constptr pp, const struct rib * rib)
1.1 misho 1852: {
1.1.1.4 ! misho 1853: const struct prefix *p = pp.p;
! 1854: char straddr[PREFIX_STRLEN];
! 1855: struct nexthop *nexthop, *tnexthop;
! 1856: int recursing;
1.1 misho 1857:
1.1.1.4 ! misho 1858: zlog_debug ("%s: dumping RIB entry %p for %s vrf %u", func, (void *)rib,
! 1859: prefix2str(p, straddr, sizeof(straddr)), rib->vrf_id);
1.1 misho 1860: zlog_debug
1861: (
1862: "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
1863: func,
1864: rib->refcnt,
1865: (unsigned long) rib->uptime,
1866: rib->type,
1867: rib->table
1868: );
1869: zlog_debug
1870: (
1871: "%s: metric == %u, distance == %u, flags == %u, status == %u",
1872: func,
1873: rib->metric,
1874: rib->distance,
1875: rib->flags,
1876: rib->status
1877: );
1878: zlog_debug
1879: (
1880: "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
1881: func,
1882: rib->nexthop_num,
1883: rib->nexthop_active_num,
1884: rib->nexthop_fib_num
1885: );
1.1.1.4 ! misho 1886:
! 1887: for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
! 1888: {
! 1889: inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
! 1890: zlog_debug
! 1891: (
! 1892: "%s: %s %s with flags %s%s%s",
! 1893: func,
! 1894: (recursing ? " NH" : "NH"),
! 1895: straddr,
! 1896: (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
! 1897: (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
! 1898: (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
! 1899: );
! 1900: }
1.1 misho 1901: zlog_debug ("%s: dump complete", func);
1902: }
1903:
1904: /* This is an exported helper to rtm_read() to dump the strange
1905: * RIB entry found by rib_lookup_ipv4_route()
1906: */
1907:
1908: void rib_lookup_and_dump (struct prefix_ipv4 * p)
1909: {
1910: struct route_table *table;
1911: struct route_node *rn;
1912: struct rib *rib;
1913: char prefix_buf[INET_ADDRSTRLEN];
1914:
1915: /* Lookup table. */
1.1.1.4 ! misho 1916: table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
1.1 misho 1917: if (! table)
1918: {
1.1.1.4 ! misho 1919: zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
1.1 misho 1920: return;
1921: }
1922:
1923: /* Scan the RIB table for exactly matching RIB entry. */
1924: rn = route_node_lookup (table, (struct prefix *) p);
1925:
1926: /* No route for this prefix. */
1927: if (! rn)
1928: {
1.1.1.4 ! misho 1929: zlog_debug ("%s: lookup failed for %s", __func__,
! 1930: prefix2str((struct prefix*) p, prefix_buf, sizeof(prefix_buf)));
1.1 misho 1931: return;
1932: }
1933:
1934: /* Unlock node. */
1935: route_unlock_node (rn);
1936:
1937: /* let's go */
1.1.1.3 misho 1938: RNODE_FOREACH_RIB (rn, rib)
1.1 misho 1939: {
1940: zlog_debug
1941: (
1942: "%s: rn %p, rib %p: %s, %s",
1943: __func__,
1.1.1.4 ! misho 1944: (void *)rn,
! 1945: (void *)rib,
1.1 misho 1946: (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
1947: (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
1948: );
1.1.1.4 ! misho 1949: rib_dump (p, rib);
1.1 misho 1950: }
1951: }
1952:
1953: /* Check if requested address assignment will fail due to another
1954: * route being installed by zebra in FIB already. Take necessary
1955: * actions, if needed: remove such a route from FIB and deSELECT
1956: * corresponding RIB entry. Then put affected RN into RIBQ head.
1957: */
1958: void rib_lookup_and_pushup (struct prefix_ipv4 * p)
1959: {
1960: struct route_table *table;
1961: struct route_node *rn;
1962: struct rib *rib;
1963: unsigned changed = 0;
1964:
1.1.1.4 ! misho 1965: if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)))
1.1 misho 1966: {
1.1.1.4 ! misho 1967: zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
1.1 misho 1968: return;
1969: }
1970:
1971: /* No matches would be the simplest case. */
1972: if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
1973: return;
1974:
1975: /* Unlock node. */
1976: route_unlock_node (rn);
1977:
1978: /* Check all RIB entries. In case any changes have to be done, requeue
1979: * the RN into RIBQ head. If the routing message about the new connected
1980: * route (generated by the IP address we are going to assign very soon)
1981: * comes before the RIBQ is processed, the new RIB entry will join
1982: * RIBQ record already on head. This is necessary for proper revalidation
1983: * of the rest of the RIB.
1984: */
1.1.1.3 misho 1985: RNODE_FOREACH_RIB (rn, rib)
1.1 misho 1986: {
1.1.1.4 ! misho 1987: if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB) &&
1.1 misho 1988: ! RIB_SYSTEM_ROUTE (rib))
1989: {
1990: changed = 1;
1991: if (IS_ZEBRA_DEBUG_RIB)
1992: {
1.1.1.4 ! misho 1993: char buf[PREFIX_STRLEN];
! 1994: zlog_debug ("%s: freeing way for connected prefix %s", __func__,
! 1995: prefix2str(&rn->p, buf, sizeof(buf)));
! 1996: rib_dump (&rn->p, rib);
1.1 misho 1997: }
1998: rib_uninstall (rn, rib);
1999: }
2000: }
2001: if (changed)
2002: rib_queue_add (&zebrad, rn);
2003: }
2004:
2005: int
1.1.1.2 misho 2006: rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
1.1 misho 2007: {
2008: struct route_table *table;
2009: struct route_node *rn;
2010: struct rib *same;
2011: struct nexthop *nexthop;
2012:
2013: /* Lookup table. */
1.1.1.4 ! misho 2014: table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id);
1.1 misho 2015: if (! table)
2016: return 0;
1.1.1.2 misho 2017:
1.1 misho 2018: /* Make it sure prefixlen is applied to the prefix. */
2019: apply_mask_ipv4 (p);
2020:
2021: /* Set default distance by route type. */
2022: if (rib->distance == 0)
2023: {
2024: rib->distance = route_info[rib->type].distance;
2025:
2026: /* iBGP distance is 200. */
2027: if (rib->type == ZEBRA_ROUTE_BGP
2028: && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
2029: rib->distance = 200;
2030: }
2031:
2032: /* Lookup route node.*/
2033: rn = route_node_get (table, (struct prefix *) p);
2034:
2035: /* If same type of route are installed, treat it as a implicit
2036: withdraw. */
1.1.1.3 misho 2037: RNODE_FOREACH_RIB (rn, same)
1.1 misho 2038: {
2039: if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
2040: continue;
2041:
2042: if (same->type == rib->type && same->table == rib->table
2043: && same->type != ZEBRA_ROUTE_CONNECT)
2044: break;
2045: }
2046:
2047: /* If this route is kernel route, set FIB flag to the route. */
2048: if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
2049: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2050: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2051:
2052: /* Link new rib to node.*/
2053: rib_addnode (rn, rib);
2054: if (IS_ZEBRA_DEBUG_RIB)
2055: {
2056: zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
1.1.1.4 ! misho 2057: __func__, (void *)rn, (void *)rib);
! 2058: rib_dump (p, rib);
1.1 misho 2059: }
2060:
2061: /* Free implicit route.*/
2062: if (same)
2063: {
2064: if (IS_ZEBRA_DEBUG_RIB)
2065: {
2066: zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
1.1.1.4 ! misho 2067: __func__, (void *)rn, (void *)same);
! 2068: rib_dump (p, same);
1.1 misho 2069: }
2070: rib_delnode (rn, same);
2071: }
2072:
2073: route_unlock_node (rn);
2074: return 0;
2075: }
2076:
2077: /* XXX factor with rib_delete_ipv6 */
2078: int
2079: rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1.1.1.4 ! misho 2080: struct in_addr *gate, ifindex_t ifindex,
! 2081: vrf_id_t vrf_id, safi_t safi)
1.1 misho 2082: {
2083: struct route_table *table;
2084: struct route_node *rn;
2085: struct rib *rib;
2086: struct rib *fib = NULL;
2087: struct rib *same = NULL;
1.1.1.4 ! misho 2088: struct nexthop *nexthop, *tnexthop;
! 2089: int recursing;
! 2090: char buf1[PREFIX_STRLEN];
1.1 misho 2091: char buf2[INET_ADDRSTRLEN];
2092:
2093: /* Lookup table. */
1.1.1.4 ! misho 2094: table = zebra_vrf_table (AFI_IP, safi, vrf_id);
1.1 misho 2095: if (! table)
2096: return 0;
2097:
2098: /* Apply mask. */
2099: apply_mask_ipv4 (p);
2100:
1.1.1.4 ! misho 2101: if (IS_ZEBRA_DEBUG_KERNEL)
! 2102: {
! 2103: if (gate)
! 2104: zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u via %s ifindex %d",
! 2105: prefix2str (p, buf1, sizeof(buf1)), vrf_id,
! 2106: inet_ntoa (*gate),
! 2107: ifindex);
! 2108: else
! 2109: zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u ifindex %d",
! 2110: prefix2str (p, buf1, sizeof(buf1)), vrf_id,
! 2111: ifindex);
! 2112: }
1.1 misho 2113:
2114: /* Lookup route node. */
2115: rn = route_node_lookup (table, (struct prefix *) p);
2116: if (! rn)
2117: {
2118: if (IS_ZEBRA_DEBUG_KERNEL)
2119: {
2120: if (gate)
1.1.1.4 ! misho 2121: zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
! 2122: prefix2str (p, buf1, sizeof(buf1)), vrf_id,
1.1 misho 2123: inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
2124: ifindex);
2125: else
1.1.1.4 ! misho 2126: zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
! 2127: prefix2str (p, buf1, sizeof(buf1)), vrf_id,
1.1 misho 2128: ifindex);
2129: }
2130: return ZEBRA_ERR_RTNOEXIST;
2131: }
2132:
2133: /* Lookup same type route. */
1.1.1.3 misho 2134: RNODE_FOREACH_RIB (rn, rib)
1.1 misho 2135: {
2136: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2137: continue;
2138:
1.1.1.4 ! misho 2139: if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
1.1 misho 2140: fib = rib;
2141:
2142: if (rib->type != type)
2143: continue;
2144: if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1.1.1.2 misho 2145: nexthop->type == NEXTHOP_TYPE_IFINDEX)
1.1 misho 2146: {
1.1.1.2 misho 2147: if (nexthop->ifindex != ifindex)
2148: continue;
1.1 misho 2149: if (rib->refcnt)
2150: {
2151: rib->refcnt--;
2152: route_unlock_node (rn);
2153: route_unlock_node (rn);
2154: return 0;
2155: }
2156: same = rib;
2157: break;
2158: }
2159: /* Make sure that the route found has the same gateway. */
1.1.1.4 ! misho 2160: else
1.1 misho 2161: {
1.1.1.4 ! misho 2162: if (gate == NULL)
! 2163: {
! 2164: same = rib;
! 2165: break;
! 2166: }
! 2167: for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
! 2168: if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
! 2169: {
! 2170: same = rib;
! 2171: break;
! 2172: }
! 2173: if (same)
! 2174: break;
! 2175: }
1.1 misho 2176: }
2177: /* If same type of route can't be found and this message is from
2178: kernel. */
2179: if (! same)
2180: {
2181: if (fib && type == ZEBRA_ROUTE_KERNEL)
2182: {
2183: /* Unset flags. */
2184: for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2185: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2186:
1.1.1.4 ! misho 2187: UNSET_FLAG (fib->status, RIB_ENTRY_SELECTED_FIB);
1.1 misho 2188: }
2189: else
2190: {
2191: if (IS_ZEBRA_DEBUG_KERNEL)
2192: {
2193: if (gate)
1.1.1.4 ! misho 2194: zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
! 2195: "doesn't exist in rib",
! 2196: prefix2str (p, buf1, sizeof(buf1)), vrf_id,
1.1 misho 2197: inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
2198: ifindex,
2199: type);
2200: else
1.1.1.4 ! misho 2201: zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
! 2202: prefix2str (p, buf1, sizeof(buf1)), vrf_id,
1.1 misho 2203: ifindex,
2204: type);
2205: }
2206: route_unlock_node (rn);
2207: return ZEBRA_ERR_RTNOEXIST;
2208: }
2209: }
2210:
2211: if (same)
2212: rib_delnode (rn, same);
2213:
2214: route_unlock_node (rn);
2215: return 0;
2216: }
1.1.1.4 ! misho 2217:
1.1 misho 2218: /* Install static route into rib. */
2219: static void
1.1.1.4 ! misho 2220: static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
1.1 misho 2221: {
2222: struct rib *rib;
2223: struct route_node *rn;
2224: struct route_table *table;
2225:
2226: /* Lookup table. */
1.1.1.4 ! misho 2227: table = zebra_vrf_table (afi, safi, si->vrf_id);
1.1 misho 2228: if (! table)
2229: return;
2230:
2231: /* Lookup existing route */
2232: rn = route_node_get (table, p);
1.1.1.3 misho 2233: RNODE_FOREACH_RIB (rn, rib)
1.1 misho 2234: {
2235: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2236: continue;
2237:
2238: if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2239: break;
2240: }
2241:
2242: if (rib)
2243: {
2244: /* Same distance static route is there. Update it with new
2245: nexthop. */
2246: route_unlock_node (rn);
2247: switch (si->type)
2248: {
1.1.1.4 ! misho 2249: case STATIC_IPV4_GATEWAY:
! 2250: nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
! 2251: break;
! 2252: case STATIC_IPV4_IFNAME:
! 2253: nexthop_ifname_add (rib, si->ifname);
! 2254: break;
! 2255: case STATIC_IPV4_BLACKHOLE:
! 2256: nexthop_blackhole_add (rib);
! 2257: break;
! 2258: case STATIC_IPV6_GATEWAY:
! 2259: nexthop_ipv6_add (rib, &si->addr.ipv6);
! 2260: break;
! 2261: case STATIC_IPV6_IFNAME:
! 2262: nexthop_ifname_add (rib, si->ifname);
! 2263: break;
! 2264: case STATIC_IPV6_GATEWAY_IFNAME:
! 2265: nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
! 2266: break;
1.1 misho 2267: }
2268: rib_queue_add (&zebrad, rn);
2269: }
2270: else
2271: {
2272: /* This is new static route. */
2273: rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2274:
2275: rib->type = ZEBRA_ROUTE_STATIC;
2276: rib->distance = si->distance;
2277: rib->metric = 0;
1.1.1.4 ! misho 2278: rib->vrf_id = si->vrf_id;
1.1.1.3 misho 2279: rib->table = zebrad.rtm_table_default;
1.1 misho 2280: rib->nexthop_num = 0;
2281:
2282: switch (si->type)
2283: {
1.1.1.4 ! misho 2284: case STATIC_IPV4_GATEWAY:
! 2285: nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
! 2286: break;
! 2287: case STATIC_IPV4_IFNAME:
! 2288: nexthop_ifname_add (rib, si->ifname);
! 2289: break;
! 2290: case STATIC_IPV4_BLACKHOLE:
! 2291: nexthop_blackhole_add (rib);
! 2292: break;
! 2293: case STATIC_IPV6_GATEWAY:
! 2294: nexthop_ipv6_add (rib, &si->addr.ipv6);
! 2295: break;
! 2296: case STATIC_IPV6_IFNAME:
! 2297: nexthop_ifname_add (rib, si->ifname);
! 2298: break;
! 2299: case STATIC_IPV6_GATEWAY_IFNAME:
! 2300: nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
! 2301: break;
1.1 misho 2302: }
2303:
2304: /* Save the flags of this static routes (reject, blackhole) */
2305: rib->flags = si->flags;
2306:
2307: /* Link this rib to the tree. */
2308: rib_addnode (rn, rib);
2309: }
2310: }
2311:
2312: static int
1.1.1.4 ! misho 2313: static_nexthop_same (struct nexthop *nexthop, struct static_route *si)
1.1 misho 2314: {
2315: if (nexthop->type == NEXTHOP_TYPE_IPV4
2316: && si->type == STATIC_IPV4_GATEWAY
1.1.1.4 ! misho 2317: && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4))
1.1 misho 2318: return 1;
2319: if (nexthop->type == NEXTHOP_TYPE_IFNAME
2320: && si->type == STATIC_IPV4_IFNAME
1.1.1.4 ! misho 2321: && strcmp (nexthop->ifname, si->ifname) == 0)
1.1 misho 2322: return 1;
2323: if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
2324: && si->type == STATIC_IPV4_BLACKHOLE)
2325: return 1;
1.1.1.4 ! misho 2326: if (nexthop->type == NEXTHOP_TYPE_IPV6
! 2327: && si->type == STATIC_IPV6_GATEWAY
! 2328: && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6))
! 2329: return 1;
! 2330: if (nexthop->type == NEXTHOP_TYPE_IFNAME
! 2331: && si->type == STATIC_IPV6_IFNAME
! 2332: && strcmp (nexthop->ifname, si->ifname) == 0)
! 2333: return 1;
! 2334: if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
! 2335: && si->type == STATIC_IPV6_GATEWAY_IFNAME
! 2336: && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)
! 2337: && strcmp (nexthop->ifname, si->ifname) == 0)
! 2338: return 1;
1.1 misho 2339: return 0;
2340: }
2341:
2342: /* Uninstall static route from RIB. */
2343: static void
1.1.1.4 ! misho 2344: static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
1.1 misho 2345: {
2346: struct route_node *rn;
2347: struct rib *rib;
2348: struct nexthop *nexthop;
2349: struct route_table *table;
2350:
2351: /* Lookup table. */
1.1.1.4 ! misho 2352: table = zebra_vrf_table (afi, safi, si->vrf_id);
1.1 misho 2353: if (! table)
2354: return;
2355:
2356: /* Lookup existing route with type and distance. */
2357: rn = route_node_lookup (table, p);
2358: if (! rn)
2359: return;
2360:
1.1.1.3 misho 2361: RNODE_FOREACH_RIB (rn, rib)
1.1 misho 2362: {
2363: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2364: continue;
2365:
2366: if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2367: break;
2368: }
2369:
2370: if (! rib)
2371: {
2372: route_unlock_node (rn);
2373: return;
2374: }
2375:
2376: /* Lookup nexthop. */
2377: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1.1.1.4 ! misho 2378: if (static_nexthop_same (nexthop, si))
1.1 misho 2379: break;
2380:
2381: /* Can't find nexthop. */
2382: if (! nexthop)
2383: {
2384: route_unlock_node (rn);
2385: return;
2386: }
2387:
2388: /* Check nexthop. */
2389: if (rib->nexthop_num == 1)
2390: rib_delnode (rn, rib);
2391: else
2392: {
2393: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2394: rib_uninstall (rn, rib);
2395: nexthop_delete (rib, nexthop);
2396: nexthop_free (nexthop);
2397: rib_queue_add (&zebrad, rn);
2398: }
2399: /* Unlock node. */
2400: route_unlock_node (rn);
2401: }
2402:
2403: int
1.1.1.4 ! misho 2404: static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
! 2405: const char *ifname, u_char flags, u_char distance,
! 2406: vrf_id_t vrf_id)
1.1 misho 2407: {
2408: u_char type = 0;
2409: struct route_node *rn;
1.1.1.4 ! misho 2410: struct static_route *si;
! 2411: struct static_route *pp;
! 2412: struct static_route *cp;
! 2413: struct static_route *update = NULL;
! 2414: struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
! 2415: struct route_table *stable = zvrf->stable[AFI_IP][safi];
1.1 misho 2416:
2417: if (! stable)
2418: return -1;
2419:
2420: /* Lookup static route prefix. */
2421: rn = route_node_get (stable, p);
2422:
2423: /* Make flags. */
2424: if (gate)
2425: type = STATIC_IPV4_GATEWAY;
2426: else if (ifname)
2427: type = STATIC_IPV4_IFNAME;
2428: else
2429: type = STATIC_IPV4_BLACKHOLE;
2430:
2431: /* Do nothing if there is a same static route. */
2432: for (si = rn->info; si; si = si->next)
2433: {
2434: if (type == si->type
1.1.1.4 ! misho 2435: && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
! 2436: && (! ifname || strcmp (ifname, si->ifname) == 0))
1.1 misho 2437: {
2438: if (distance == si->distance)
2439: {
2440: route_unlock_node (rn);
2441: return 0;
2442: }
2443: else
2444: update = si;
2445: }
2446: }
2447:
2448: /* Distance changed. */
2449: if (update)
1.1.1.4 ! misho 2450: static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
1.1 misho 2451:
2452: /* Make new static route structure. */
1.1.1.4 ! misho 2453: si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
1.1 misho 2454:
2455: si->type = type;
2456: si->distance = distance;
2457: si->flags = flags;
1.1.1.4 ! misho 2458: si->vrf_id = vrf_id;
1.1 misho 2459:
2460: if (gate)
1.1.1.4 ! misho 2461: si->addr.ipv4 = *gate;
1.1 misho 2462: if (ifname)
1.1.1.4 ! misho 2463: si->ifname = XSTRDUP (0, ifname);
1.1 misho 2464:
2465: /* Add new static route information to the tree with sort by
2466: distance value and gateway address. */
2467: for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2468: {
2469: if (si->distance < cp->distance)
2470: break;
2471: if (si->distance > cp->distance)
2472: continue;
2473: if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
2474: {
1.1.1.4 ! misho 2475: if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr))
1.1 misho 2476: break;
1.1.1.4 ! misho 2477: if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr))
1.1 misho 2478: continue;
2479: }
2480: }
2481:
2482: /* Make linked list. */
2483: if (pp)
2484: pp->next = si;
2485: else
2486: rn->info = si;
2487: if (cp)
2488: cp->prev = si;
2489: si->prev = pp;
2490: si->next = cp;
2491:
2492: /* Install into rib. */
1.1.1.4 ! misho 2493: static_install_route (AFI_IP, safi, p, si);
1.1 misho 2494:
2495: return 1;
2496: }
2497:
2498: int
1.1.1.4 ! misho 2499: static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
! 2500: const char *ifname, u_char distance, vrf_id_t vrf_id)
1.1 misho 2501: {
2502: u_char type = 0;
2503: struct route_node *rn;
1.1.1.4 ! misho 2504: struct static_route *si;
1.1 misho 2505: struct route_table *stable;
2506:
2507: /* Lookup table. */
1.1.1.4 ! misho 2508: stable = zebra_vrf_static_table (AFI_IP, safi, vrf_id);
1.1 misho 2509: if (! stable)
2510: return -1;
2511:
2512: /* Lookup static route prefix. */
2513: rn = route_node_lookup (stable, p);
2514: if (! rn)
2515: return 0;
2516:
2517: /* Make flags. */
2518: if (gate)
2519: type = STATIC_IPV4_GATEWAY;
2520: else if (ifname)
2521: type = STATIC_IPV4_IFNAME;
2522: else
2523: type = STATIC_IPV4_BLACKHOLE;
2524:
2525: /* Find same static route is the tree */
2526: for (si = rn->info; si; si = si->next)
2527: if (type == si->type
1.1.1.4 ! misho 2528: && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
! 2529: && (! ifname || strcmp (ifname, si->ifname) == 0))
1.1 misho 2530: break;
2531:
2532: /* Can't find static route. */
2533: if (! si)
2534: {
2535: route_unlock_node (rn);
2536: return 0;
2537: }
2538:
2539: /* Install into rib. */
1.1.1.4 ! misho 2540: static_uninstall_route (AFI_IP, safi, p, si);
1.1 misho 2541:
2542: /* Unlink static route from linked list. */
2543: if (si->prev)
2544: si->prev->next = si->next;
2545: else
2546: rn->info = si->next;
2547: if (si->next)
2548: si->next->prev = si->prev;
2549: route_unlock_node (rn);
2550:
2551: /* Free static route configuration. */
2552: if (ifname)
1.1.1.4 ! misho 2553: XFREE (0, si->ifname);
! 2554: XFREE (MTYPE_STATIC_ROUTE, si);
1.1 misho 2555:
2556: route_unlock_node (rn);
2557:
2558: return 1;
2559: }
2560:
2561: int
2562: rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1.1.1.4 ! misho 2563: struct in6_addr *gate, ifindex_t ifindex,
! 2564: vrf_id_t vrf_id, int table_id,
! 2565: u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
1.1 misho 2566: {
2567: struct rib *rib;
2568: struct rib *same = NULL;
2569: struct route_table *table;
2570: struct route_node *rn;
2571: struct nexthop *nexthop;
2572:
2573: /* Lookup table. */
1.1.1.4 ! misho 2574: table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
1.1 misho 2575: if (! table)
2576: return 0;
2577:
2578: /* Make sure mask is applied. */
2579: apply_mask_ipv6 (p);
2580:
2581: /* Set default distance by route type. */
2582: if (!distance)
2583: distance = route_info[type].distance;
2584:
2585: if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
2586: distance = 200;
2587:
2588: /* Lookup route node.*/
2589: rn = route_node_get (table, (struct prefix *) p);
2590:
2591: /* If same type of route are installed, treat it as a implicit
2592: withdraw. */
1.1.1.3 misho 2593: RNODE_FOREACH_RIB (rn, rib)
1.1 misho 2594: {
2595: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2596: continue;
2597:
2598: if (rib->type != type)
2599: continue;
2600: if (rib->type != ZEBRA_ROUTE_CONNECT)
2601: {
2602: same = rib;
2603: break;
2604: }
2605: else if ((nexthop = rib->nexthop) &&
2606: nexthop->type == NEXTHOP_TYPE_IFINDEX &&
2607: nexthop->ifindex == ifindex)
2608: {
2609: rib->refcnt++;
2610: return 0;
2611: }
2612: }
2613:
2614: /* Allocate new rib structure. */
2615: rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2616:
2617: rib->type = type;
2618: rib->distance = distance;
2619: rib->flags = flags;
2620: rib->metric = metric;
1.1.1.4 ! misho 2621: rib->mtu = mtu;
! 2622: rib->vrf_id = vrf_id;
! 2623: rib->table = table_id;
1.1 misho 2624: rib->nexthop_num = 0;
2625: rib->uptime = time (NULL);
2626:
2627: /* Nexthop settings. */
2628: if (gate)
2629: {
2630: if (ifindex)
2631: nexthop_ipv6_ifindex_add (rib, gate, ifindex);
2632: else
2633: nexthop_ipv6_add (rib, gate);
2634: }
2635: else
2636: nexthop_ifindex_add (rib, ifindex);
2637:
2638: /* If this route is kernel route, set FIB flag to the route. */
2639: if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
2640: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2641: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2642:
2643: /* Link new rib to node.*/
2644: rib_addnode (rn, rib);
1.1.1.4 ! misho 2645: if (IS_ZEBRA_DEBUG_RIB)
! 2646: {
! 2647: zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
! 2648: __func__, (void *)rn, (void *)rib);
! 2649: rib_dump (p, rib);
! 2650: }
1.1 misho 2651:
2652: /* Free implicit route.*/
2653: if (same)
1.1.1.4 ! misho 2654: {
! 2655: if (IS_ZEBRA_DEBUG_RIB)
! 2656: {
! 2657: zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
! 2658: __func__, (void *)rn, (void *)same);
! 2659: rib_dump (p, same);
! 2660: }
1.1 misho 2661: rib_delnode (rn, same);
1.1.1.4 ! misho 2662: }
1.1 misho 2663:
2664: route_unlock_node (rn);
2665: return 0;
2666: }
2667:
2668: /* XXX factor with rib_delete_ipv6 */
2669: int
2670: rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1.1.1.4 ! misho 2671: struct in6_addr *gate, ifindex_t ifindex,
! 2672: vrf_id_t vrf_id, safi_t safi)
1.1 misho 2673: {
2674: struct route_table *table;
2675: struct route_node *rn;
2676: struct rib *rib;
2677: struct rib *fib = NULL;
2678: struct rib *same = NULL;
1.1.1.4 ! misho 2679: struct nexthop *nexthop, *tnexthop;
! 2680: int recursing;
! 2681: char buf1[PREFIX_STRLEN];
1.1 misho 2682: char buf2[INET6_ADDRSTRLEN];
2683:
2684: /* Apply mask. */
2685: apply_mask_ipv6 (p);
2686:
2687: /* Lookup table. */
1.1.1.4 ! misho 2688: table = zebra_vrf_table (AFI_IP6, safi, vrf_id);
1.1 misho 2689: if (! table)
2690: return 0;
2691:
2692: /* Lookup route node. */
2693: rn = route_node_lookup (table, (struct prefix *) p);
2694: if (! rn)
2695: {
2696: if (IS_ZEBRA_DEBUG_KERNEL)
2697: {
2698: if (gate)
1.1.1.4 ! misho 2699: zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
! 2700: prefix2str (p, buf1, sizeof(buf1)), vrf_id,
1.1 misho 2701: inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
2702: ifindex);
2703: else
1.1.1.4 ! misho 2704: zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
! 2705: prefix2str (p, buf1, sizeof(buf1)), vrf_id,
1.1 misho 2706: ifindex);
2707: }
2708: return ZEBRA_ERR_RTNOEXIST;
2709: }
2710:
2711: /* Lookup same type route. */
1.1.1.3 misho 2712: RNODE_FOREACH_RIB (rn, rib)
1.1 misho 2713: {
2714: if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
2715: continue;
2716:
1.1.1.4 ! misho 2717: if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
1.1 misho 2718: fib = rib;
2719:
2720: if (rib->type != type)
2721: continue;
2722: if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1.1.1.2 misho 2723: nexthop->type == NEXTHOP_TYPE_IFINDEX)
1.1 misho 2724: {
1.1.1.2 misho 2725: if (nexthop->ifindex != ifindex)
2726: continue;
1.1 misho 2727: if (rib->refcnt)
2728: {
2729: rib->refcnt--;
2730: route_unlock_node (rn);
2731: route_unlock_node (rn);
2732: return 0;
2733: }
2734: same = rib;
2735: break;
2736: }
2737: /* Make sure that the route found has the same gateway. */
1.1.1.4 ! misho 2738: else
! 2739: {
! 2740: if (gate == NULL)
! 2741: {
! 2742: same = rib;
! 2743: break;
! 2744: }
! 2745: for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
! 2746: if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
! 2747: {
! 2748: same = rib;
! 2749: break;
! 2750: }
! 2751: if (same)
! 2752: break;
! 2753: }
1.1 misho 2754: }
2755:
2756: /* If same type of route can't be found and this message is from
2757: kernel. */
2758: if (! same)
2759: {
2760: if (fib && type == ZEBRA_ROUTE_KERNEL)
2761: {
2762: /* Unset flags. */
2763: for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
2764: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
2765:
1.1.1.4 ! misho 2766: UNSET_FLAG (fib->status, RIB_ENTRY_SELECTED_FIB);
1.1 misho 2767: }
2768: else
2769: {
2770: if (IS_ZEBRA_DEBUG_KERNEL)
2771: {
2772: if (gate)
1.1.1.4 ! misho 2773: zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
! 2774: "doesn't exist in rib",
! 2775: prefix2str (p, buf1, sizeof(buf1)), vrf_id,
1.1 misho 2776: inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
2777: ifindex,
2778: type);
2779: else
1.1.1.4 ! misho 2780: zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
! 2781: prefix2str (p, buf1, sizeof(buf1)), vrf_id,
1.1 misho 2782: ifindex,
2783: type);
2784: }
2785: route_unlock_node (rn);
2786: return ZEBRA_ERR_RTNOEXIST;
2787: }
2788: }
2789:
2790: if (same)
2791: rib_delnode (rn, same);
2792:
2793: route_unlock_node (rn);
2794: return 0;
2795: }
2796:
2797:
2798: /* Add static route into static route configuration. */
2799: int
2800: static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
2801: const char *ifname, u_char flags, u_char distance,
1.1.1.4 ! misho 2802: vrf_id_t vrf_id)
1.1 misho 2803: {
2804: struct route_node *rn;
1.1.1.4 ! misho 2805: struct static_route *si;
! 2806: struct static_route *pp;
! 2807: struct static_route *cp;
! 2808: struct static_route *update = NULL;
! 2809: struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
! 2810: struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST];
1.1 misho 2811:
2812: if (! stable)
2813: return -1;
2814:
2815: if (!gate &&
2816: (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2817: return -1;
2818:
2819: if (!ifname &&
2820: (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2821: return -1;
2822:
2823: /* Lookup static route prefix. */
2824: rn = route_node_get (stable, p);
2825:
2826: /* Do nothing if there is a same static route. */
2827: for (si = rn->info; si; si = si->next)
2828: {
1.1.1.4 ! misho 2829: if (type == si->type
! 2830: && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
1.1 misho 2831: && (! ifname || strcmp (ifname, si->ifname) == 0))
2832: {
1.1.1.4 ! misho 2833: if (distance == si->distance)
! 2834: {
! 2835: route_unlock_node (rn);
! 2836: return 0;
! 2837: }
! 2838: else
! 2839: update = si;
1.1 misho 2840: }
2841: }
2842:
1.1.1.4 ! misho 2843: if (update)
! 2844: static_delete_ipv6(p, type, gate, ifname, si->distance, vrf_id);
! 2845:
1.1 misho 2846: /* Make new static route structure. */
1.1.1.4 ! misho 2847: si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
1.1 misho 2848:
2849: si->type = type;
2850: si->distance = distance;
2851: si->flags = flags;
1.1.1.4 ! misho 2852: si->vrf_id = vrf_id;
1.1 misho 2853:
2854: switch (type)
2855: {
2856: case STATIC_IPV6_GATEWAY:
1.1.1.4 ! misho 2857: si->addr.ipv6 = *gate;
1.1 misho 2858: break;
2859: case STATIC_IPV6_IFNAME:
2860: si->ifname = XSTRDUP (0, ifname);
2861: break;
2862: case STATIC_IPV6_GATEWAY_IFNAME:
1.1.1.4 ! misho 2863: si->addr.ipv6 = *gate;
1.1 misho 2864: si->ifname = XSTRDUP (0, ifname);
2865: break;
2866: }
2867:
2868: /* Add new static route information to the tree with sort by
2869: distance value and gateway address. */
2870: for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2871: {
2872: if (si->distance < cp->distance)
2873: break;
2874: if (si->distance > cp->distance)
2875: continue;
2876: }
2877:
2878: /* Make linked list. */
2879: if (pp)
2880: pp->next = si;
2881: else
2882: rn->info = si;
2883: if (cp)
2884: cp->prev = si;
2885: si->prev = pp;
2886: si->next = cp;
2887:
2888: /* Install into rib. */
1.1.1.4 ! misho 2889: static_install_route (AFI_IP6, SAFI_UNICAST, p, si);
1.1 misho 2890:
2891: return 1;
2892: }
2893:
2894: /* Delete static route from static route configuration. */
2895: int
2896: static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
1.1.1.4 ! misho 2897: const char *ifname, u_char distance, vrf_id_t vrf_id)
1.1 misho 2898: {
2899: struct route_node *rn;
1.1.1.4 ! misho 2900: struct static_route *si;
1.1 misho 2901: struct route_table *stable;
2902:
2903: /* Lookup table. */
1.1.1.4 ! misho 2904: stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
1.1 misho 2905: if (! stable)
2906: return -1;
2907:
2908: /* Lookup static route prefix. */
2909: rn = route_node_lookup (stable, p);
2910: if (! rn)
2911: return 0;
2912:
2913: /* Find same static route is the tree */
2914: for (si = rn->info; si; si = si->next)
2915: if (distance == si->distance
2916: && type == si->type
1.1.1.4 ! misho 2917: && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
1.1 misho 2918: && (! ifname || strcmp (ifname, si->ifname) == 0))
2919: break;
2920:
2921: /* Can't find static route. */
2922: if (! si)
2923: {
2924: route_unlock_node (rn);
2925: return 0;
2926: }
2927:
2928: /* Install into rib. */
1.1.1.4 ! misho 2929: static_uninstall_route (AFI_IP6, SAFI_UNICAST, p, si);
1.1 misho 2930:
2931: /* Unlink static route from linked list. */
2932: if (si->prev)
2933: si->prev->next = si->next;
2934: else
2935: rn->info = si->next;
2936: if (si->next)
2937: si->next->prev = si->prev;
2938:
2939: /* Free static route configuration. */
2940: if (ifname)
2941: XFREE (0, si->ifname);
1.1.1.4 ! misho 2942: XFREE (MTYPE_STATIC_ROUTE, si);
1.1 misho 2943:
2944: return 1;
2945: }
1.1.1.4 ! misho 2946:
1.1 misho 2947: /* RIB update function. */
2948: void
1.1.1.4 ! misho 2949: rib_update (vrf_id_t vrf_id)
1.1 misho 2950: {
2951: struct route_node *rn;
2952: struct route_table *table;
2953:
1.1.1.4 ! misho 2954: table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
1.1 misho 2955: if (table)
2956: for (rn = route_top (table); rn; rn = route_next (rn))
1.1.1.3 misho 2957: if (rnode_to_ribs (rn))
1.1 misho 2958: rib_queue_add (&zebrad, rn);
2959:
1.1.1.4 ! misho 2960: table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
1.1 misho 2961: if (table)
2962: for (rn = route_top (table); rn; rn = route_next (rn))
1.1.1.3 misho 2963: if (rnode_to_ribs (rn))
1.1 misho 2964: rib_queue_add (&zebrad, rn);
2965: }
2966:
1.1.1.4 ! misho 2967:
1.1 misho 2968: /* Remove all routes which comes from non main table. */
2969: static void
2970: rib_weed_table (struct route_table *table)
2971: {
2972: struct route_node *rn;
2973: struct rib *rib;
2974: struct rib *next;
2975:
2976: if (table)
2977: for (rn = route_top (table); rn; rn = route_next (rn))
1.1.1.3 misho 2978: RNODE_FOREACH_RIB_SAFE (rn, rib, next)
1.1 misho 2979: {
2980: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2981: continue;
2982:
2983: if (rib->table != zebrad.rtm_table_default &&
2984: rib->table != RT_TABLE_MAIN)
2985: rib_delnode (rn, rib);
2986: }
2987: }
2988:
2989: /* Delete all routes from non main table. */
2990: void
2991: rib_weed_tables (void)
2992: {
1.1.1.4 ! misho 2993: vrf_iter_t iter;
! 2994: struct zebra_vrf *zvrf;
! 2995:
! 2996: for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
! 2997: if ((zvrf = vrf_iter2info (iter)) != NULL)
! 2998: {
! 2999: rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
! 3000: rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
! 3001: }
1.1 misho 3002: }
1.1.1.4 ! misho 3003:
! 3004: #if 0
1.1 misho 3005: /* Delete self installed routes after zebra is relaunched. */
3006: static void
3007: rib_sweep_table (struct route_table *table)
3008: {
3009: struct route_node *rn;
3010: struct rib *rib;
3011: struct rib *next;
3012: int ret = 0;
3013:
3014: if (table)
3015: for (rn = route_top (table); rn; rn = route_next (rn))
1.1.1.3 misho 3016: RNODE_FOREACH_RIB_SAFE (rn, rib, next)
1.1 misho 3017: {
3018: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3019: continue;
3020:
3021: if (rib->type == ZEBRA_ROUTE_KERNEL &&
3022: CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
3023: {
1.1.1.4 ! misho 3024: ret = rib_update_kernel (rn, rib, NULL);
1.1 misho 3025: if (! ret)
3026: rib_delnode (rn, rib);
3027: }
3028: }
3029: }
1.1.1.4 ! misho 3030: #endif
1.1 misho 3031:
3032: /* Sweep all RIB tables. */
3033: void
3034: rib_sweep_route (void)
3035: {
1.1.1.4 ! misho 3036: vrf_iter_t iter;
! 3037: struct zebra_vrf *zvrf;
! 3038:
! 3039: for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
! 3040: if ((zvrf = vrf_iter2info (iter)) != NULL)
! 3041: {
! 3042: rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
! 3043: rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
! 3044: }
1.1 misho 3045: }
1.1.1.2 misho 3046:
3047: /* Remove specific by protocol routes from 'table'. */
3048: static unsigned long
3049: rib_score_proto_table (u_char proto, struct route_table *table)
3050: {
3051: struct route_node *rn;
3052: struct rib *rib;
3053: struct rib *next;
3054: unsigned long n = 0;
3055:
3056: if (table)
3057: for (rn = route_top (table); rn; rn = route_next (rn))
1.1.1.3 misho 3058: RNODE_FOREACH_RIB_SAFE (rn, rib, next)
1.1.1.2 misho 3059: {
3060: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
3061: continue;
3062: if (rib->type == proto)
3063: {
3064: rib_delnode (rn, rib);
3065: n++;
3066: }
3067: }
3068:
3069: return n;
3070: }
3071:
3072: /* Remove specific by protocol routes. */
3073: unsigned long
3074: rib_score_proto (u_char proto)
3075: {
1.1.1.4 ! misho 3076: vrf_iter_t iter;
! 3077: struct zebra_vrf *zvrf;
! 3078: unsigned long cnt = 0;
! 3079:
! 3080: for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
! 3081: if ((zvrf = vrf_iter2info (iter)) != NULL)
! 3082: cnt += rib_score_proto_table (proto, zvrf->table[AFI_IP][SAFI_UNICAST])
! 3083: +rib_score_proto_table (proto, zvrf->table[AFI_IP6][SAFI_UNICAST]);
! 3084:
! 3085: return cnt;
1.1.1.2 misho 3086: }
3087:
1.1 misho 3088: /* Close RIB and clean up kernel routes. */
1.1.1.4 ! misho 3089: void
1.1 misho 3090: rib_close_table (struct route_table *table)
3091: {
3092: struct route_node *rn;
1.1.1.4 ! misho 3093: rib_table_info_t *info = table->info;
1.1 misho 3094: struct rib *rib;
3095:
3096: if (table)
3097: for (rn = route_top (table); rn; rn = route_next (rn))
1.1.1.3 misho 3098: RNODE_FOREACH_RIB (rn, rib)
1.1 misho 3099: {
1.1.1.4 ! misho 3100: if (!CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
1.1.1.3 misho 3101: continue;
3102:
1.1.1.4 ! misho 3103: if (info->safi == SAFI_UNICAST)
! 3104: zfpm_trigger_update (rn, NULL);
1.1.1.3 misho 3105:
3106: if (! RIB_SYSTEM_ROUTE (rib))
1.1.1.4 ! misho 3107: rib_update_kernel (rn, rib, NULL);
1.1 misho 3108: }
3109: }
3110:
3111: /* Close all RIB tables. */
3112: void
3113: rib_close (void)
3114: {
1.1.1.4 ! misho 3115: vrf_iter_t iter;
! 3116: struct zebra_vrf *zvrf;
! 3117:
! 3118: for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
! 3119: if ((zvrf = vrf_iter2info (iter)) != NULL)
! 3120: {
! 3121: rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
! 3122: rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
! 3123: }
1.1 misho 3124: }
1.1.1.4 ! misho 3125:
1.1 misho 3126: /* Routing information base initialize. */
3127: void
3128: rib_init (void)
3129: {
3130: rib_queue_init (&zebrad);
3131: }
1.1.1.3 misho 3132:
3133: /*
3134: * vrf_id_get_next
3135: *
3136: * Get the first vrf id that is greater than the given vrf id if any.
3137: *
3138: * Returns TRUE if a vrf id was found, FALSE otherwise.
3139: */
3140: static inline int
1.1.1.4 ! misho 3141: vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p)
1.1.1.3 misho 3142: {
1.1.1.4 ! misho 3143: vrf_iter_t iter = vrf_iterator (vrf_id);
! 3144: struct zebra_vrf *zvrf = vrf_iter2info (iter);
! 3145:
! 3146: /* The same one ? Then find out the next. */
! 3147: if (zvrf && (zvrf->vrf_id == vrf_id))
! 3148: zvrf = vrf_iter2info (vrf_next (iter));
! 3149:
! 3150: if (zvrf)
1.1.1.3 misho 3151: {
1.1.1.4 ! misho 3152: *next_id_p = zvrf->vrf_id;
! 3153: return 1;
1.1.1.3 misho 3154: }
3155:
3156: return 0;
3157: }
3158:
3159: /*
3160: * rib_tables_iter_next
3161: *
3162: * Returns the next table in the iteration.
3163: */
3164: struct route_table *
3165: rib_tables_iter_next (rib_tables_iter_t *iter)
3166: {
3167: struct route_table *table;
3168:
3169: /*
3170: * Array that helps us go over all AFI/SAFI combinations via one
3171: * index.
3172: */
3173: static struct {
3174: afi_t afi;
3175: safi_t safi;
3176: } afi_safis[] = {
3177: { AFI_IP, SAFI_UNICAST },
3178: { AFI_IP, SAFI_MULTICAST },
3179: { AFI_IP6, SAFI_UNICAST },
3180: { AFI_IP6, SAFI_MULTICAST },
3181: };
3182:
3183: table = NULL;
3184:
3185: switch (iter->state)
3186: {
3187:
3188: case RIB_TABLES_ITER_S_INIT:
1.1.1.4 ! misho 3189: iter->vrf_id = VRF_DEFAULT;
1.1.1.3 misho 3190: iter->afi_safi_ix = -1;
3191:
3192: /* Fall through */
3193:
3194: case RIB_TABLES_ITER_S_ITERATING:
3195: iter->afi_safi_ix++;
3196: while (1)
3197: {
3198:
3199: while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis))
3200: {
1.1.1.4 ! misho 3201: table = zebra_vrf_table (afi_safis[iter->afi_safi_ix].afi,
1.1.1.3 misho 3202: afi_safis[iter->afi_safi_ix].safi,
3203: iter->vrf_id);
3204: if (table)
3205: break;
3206:
3207: iter->afi_safi_ix++;
3208: }
3209:
3210: /*
3211: * Found another table in this vrf.
3212: */
3213: if (table)
3214: break;
3215:
3216: /*
3217: * Done with all tables in the current vrf, go to the next
3218: * one.
3219: */
3220: if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id))
3221: break;
3222:
3223: iter->afi_safi_ix = 0;
3224: }
3225:
3226: break;
3227:
3228: case RIB_TABLES_ITER_S_DONE:
3229: return NULL;
3230: }
3231:
3232: if (table)
3233: iter->state = RIB_TABLES_ITER_S_ITERATING;
3234: else
3235: iter->state = RIB_TABLES_ITER_S_DONE;
3236:
3237: return table;
3238: }
1.1.1.4 ! misho 3239:
! 3240: /*
! 3241: * Create a routing table for the specific AFI/SAFI in the given VRF.
! 3242: */
! 3243: static void
! 3244: zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
! 3245: {
! 3246: rib_table_info_t *info;
! 3247: struct route_table *table;
! 3248:
! 3249: assert (!zvrf->table[afi][safi]);
! 3250:
! 3251: table = route_table_init ();
! 3252: zvrf->table[afi][safi] = table;
! 3253:
! 3254: info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
! 3255: info->zvrf = zvrf;
! 3256: info->afi = afi;
! 3257: info->safi = safi;
! 3258: table->info = info;
! 3259: }
! 3260:
! 3261: /* Allocate new zebra VRF. */
! 3262: struct zebra_vrf *
! 3263: zebra_vrf_alloc (vrf_id_t vrf_id)
! 3264: {
! 3265: struct zebra_vrf *zvrf;
! 3266: #ifdef HAVE_NETLINK
! 3267: char nl_name[64];
! 3268: #endif
! 3269:
! 3270: zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
! 3271:
! 3272: /* Allocate routing table and static table. */
! 3273: zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
! 3274: zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
! 3275: zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
! 3276: zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
! 3277: zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
! 3278: zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
! 3279: zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
! 3280: zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
! 3281:
! 3282: /* Set VRF ID */
! 3283: zvrf->vrf_id = vrf_id;
! 3284:
! 3285: #ifdef HAVE_NETLINK
! 3286: /* Initialize netlink sockets */
! 3287: snprintf (nl_name, 64, "netlink-listen (vrf %u)", vrf_id);
! 3288: zvrf->netlink.sock = -1;
! 3289: zvrf->netlink.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
! 3290:
! 3291: snprintf (nl_name, 64, "netlink-cmd (vrf %u)", vrf_id);
! 3292: zvrf->netlink_cmd.sock = -1;
! 3293: zvrf->netlink_cmd.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name);
! 3294: #endif
! 3295:
! 3296: return zvrf;
! 3297: }
! 3298:
! 3299: /* Lookup the routing table in an enabled VRF. */
! 3300: struct route_table *
! 3301: zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
! 3302: {
! 3303: struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
! 3304:
! 3305: if (!zvrf)
! 3306: return NULL;
! 3307:
! 3308: if (afi >= AFI_MAX || safi >= SAFI_MAX)
! 3309: return NULL;
! 3310:
! 3311: return zvrf->table[afi][safi];
! 3312: }
! 3313:
! 3314: /* Lookup the static routing table in a VRF. */
! 3315: struct route_table *
! 3316: zebra_vrf_static_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
! 3317: {
! 3318: struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
! 3319:
! 3320: if (!zvrf)
! 3321: return NULL;
! 3322:
! 3323: if (afi >= AFI_MAX || safi >= SAFI_MAX)
! 3324: return NULL;
! 3325:
! 3326: return zvrf->stable[afi][safi];
! 3327: }
! 3328:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>