diff options
author | whitespace / reindent <invalid@invalid.invalid> | 2017-07-17 14:03:14 +0200 |
---|---|---|
committer | whitespace / reindent <invalid@invalid.invalid> | 2017-07-17 14:04:07 +0200 |
commit | d62a17aedeb0eebdba98238874bb13d62c48dbf9 (patch) | |
tree | 3b319b1d61c8b85b4d1f06adf8b844bb8a9b5107 /zebra | |
parent | *: add indent control files (diff) | |
download | frr-d62a17aedeb0eebdba98238874bb13d62c48dbf9.tar.xz frr-d62a17aedeb0eebdba98238874bb13d62c48dbf9.zip |
*: reindentreindent-master-after
indent.py `git ls-files | pcregrep '\.[ch]$' | pcregrep -v '^(ldpd|babeld|nhrpd)/'`
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'zebra')
84 files changed, 32006 insertions, 33417 deletions
diff --git a/zebra/client_main.c b/zebra/client_main.c index 2903b8425..17130c602 100644 --- a/zebra/client_main.c +++ b/zebra/client_main.c @@ -38,194 +38,176 @@ struct zclient *zclient = NULL; int sock; /* IPv4 route add and delete test. */ -void -zebra_test_ipv4 (int command, int type, char *prefix, char *gateway, - u_char distance) +void zebra_test_ipv4(int command, int type, char *prefix, char *gateway, + u_char distance) { - struct zapi_ipv4 api; - struct prefix_ipv4 p; - struct in_addr gate; - struct in_addr *gpnt; - - str2prefix_ipv4 (prefix, &p); - if (!inet_aton (gateway, &gate)) - { - printf("Gateway specified: %s is illegal\n", gateway); - return; - } - - gpnt = &gate; - - api.vrf_id = VRF_DEFAULT; - api.type = type; - api.flags = 0; - - api.message = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; - api.nexthop = &gpnt; - api.ifindex_num = 0; - if (distance) - { - SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = distance; - } - - - switch (command) - { - case ZEBRA_IPV4_ROUTE_ADD: - zapi_ipv4_add (zclient, &p, &api); - break; - case ZEBRA_IPV4_ROUTE_DELETE: - zapi_ipv4_delete (zclient, &p, &api); - break; - } + struct zapi_ipv4 api; + struct prefix_ipv4 p; + struct in_addr gate; + struct in_addr *gpnt; + + str2prefix_ipv4(prefix, &p); + if (!inet_aton(gateway, &gate)) { + printf("Gateway specified: %s is illegal\n", gateway); + return; + } + + gpnt = &gate; + + api.vrf_id = VRF_DEFAULT; + api.type = type; + api.flags = 0; + + api.message = 0; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 1; + api.nexthop = &gpnt; + api.ifindex_num = 0; + if (distance) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = distance; + } + + + switch (command) { + case ZEBRA_IPV4_ROUTE_ADD: + zapi_ipv4_add(zclient, &p, &api); + break; + case ZEBRA_IPV4_ROUTE_DELETE: + zapi_ipv4_delete(zclient, &p, &api); + break; + } } /* IPv6 route add and delete test. */ -void -zebra_test_v6 (int sock) +void zebra_test_v6(int sock) { - struct prefix_ipv6 p; - struct in6_addr nexthop; + struct prefix_ipv6 p; + struct in6_addr nexthop; - str2prefix_ipv6 ("3ffe:506::2/128", &p); - inet_pton (AF_INET6, "::1", &nexthop); + str2prefix_ipv6("3ffe:506::2/128", &p); + inet_pton(AF_INET6, "::1", &nexthop); - /* zebra_ipv6_add (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */ + /* zebra_ipv6_add (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */ - sleep (5); - /* zebra_ipv6_delete (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */ + sleep(5); + /* zebra_ipv6_delete (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */ } /* Print out usage and exit. */ -void -usage_exit () +void usage_exit() { - fprintf (stderr, "Usage: client filename\n"); - exit (1); + fprintf(stderr, "Usage: client filename\n"); + exit(1); } -struct zebra_info -{ - char *str; - int type; -} zebra_type[] = -{ - { "static", ZEBRA_ROUTE_STATIC }, - { "rip", ZEBRA_ROUTE_RIP }, - { "ripng", ZEBRA_ROUTE_RIPNG }, - { "ospf", ZEBRA_ROUTE_OSPF }, - { "ospf6", ZEBRA_ROUTE_OSPF6 }, - { "bgp", ZEBRA_ROUTE_BGP }, - { "nhrp", ZEBRA_ROUTE_NHRP }, - { "pim", ZEBRA_ROUTE_PIM }, - { NULL, 0 } -}; +struct zebra_info { + char *str; + int type; +} zebra_type[] = {{"static", ZEBRA_ROUTE_STATIC}, + {"rip", ZEBRA_ROUTE_RIP}, + {"ripng", ZEBRA_ROUTE_RIPNG}, + {"ospf", ZEBRA_ROUTE_OSPF}, + {"ospf6", ZEBRA_ROUTE_OSPF6}, + {"bgp", ZEBRA_ROUTE_BGP}, + {"nhrp", ZEBRA_ROUTE_NHRP}, + {"pim", ZEBRA_ROUTE_PIM}, + {NULL, 0}}; /* Zebra route simulator. */ -void -zebra_sim (FILE *fp) +void zebra_sim(FILE *fp) { - char buf[BUFSIZ]; - char distance_str[BUFSIZ]; - u_char distance; - - while (fgets (buf, sizeof buf, fp)) - { - int i; - int ret; - int type; - char str[BUFSIZ], command[BUFSIZ], prefix[BUFSIZ], gateway[BUFSIZ]; - - distance = 0; - - if (*buf == '#') - continue; - - type = ZEBRA_ROUTE_STATIC; - - ret = sscanf (buf, "%s %s %s %s %s\n", command, str, prefix, gateway, - distance_str); - - if (ret == 5) - { - distance = atoi (distance_str); - } - else - { - ret = sscanf (buf, "%s %s %s %s\n", command, str, prefix, gateway); - - if (ret != 4) - continue; + char buf[BUFSIZ]; + char distance_str[BUFSIZ]; + u_char distance; + + while (fgets(buf, sizeof buf, fp)) { + int i; + int ret; + int type; + char str[BUFSIZ], command[BUFSIZ], prefix[BUFSIZ], + gateway[BUFSIZ]; + + distance = 0; + + if (*buf == '#') + continue; + + type = ZEBRA_ROUTE_STATIC; + + ret = sscanf(buf, "%s %s %s %s %s\n", command, str, prefix, + gateway, distance_str); + + if (ret == 5) { + distance = atoi(distance_str); + } else { + ret = sscanf(buf, "%s %s %s %s\n", command, str, prefix, + gateway); + + if (ret != 4) + continue; + } + + for (i = 0; i < 10; i++) { + if (!zebra_type[i].str) + break; + if (strcmp(zebra_type[i].str, str) == 0) { + type = zebra_type[i].type; + break; + } + } + + if (strcmp(command, "add") == 0) { + zebra_test_ipv4(ZEBRA_IPV4_ROUTE_ADD, type, prefix, + gateway, distance); + printf("%s", buf); + continue; + } + + if (strcmp(command, "del") == 0) { + zebra_test_ipv4(ZEBRA_IPV4_ROUTE_DELETE, type, prefix, + gateway, distance); + printf("%s", buf); + continue; + } } - - for (i = 0; i < 10; i++) - { - if (!zebra_type[i].str) - break; - if (strcmp (zebra_type[i].str, str) == 0) - { - type = zebra_type[i].type; - break; - } - } - - if (strcmp (command, "add") == 0) - { - zebra_test_ipv4 (ZEBRA_IPV4_ROUTE_ADD, type, prefix, gateway, - distance); - printf ("%s", buf); - continue; - } - - if (strcmp (command, "del") == 0) - { - zebra_test_ipv4 (ZEBRA_IPV4_ROUTE_DELETE, type, prefix, gateway, - distance); - printf ("%s", buf); - continue; - } - } } /* Test zebra client main routine. */ -int -main (int argc, char **argv) +int main(int argc, char **argv) { - struct thread_master *master; - FILE *fp; + struct thread_master *master; + FILE *fp; - if (argc == 1) - usage_exit (); + if (argc == 1) + usage_exit(); - master = thread_master_create(NULL); - /* Establish connection to zebra. */ - zclient = zclient_new(master); - zclient->enable = 1; + master = thread_master_create(NULL); + /* Establish connection to zebra. */ + zclient = zclient_new(master); + zclient->enable = 1; #ifdef HAVE_TCP_ZEBRA - zclient->sock = zclient_socket (); + zclient->sock = zclient_socket(); #else - zclient->sock = zclient_socket_un (ZEBRA_SERV_PATH); + zclient->sock = zclient_socket_un(ZEBRA_SERV_PATH); #endif /* HAVE_TCP_ZEBRA */ - /* Open simulation file. */ - fp = fopen (argv[1], "r"); - if (fp == NULL) - { - fprintf (stderr,"%% Can't open configuration file %s due to '%s'\n", - argv[1], safe_strerror(errno)); - exit (1); - } + /* Open simulation file. */ + fp = fopen(argv[1], "r"); + if (fp == NULL) { + fprintf(stderr, + "%% Can't open configuration file %s due to '%s'\n", + argv[1], safe_strerror(errno)); + exit(1); + } - /* Do main work. */ - zebra_sim (fp); + /* Do main work. */ + zebra_sim(fp); - sleep (100); + sleep(100); - fclose (fp); - close (sock); + fclose(fp); + close(sock); - return 0; + return 0; } diff --git a/zebra/connected.c b/zebra/connected.c index 4d8fe9f6d..80f9ebe5e 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -42,533 +42,528 @@ #include "zebra/debug.h" /* communicate the withdrawal of a connected address */ -static void -connected_withdraw (struct connected *ifc) +static void connected_withdraw(struct connected *ifc) { - if (! ifc) - return; + if (!ifc) + return; - /* Update interface address information to protocol daemon. */ - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - { - zebra_interface_address_delete_update (ifc->ifp, ifc); + /* Update interface address information to protocol daemon. */ + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) { + zebra_interface_address_delete_update(ifc->ifp, ifc); - if (ifc->address->family == AF_INET) - if_subnet_delete (ifc->ifp, ifc); + if (ifc->address->family == AF_INET) + if_subnet_delete(ifc->ifp, ifc); - if (ifc->address->family == AF_INET) - connected_down_ipv4 (ifc->ifp, ifc); - else - connected_down_ipv6 (ifc->ifp, ifc); + if (ifc->address->family == AF_INET) + connected_down_ipv4(ifc->ifp, ifc); + else + connected_down_ipv6(ifc->ifp, ifc); - UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - } + UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL); + } - /* The address is not in the kernel anymore, so clear the flag */ - UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* The address is not in the kernel anymore, so clear the flag */ + UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); - if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - { - listnode_delete (ifc->ifp->connected, ifc); - connected_free (ifc); - } + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) { + listnode_delete(ifc->ifp->connected, ifc); + connected_free(ifc); + } } -static void -connected_announce (struct interface *ifp, struct connected *ifc) +static void connected_announce(struct interface *ifp, struct connected *ifc) { - if (!ifc) - return; - - if (!if_is_loopback(ifp) && ifc->address->family == AF_INET) - { - if (ifc->address->prefixlen == 32) - SET_FLAG (ifc->flags, ZEBRA_IFA_UNNUMBERED); - else - UNSET_FLAG (ifc->flags, ZEBRA_IFA_UNNUMBERED); - } - - listnode_add (ifp->connected, ifc); - - /* Update interface address information to protocol daemon. */ - if (ifc->address->family == AF_INET) - if_subnet_add (ifp, ifc); - - zebra_interface_address_add_update (ifp, ifc); - - if (if_is_operative(ifp)) - { - if (ifc->address->family == AF_INET) - connected_up_ipv4 (ifp, ifc); - else - connected_up_ipv6 (ifp, ifc); - } + if (!ifc) + return; + + if (!if_is_loopback(ifp) && ifc->address->family == AF_INET) { + if (ifc->address->prefixlen == 32) + SET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED); + else + UNSET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED); + } + + listnode_add(ifp->connected, ifc); + + /* Update interface address information to protocol daemon. */ + if (ifc->address->family == AF_INET) + if_subnet_add(ifp, ifc); + + zebra_interface_address_add_update(ifp, ifc); + + if (if_is_operative(ifp)) { + if (ifc->address->family == AF_INET) + connected_up_ipv4(ifp, ifc); + else + connected_up_ipv6(ifp, ifc); + } } /* If same interface address is already exist... */ -struct connected * -connected_check (struct interface *ifp, struct prefix *p) +struct connected *connected_check(struct interface *ifp, struct prefix *p) { - struct connected *ifc; - struct listnode *node; + struct connected *ifc; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) - if (prefix_same (ifc->address, p)) - return ifc; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) + if (prefix_same(ifc->address, p)) + return ifc; - return NULL; + return NULL; } /* Check if two ifc's describe the same address in the same state */ -static int -connected_same (struct connected *ifc1, struct connected *ifc2) +static int connected_same(struct connected *ifc1, struct connected *ifc2) { - if (ifc1->ifp != ifc2->ifp) - return 0; - - if (ifc1->destination) - if (!ifc2->destination) - return 0; - if (ifc2->destination) - if (!ifc1->destination) - return 0; - - if (ifc1->destination && ifc2->destination) - if (!prefix_same (ifc1->destination, ifc2->destination)) - return 0; - - if (ifc1->flags != ifc2->flags) - return 0; - - if (ifc1->conf != ifc2->conf) - return 0; - - return 1; + if (ifc1->ifp != ifc2->ifp) + return 0; + + if (ifc1->destination) + if (!ifc2->destination) + return 0; + if (ifc2->destination) + if (!ifc1->destination) + return 0; + + if (ifc1->destination && ifc2->destination) + if (!prefix_same(ifc1->destination, ifc2->destination)) + return 0; + + if (ifc1->flags != ifc2->flags) + return 0; + + if (ifc1->conf != ifc2->conf) + return 0; + + return 1; } /* Handle changes to addresses and send the neccesary announcements * to clients. */ -static void -connected_update(struct interface *ifp, struct connected *ifc) +static void connected_update(struct interface *ifp, struct connected *ifc) { - struct connected *current; - - /* Check same connected route. */ - if ((current = connected_check (ifp, (struct prefix *) ifc->address))) - { - if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED)) - SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); - - /* Avoid spurious withdraws, this might be just the kernel 'reflecting' - * back an address we have already added. - */ - if (connected_same (current, ifc)) - { - /* nothing to do */ - connected_free (ifc); - return; - } - - /* Clear the configured flag on the old ifc, so it will be freed by - * connected withdraw. */ - UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED); - connected_withdraw (current); /* implicit withdraw - freebsd does this */ - } - - /* If the connected is new or has changed, announce it, if it is usable */ - if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) - connected_announce(ifp, ifc); + struct connected *current; + + /* Check same connected route. */ + if ((current = connected_check(ifp, (struct prefix *)ifc->address))) { + if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED)) + SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); + + /* Avoid spurious withdraws, this might be just the kernel + * 'reflecting' + * back an address we have already added. + */ + if (connected_same(current, ifc)) { + /* nothing to do */ + connected_free(ifc); + return; + } + + /* Clear the configured flag on the old ifc, so it will be freed + * by + * connected withdraw. */ + UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED); + connected_withdraw( + current); /* implicit withdraw - freebsd does this */ + } + + /* If the connected is new or has changed, announce it, if it is usable + */ + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + connected_announce(ifp, ifc); } /* Called from if_up(). */ -void -connected_up_ipv4 (struct interface *ifp, struct connected *ifc) +void connected_up_ipv4(struct interface *ifp, struct connected *ifc) { - struct prefix p; - - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - return; - - PREFIX_COPY_IPV4((struct prefix_ipv4 *)&p, CONNECTED_PREFIX(ifc)); - - /* Apply mask to the network. */ - apply_mask (&p); - - /* In case of connected address is 0.0.0.0/0 we treat it tunnel - address. */ - if (prefix_ipv4_any ((struct prefix_ipv4 *)&p)) - return; - - rib_add (AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, NULL, ifp->ifindex, - RT_TABLE_MAIN, ifp->metric, 0, 0); - - rib_add (AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, NULL, ifp->ifindex, - RT_TABLE_MAIN, ifp->metric, 0, 0); - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling RIB processing", - ifp->vrf_id, ifp->name); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - - /* Schedule LSP forwarding entries for processing, if appropriate. */ - if (ifp->vrf_id == VRF_DEFAULT) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling MPLS processing", - ifp->vrf_id, ifp->name); - mpls_mark_lsps_for_processing (vrf_info_lookup(ifp->vrf_id)); - } + struct prefix p; + + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + return; + + PREFIX_COPY_IPV4((struct prefix_ipv4 *)&p, CONNECTED_PREFIX(ifc)); + + /* Apply mask to the network. */ + apply_mask(&p); + + /* In case of connected address is 0.0.0.0/0 we treat it tunnel + address. */ + if (prefix_ipv4_any((struct prefix_ipv4 *)&p)) + return; + + rib_add(AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, + &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, + 0, 0); + + rib_add(AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, + &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, + 0, 0); + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling RIB processing", + ifp->vrf_id, ifp->name); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + + /* Schedule LSP forwarding entries for processing, if appropriate. */ + if (ifp->vrf_id == VRF_DEFAULT) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling MPLS processing", + ifp->vrf_id, ifp->name); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + } } /* Add connected IPv4 route to the interface. */ -void -connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, - u_char prefixlen, struct in_addr *broad, - const char *label) +void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr, + u_char prefixlen, struct in_addr *broad, + const char *label) { - struct prefix_ipv4 *p; - struct connected *ifc; - - if (ipv4_martian(addr)) - return; - - /* Make connected structure. */ - ifc = connected_new (); - ifc->ifp = ifp; - ifc->flags = flags; - /* If we get a notification from the kernel, - * we can safely assume the address is known to the kernel */ - SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); - - /* Allocate new connected address. */ - p = prefix_ipv4_new (); - p->family = AF_INET; - p->prefix = *addr; - p->prefixlen = prefixlen; - ifc->address = (struct prefix *) p; - - /* If there is broadcast or peer address. */ - if (broad) - { - p = prefix_ipv4_new (); - p->family = AF_INET; - p->prefix = *broad; - p->prefixlen = prefixlen; - ifc->destination = (struct prefix *) p; - - /* validate the destination address */ - if (CONNECTED_PEER(ifc)) - { - if (IPV4_ADDR_SAME(addr,broad)) - zlog_warn("warning: interface %s has same local and peer " - "address %s, routing protocols may malfunction", - ifp->name,inet_ntoa(*addr)); - } - else - { - if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen)) - { - char buf[2][INET_ADDRSTRLEN]; - struct in_addr bcalc; - bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen); - zlog_warn("warning: interface %s broadcast addr %s/%d != " - "calculated %s, routing protocols may malfunction", - ifp->name, - inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])), - prefixlen, - inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1]))); - } - } - - } - else - { - if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) - { - zlog_warn("warning: %s called for interface %s " - "with peer flag set, but no peer address supplied", - __func__, ifp->name); - UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); + struct prefix_ipv4 *p; + struct connected *ifc; + + if (ipv4_martian(addr)) + return; + + /* Make connected structure. */ + ifc = connected_new(); + ifc->ifp = ifp; + ifc->flags = flags; + /* If we get a notification from the kernel, + * we can safely assume the address is known to the kernel */ + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + + /* Allocate new connected address. */ + p = prefix_ipv4_new(); + p->family = AF_INET; + p->prefix = *addr; + p->prefixlen = prefixlen; + ifc->address = (struct prefix *)p; + + /* If there is broadcast or peer address. */ + if (broad) { + p = prefix_ipv4_new(); + p->family = AF_INET; + p->prefix = *broad; + p->prefixlen = prefixlen; + ifc->destination = (struct prefix *)p; + + /* validate the destination address */ + if (CONNECTED_PEER(ifc)) { + if (IPV4_ADDR_SAME(addr, broad)) + zlog_warn( + "warning: interface %s has same local and peer " + "address %s, routing protocols may malfunction", + ifp->name, inet_ntoa(*addr)); + } else { + if (broad->s_addr + != ipv4_broadcast_addr(addr->s_addr, prefixlen)) { + char buf[2][INET_ADDRSTRLEN]; + struct in_addr bcalc; + bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr, + prefixlen); + zlog_warn( + "warning: interface %s broadcast addr %s/%d != " + "calculated %s, routing protocols may malfunction", + ifp->name, + inet_ntop(AF_INET, broad, buf[0], + sizeof(buf[0])), + prefixlen, + inet_ntop(AF_INET, &bcalc, buf[1], + sizeof(buf[1]))); + } + } + + } else { + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) { + zlog_warn( + "warning: %s called for interface %s " + "with peer flag set, but no peer address supplied", + __func__, ifp->name); + UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); + } + + /* no broadcast or destination address was supplied */ + if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp)) + zlog_warn( + "warning: PtP interface %s with addr %s/%d needs a " + "peer address", + ifp->name, inet_ntoa(*addr), prefixlen); } - /* no broadcast or destination address was supplied */ - if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp)) - zlog_warn("warning: PtP interface %s with addr %s/%d needs a " - "peer address",ifp->name,inet_ntoa(*addr),prefixlen); - } + /* Label of this address. */ + if (label) + ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); - /* Label of this address. */ - if (label) - ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); + /* For all that I know an IPv4 address is always ready when we receive + * the notification. So it should be safe to set the REAL flag here. */ + SET_FLAG(ifc->conf, ZEBRA_IFC_REAL); - /* For all that I know an IPv4 address is always ready when we receive - * the notification. So it should be safe to set the REAL flag here. */ - SET_FLAG(ifc->conf, ZEBRA_IFC_REAL); - - connected_update(ifp, ifc); + connected_update(ifp, ifc); } -void -connected_down_ipv4 (struct interface *ifp, struct connected *ifc) +void connected_down_ipv4(struct interface *ifp, struct connected *ifc) { - struct prefix p; + struct prefix p; - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - return; + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + return; - PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); + PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); - /* Apply mask to the network. */ - apply_mask (&p); + /* Apply mask to the network. */ + apply_mask(&p); - /* In case of connected address is 0.0.0.0/0 we treat it tunnel - address. */ - if (prefix_ipv4_any ((struct prefix_ipv4 *)&p)) - return; + /* In case of connected address is 0.0.0.0/0 we treat it tunnel + address. */ + if (prefix_ipv4_any((struct prefix_ipv4 *)&p)) + return; - /* Same logic as for connected_up_ipv4(): push the changes into the head. */ - rib_delete (AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, ifp->ifindex, 0); + /* Same logic as for connected_up_ipv4(): push the changes into the + * head. */ + rib_delete(AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, + &p, NULL, NULL, ifp->ifindex, 0); - rib_delete (AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, ifp->ifindex, 0); + rib_delete(AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, + 0, &p, NULL, NULL, ifp->ifindex, 0); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s IPv4 address down, scheduling RIB processing", - ifp->vrf_id, ifp->name); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IF %s IPv4 address down, scheduling RIB processing", + ifp->vrf_id, ifp->name); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - /* Schedule LSP forwarding entries for processing, if appropriate. */ - if (ifp->vrf_id == VRF_DEFAULT) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling MPLS processing", - ifp->vrf_id, ifp->name); - mpls_mark_lsps_for_processing (vrf_info_lookup(ifp->vrf_id)); - } + /* Schedule LSP forwarding entries for processing, if appropriate. */ + if (ifp->vrf_id == VRF_DEFAULT) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling MPLS processing", + ifp->vrf_id, ifp->name); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + } } /* Delete connected IPv4 route to the interface. */ -void -connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, - u_char prefixlen, struct in_addr *broad) +void connected_delete_ipv4(struct interface *ifp, int flags, + struct in_addr *addr, u_char prefixlen, + struct in_addr *broad) { - struct prefix_ipv4 p; - struct connected *ifc; - - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefix = *addr; - p.prefixlen = prefixlen; - - ifc = connected_check (ifp, (struct prefix *) &p); - if (! ifc) - return; - - connected_withdraw (ifc); - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s IPv4 address del, scheduling RIB processing", - ifp->vrf_id, ifp->name); - - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - - /* Schedule LSP forwarding entries for processing, if appropriate. */ - if (ifp->vrf_id == VRF_DEFAULT) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling MPLS processing", - ifp->vrf_id, ifp->name); - mpls_mark_lsps_for_processing (vrf_info_lookup(ifp->vrf_id)); - } + struct prefix_ipv4 p; + struct connected *ifc; + + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefix = *addr; + p.prefixlen = prefixlen; + + ifc = connected_check(ifp, (struct prefix *)&p); + if (!ifc) + return; + + connected_withdraw(ifc); + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IF %s IPv4 address del, scheduling RIB processing", + ifp->vrf_id, ifp->name); + + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + + /* Schedule LSP forwarding entries for processing, if appropriate. */ + if (ifp->vrf_id == VRF_DEFAULT) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling MPLS processing", + ifp->vrf_id, ifp->name); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + } } -void -connected_up_ipv6 (struct interface *ifp, struct connected *ifc) +void connected_up_ipv6(struct interface *ifp, struct connected *ifc) { - struct prefix p; + struct prefix p; - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - return; + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + return; - PREFIX_COPY_IPV6((struct prefix_ipv6 *)&p, CONNECTED_PREFIX(ifc)); + PREFIX_COPY_IPV6((struct prefix_ipv6 *)&p, CONNECTED_PREFIX(ifc)); - /* Apply mask to the network. */ - apply_mask (&p); + /* Apply mask to the network. */ + apply_mask(&p); #ifndef LINUX - /* XXX: It is already done by rib_bogus_ipv6 within rib_add */ - if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) - return; + /* XXX: It is already done by rib_bogus_ipv6 within rib_add */ + if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6)) + return; #endif - rib_add (AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, NULL, ifp->ifindex, - RT_TABLE_MAIN, ifp->metric, 0, 0); + rib_add(AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, + &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, + 0, 0); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing", - ifp->vrf_id, ifp->name); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IF %s IPv6 address down, scheduling RIB processing", + ifp->vrf_id, ifp->name); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - /* Schedule LSP forwarding entries for processing, if appropriate. */ - if (ifp->vrf_id == VRF_DEFAULT) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling MPLS processing", - ifp->vrf_id, ifp->name); - mpls_mark_lsps_for_processing (vrf_info_lookup(ifp->vrf_id)); - } + /* Schedule LSP forwarding entries for processing, if appropriate. */ + if (ifp->vrf_id == VRF_DEFAULT) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling MPLS processing", + ifp->vrf_id, ifp->name); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + } } /* Add connected IPv6 route to the interface. */ -void -connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr, - u_char prefixlen, struct in6_addr *broad, - const char *label) +void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr, + u_char prefixlen, struct in6_addr *broad, + const char *label) { - struct prefix_ipv6 *p; - struct connected *ifc; - - if (ipv6_martian(addr)) - return; - - /* Make connected structure. */ - ifc = connected_new (); - ifc->ifp = ifp; - ifc->flags = flags; - /* If we get a notification from the kernel, - * we can safely assume the address is known to the kernel */ - SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); - - /* Allocate new connected address. */ - p = prefix_ipv6_new (); - p->family = AF_INET6; - IPV6_ADDR_COPY (&p->prefix, addr); - p->prefixlen = prefixlen; - ifc->address = (struct prefix *) p; - - /* If there is broadcast or peer address. */ - if (broad) - { - if (IN6_IS_ADDR_UNSPECIFIED(broad)) - zlog_warn("warning: %s called for interface %s with unspecified " - "destination address; ignoring!", __func__, ifp->name); - else - { - p = prefix_ipv6_new (); - p->family = AF_INET6; - IPV6_ADDR_COPY (&p->prefix, broad); - p->prefixlen = prefixlen; - ifc->destination = (struct prefix *) p; + struct prefix_ipv6 *p; + struct connected *ifc; + + if (ipv6_martian(addr)) + return; + + /* Make connected structure. */ + ifc = connected_new(); + ifc->ifp = ifp; + ifc->flags = flags; + /* If we get a notification from the kernel, + * we can safely assume the address is known to the kernel */ + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + + /* Allocate new connected address. */ + p = prefix_ipv6_new(); + p->family = AF_INET6; + IPV6_ADDR_COPY(&p->prefix, addr); + p->prefixlen = prefixlen; + ifc->address = (struct prefix *)p; + + /* If there is broadcast or peer address. */ + if (broad) { + if (IN6_IS_ADDR_UNSPECIFIED(broad)) + zlog_warn( + "warning: %s called for interface %s with unspecified " + "destination address; ignoring!", + __func__, ifp->name); + else { + p = prefix_ipv6_new(); + p->family = AF_INET6; + IPV6_ADDR_COPY(&p->prefix, broad); + p->prefixlen = prefixlen; + ifc->destination = (struct prefix *)p; + } + } + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination) { + zlog_warn( + "warning: %s called for interface %s " + "with peer flag set, but no peer address supplied", + __func__, ifp->name); + UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); } - } - if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination) - { - zlog_warn("warning: %s called for interface %s " - "with peer flag set, but no peer address supplied", - __func__, ifp->name); - UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); - } - - /* Label of this address. */ - if (label) - ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); - - /* On Linux, we only get here when DAD is complete, therefore we can set - * ZEBRA_IFC_REAL. - * - * On BSD, there currently doesn't seem to be a way to check for completion of - * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, although DAD - * might still be running. - */ - SET_FLAG(ifc->conf, ZEBRA_IFC_REAL); - connected_update(ifp, ifc); + + /* Label of this address. */ + if (label) + ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); + + /* On Linux, we only get here when DAD is complete, therefore we can set + * ZEBRA_IFC_REAL. + * + * On BSD, there currently doesn't seem to be a way to check for + * completion of + * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, + * although DAD + * might still be running. + */ + SET_FLAG(ifc->conf, ZEBRA_IFC_REAL); + connected_update(ifp, ifc); } -void -connected_down_ipv6 (struct interface *ifp, struct connected *ifc) +void connected_down_ipv6(struct interface *ifp, struct connected *ifc) { - struct prefix p; + struct prefix p; - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - return; + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + return; - PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); + PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); - apply_mask (&p); + apply_mask(&p); - if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) - return; + if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6)) + return; - rib_delete (AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, ifp->ifindex, 0); + rib_delete(AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, + 0, &p, NULL, NULL, ifp->ifindex, 0); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing", - ifp->vrf_id, ifp->name); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IF %s IPv6 address down, scheduling RIB processing", + ifp->vrf_id, ifp->name); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - /* Schedule LSP forwarding entries for processing, if appropriate. */ - if (ifp->vrf_id == VRF_DEFAULT) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling MPLS processing", - ifp->vrf_id, ifp->name); - mpls_mark_lsps_for_processing (vrf_info_lookup(ifp->vrf_id)); - } + /* Schedule LSP forwarding entries for processing, if appropriate. */ + if (ifp->vrf_id == VRF_DEFAULT) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling MPLS processing", + ifp->vrf_id, ifp->name); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + } } -void -connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address, - u_char prefixlen, struct in6_addr *broad) +void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address, + u_char prefixlen, struct in6_addr *broad) { - struct prefix_ipv6 p; - struct connected *ifc; - - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - memcpy (&p.prefix, address, sizeof (struct in6_addr)); - p.prefixlen = prefixlen; - - ifc = connected_check (ifp, (struct prefix *) &p); - if (! ifc) - return; - - connected_withdraw (ifc); - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s IPv6 address del, scheduling RIB processing", - ifp->vrf_id, ifp->name); - - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - - /* Schedule LSP forwarding entries for processing, if appropriate. */ - if (ifp->vrf_id == VRF_DEFAULT) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling MPLS processing", - ifp->vrf_id, ifp->name); - mpls_mark_lsps_for_processing (vrf_info_lookup(ifp->vrf_id)); - } + struct prefix_ipv6 p; + struct connected *ifc; + + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + memcpy(&p.prefix, address, sizeof(struct in6_addr)); + p.prefixlen = prefixlen; + + ifc = connected_check(ifp, (struct prefix *)&p); + if (!ifc) + return; + + connected_withdraw(ifc); + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IF %s IPv6 address del, scheduling RIB processing", + ifp->vrf_id, ifp->name); + + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + + /* Schedule LSP forwarding entries for processing, if appropriate. */ + if (ifp->vrf_id == VRF_DEFAULT) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling MPLS processing", + ifp->vrf_id, ifp->name); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + } } -int -connected_is_unnumbered (struct interface *ifp) +int connected_is_unnumbered(struct interface *ifp) { - struct connected *connected; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) - { - if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) && - connected->address->family == AF_INET) - return CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED); - } - return 0; + struct connected *connected; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { + if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) + && connected->address->family == AF_INET) + return CHECK_FLAG(connected->flags, + ZEBRA_IFA_UNNUMBERED); + } + return 0; } diff --git a/zebra/connected.h b/zebra/connected.h index 3e3734685..eaf79fe9a 100644 --- a/zebra/connected.h +++ b/zebra/connected.h @@ -22,35 +22,32 @@ #ifndef _ZEBRA_CONNECTED_H #define _ZEBRA_CONNECTED_H -extern struct connected * -connected_check (struct interface *ifp, struct prefix *p); +extern struct connected *connected_check(struct interface *ifp, + struct prefix *p); -extern void -connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, - u_char prefixlen, struct in_addr *broad, - const char *label); +extern void connected_add_ipv4(struct interface *ifp, int flags, + struct in_addr *addr, u_char prefixlen, + struct in_addr *broad, const char *label); -extern void -connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, - u_char prefixlen, struct in_addr *broad); +extern void connected_delete_ipv4(struct interface *ifp, int flags, + struct in_addr *addr, u_char prefixlen, + struct in_addr *broad); -extern void -connected_delete_ipv4_unnumbered (struct connected *ifc); +extern void connected_delete_ipv4_unnumbered(struct connected *ifc); -extern void connected_up_ipv4 (struct interface *, struct connected *); -extern void connected_down_ipv4 (struct interface *, struct connected *); +extern void connected_up_ipv4(struct interface *, struct connected *); +extern void connected_down_ipv4(struct interface *, struct connected *); -extern void -connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *address, - u_char prefixlen, struct in6_addr *broad, - const char *label); -extern void -connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address, - u_char prefixlen, struct in6_addr *broad); +extern void connected_add_ipv6(struct interface *ifp, int flags, + struct in6_addr *address, u_char prefixlen, + struct in6_addr *broad, const char *label); +extern void connected_delete_ipv6(struct interface *ifp, + struct in6_addr *address, u_char prefixlen, + struct in6_addr *broad); -extern void connected_up_ipv6 (struct interface *, struct connected *); -extern void connected_down_ipv6 (struct interface *ifp, struct connected *); +extern void connected_up_ipv6(struct interface *, struct connected *); +extern void connected_down_ipv6(struct interface *ifp, struct connected *); -extern int connected_is_unnumbered (struct interface *); +extern int connected_is_unnumbered(struct interface *); #endif /*_ZEBRA_CONNECTED_H */ diff --git a/zebra/debug.c b/zebra/debug.c index 1c3cf9a3d..dfee6b74c 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -40,50 +40,50 @@ DEFUN (show_debugging_zebra, "Debugging information\n" "Zebra configuration\n") { - vty_out (vty, "Zebra debugging status:\n"); - - if (IS_ZEBRA_DEBUG_EVENT) - vty_out (vty, " Zebra event debugging is on\n"); - - if (IS_ZEBRA_DEBUG_PACKET) - { - if (IS_ZEBRA_DEBUG_SEND && IS_ZEBRA_DEBUG_RECV) - { - vty_out (vty, " Zebra packet%s debugging is on\n", - IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + vty_out(vty, "Zebra debugging status:\n"); + + if (IS_ZEBRA_DEBUG_EVENT) + vty_out(vty, " Zebra event debugging is on\n"); + + if (IS_ZEBRA_DEBUG_PACKET) { + if (IS_ZEBRA_DEBUG_SEND && IS_ZEBRA_DEBUG_RECV) { + vty_out(vty, " Zebra packet%s debugging is on\n", + IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + } else { + if (IS_ZEBRA_DEBUG_SEND) + vty_out(vty, + " Zebra packet send%s debugging is on\n", + IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + else + vty_out(vty, + " Zebra packet receive%s debugging is on\n", + IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + } } - else - { - if (IS_ZEBRA_DEBUG_SEND) - vty_out (vty, " Zebra packet send%s debugging is on\n", - IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); - else - vty_out (vty, " Zebra packet receive%s debugging is on\n", - IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); - } - } - - if (IS_ZEBRA_DEBUG_KERNEL) - vty_out (vty, " Zebra kernel debugging is on\n"); - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) - vty_out (vty, " Zebra kernel netlink message dumps (send) are on\n"); - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) - vty_out (vty, " Zebra kernel netlink message dumps (recv) are on\n"); - - /* Check here using flags as the 'macro' does an OR */ - if (CHECK_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB)) - vty_out (vty, " Zebra RIB debugging is on\n"); - if (CHECK_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED)) - vty_out (vty, " Zebra RIB detailed debugging is on\n"); - - if (IS_ZEBRA_DEBUG_FPM) - vty_out (vty, " Zebra FPM debugging is on\n"); - if (IS_ZEBRA_DEBUG_NHT) - vty_out (vty, " Zebra next-hop tracking debugging is on\n"); - if (IS_ZEBRA_DEBUG_MPLS) - vty_out (vty, " Zebra MPLS debugging is on\n"); - - return CMD_SUCCESS; + + if (IS_ZEBRA_DEBUG_KERNEL) + vty_out(vty, " Zebra kernel debugging is on\n"); + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) + vty_out(vty, + " Zebra kernel netlink message dumps (send) are on\n"); + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) + vty_out(vty, + " Zebra kernel netlink message dumps (recv) are on\n"); + + /* Check here using flags as the 'macro' does an OR */ + if (CHECK_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB)) + vty_out(vty, " Zebra RIB debugging is on\n"); + if (CHECK_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED)) + vty_out(vty, " Zebra RIB detailed debugging is on\n"); + + if (IS_ZEBRA_DEBUG_FPM) + vty_out(vty, " Zebra FPM debugging is on\n"); + if (IS_ZEBRA_DEBUG_NHT) + vty_out(vty, " Zebra next-hop tracking debugging is on\n"); + if (IS_ZEBRA_DEBUG_MPLS) + vty_out(vty, " Zebra MPLS debugging is on\n"); + + return CMD_SUCCESS; } DEFUN (debug_zebra_events, @@ -93,8 +93,8 @@ DEFUN (debug_zebra_events, "Zebra configuration\n" "Debug option set for zebra events\n") { - zebra_debug_event = ZEBRA_DEBUG_EVENT; - return CMD_WARNING_CONFIG_FAILED; + zebra_debug_event = ZEBRA_DEBUG_EVENT; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (debug_zebra_nht, @@ -104,8 +104,8 @@ DEFUN (debug_zebra_nht, "Zebra configuration\n" "Debug option set for zebra next hop tracking\n") { - zebra_debug_nht = ZEBRA_DEBUG_NHT; - return CMD_WARNING_CONFIG_FAILED; + zebra_debug_nht = ZEBRA_DEBUG_NHT; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (debug_zebra_mpls, @@ -115,8 +115,8 @@ DEFUN (debug_zebra_mpls, "Zebra configuration\n" "Debug option set for zebra MPLS LSPs\n") { - zebra_debug_mpls = ZEBRA_DEBUG_MPLS; - return CMD_WARNING_CONFIG_FAILED; + zebra_debug_mpls = ZEBRA_DEBUG_MPLS; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (debug_zebra_vxlan, @@ -126,8 +126,8 @@ DEFUN (debug_zebra_vxlan, "Zebra configuration\n" "Debug option set for zebra VxLAN (EVPN)\n") { - zebra_debug_vxlan = ZEBRA_DEBUG_VXLAN; - return CMD_WARNING; + zebra_debug_vxlan = ZEBRA_DEBUG_VXLAN; + return CMD_WARNING; } DEFUN (debug_zebra_packet, @@ -140,24 +140,23 @@ DEFUN (debug_zebra_packet, "Debug option set for send packet\n" "Debug option set for detailed info\n") { - int idx = 0; - zebra_debug_packet = ZEBRA_DEBUG_PACKET; - - if (argv_find (argv, argc, "send", &idx)) - SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); - idx = 0; - if (argv_find (argv, argc, "recv", &idx)) - SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); - idx = 0; - if (argv_find (argv, argc, "detail", &idx)) - SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_DETAIL); - - if (!(zebra_debug_packet & ZEBRA_DEBUG_SEND & ZEBRA_DEBUG_RECV)) - { - SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); - SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); - } - return CMD_SUCCESS; + int idx = 0; + zebra_debug_packet = ZEBRA_DEBUG_PACKET; + + if (argv_find(argv, argc, "send", &idx)) + SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); + idx = 0; + if (argv_find(argv, argc, "recv", &idx)) + SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); + idx = 0; + if (argv_find(argv, argc, "detail", &idx)) + SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_DETAIL); + + if (!(zebra_debug_packet & ZEBRA_DEBUG_SEND & ZEBRA_DEBUG_RECV)) { + SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); + SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); + } + return CMD_SUCCESS; } DEFUN (debug_zebra_kernel, @@ -167,8 +166,8 @@ DEFUN (debug_zebra_kernel, "Zebra configuration\n" "Debug option set for zebra between kernel interface\n") { - SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL); - return CMD_SUCCESS; + SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL); + return CMD_SUCCESS; } DEFUN (debug_zebra_kernel_msgdump, @@ -181,13 +180,13 @@ DEFUN (debug_zebra_kernel_msgdump, "Dump raw netlink messages received\n" "Dump raw netlink messages sent\n") { - int idx = 0; - if (argc == 4 || argv_find (argv, argc, "recv", &idx)) - SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); - if (argc == 4 || argv_find (argv, argc, "send", &idx)) - SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); + int idx = 0; + if (argc == 4 || argv_find(argv, argc, "recv", &idx)) + SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); + if (argc == 4 || argv_find(argv, argc, "send", &idx)) + SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_zebra_rib, @@ -197,8 +196,8 @@ DEFUN (debug_zebra_rib, "Zebra configuration\n" "Debug RIB events\n") { - SET_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB); - return CMD_SUCCESS; + SET_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB); + return CMD_SUCCESS; } DEFUN (debug_zebra_rib_detailed, @@ -209,8 +208,8 @@ DEFUN (debug_zebra_rib_detailed, "Debug RIB events\n" "Detailed debugs\n") { - SET_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED); - return CMD_SUCCESS; + SET_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED); + return CMD_SUCCESS; } DEFUN (debug_zebra_fpm, @@ -220,8 +219,8 @@ DEFUN (debug_zebra_fpm, "Zebra configuration\n" "Debug zebra FPM events\n") { - SET_FLAG (zebra_debug_fpm, ZEBRA_DEBUG_FPM); - return CMD_SUCCESS; + SET_FLAG(zebra_debug_fpm, ZEBRA_DEBUG_FPM); + return CMD_SUCCESS; } DEFUN (no_debug_zebra_events, @@ -232,8 +231,8 @@ DEFUN (no_debug_zebra_events, "Zebra configuration\n" "Debug option set for zebra events\n") { - zebra_debug_event = 0; - return CMD_SUCCESS; + zebra_debug_event = 0; + return CMD_SUCCESS; } DEFUN (no_debug_zebra_nht, @@ -244,8 +243,8 @@ DEFUN (no_debug_zebra_nht, "Zebra configuration\n" "Debug option set for zebra next hop tracking\n") { - zebra_debug_nht = 0; - return CMD_SUCCESS; + zebra_debug_nht = 0; + return CMD_SUCCESS; } DEFUN (no_debug_zebra_mpls, @@ -256,8 +255,8 @@ DEFUN (no_debug_zebra_mpls, "Zebra configuration\n" "Debug option set for zebra MPLS LSPs\n") { - zebra_debug_mpls = 0; - return CMD_SUCCESS; + zebra_debug_mpls = 0; + return CMD_SUCCESS; } DEFUN (no_debug_zebra_vxlan, @@ -268,8 +267,8 @@ DEFUN (no_debug_zebra_vxlan, "Zebra configuration\n" "Debug option set for zebra VxLAN (EVPN)\n") { - zebra_debug_vxlan = 0; - return CMD_SUCCESS; + zebra_debug_vxlan = 0; + return CMD_SUCCESS; } DEFUN (no_debug_zebra_packet, @@ -282,12 +281,12 @@ DEFUN (no_debug_zebra_packet, "Debug option set for receive packet\n" "Debug option set for send packet\n") { - int idx = 0; - if (argc == 4 || argv_find (argv, argc, "send", &idx)) - UNSET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); - if (argc == 4 || argv_find (argv, argc, "recv", &idx)) - UNSET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); - return CMD_SUCCESS; + int idx = 0; + if (argc == 4 || argv_find(argv, argc, "send", &idx)) + UNSET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); + if (argc == 4 || argv_find(argv, argc, "recv", &idx)) + UNSET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); + return CMD_SUCCESS; } DEFUN (no_debug_zebra_kernel, @@ -298,8 +297,8 @@ DEFUN (no_debug_zebra_kernel, "Zebra configuration\n" "Debug option set for zebra between kernel interface\n") { - UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL); - return CMD_SUCCESS; + UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL); + return CMD_SUCCESS; } DEFUN (no_debug_zebra_kernel_msgdump, @@ -313,13 +312,13 @@ DEFUN (no_debug_zebra_kernel_msgdump, "Dump raw netlink messages received\n" "Dump raw netlink messages sent\n") { - int idx = 0; - if (argc == 5 || argv_find (argv, argc, "recv", &idx)) - UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); - if (argc == 5 || argv_find (argv, argc, "send", &idx)) - UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); + int idx = 0; + if (argc == 5 || argv_find(argv, argc, "recv", &idx)) + UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); + if (argc == 5 || argv_find(argv, argc, "send", &idx)) + UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_zebra_rib, @@ -330,8 +329,8 @@ DEFUN (no_debug_zebra_rib, "Zebra configuration\n" "Debug zebra RIB\n") { - zebra_debug_rib = 0; - return CMD_SUCCESS; + zebra_debug_rib = 0; + return CMD_SUCCESS; } DEFUN (no_debug_zebra_rib_detailed, @@ -343,8 +342,8 @@ DEFUN (no_debug_zebra_rib_detailed, "Debug zebra RIB\n" "Detailed debugs\n") { - UNSET_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED); - return CMD_SUCCESS; + UNSET_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED); + return CMD_SUCCESS; } DEFUN (no_debug_zebra_fpm, @@ -355,150 +354,130 @@ DEFUN (no_debug_zebra_fpm, "Zebra configuration\n" "Debug zebra FPM events\n") { - zebra_debug_fpm = 0; - return CMD_SUCCESS; + zebra_debug_fpm = 0; + return CMD_SUCCESS; } /* Debug node. */ -struct cmd_node debug_node = -{ - DEBUG_NODE, - "", /* Debug node has no interface. */ - 1 -}; +struct cmd_node debug_node = {DEBUG_NODE, "", /* Debug node has no interface. */ + 1}; -static int -config_write_debug (struct vty *vty) +static int config_write_debug(struct vty *vty) { - int write = 0; - - if (IS_ZEBRA_DEBUG_EVENT) - { - vty_out (vty, "debug zebra events\n"); - write++; - } - if (IS_ZEBRA_DEBUG_PACKET) - { - if (IS_ZEBRA_DEBUG_SEND && IS_ZEBRA_DEBUG_RECV) - { - vty_out (vty, "debug zebra packet%s\n", - IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); - write++; + int write = 0; + + if (IS_ZEBRA_DEBUG_EVENT) { + vty_out(vty, "debug zebra events\n"); + write++; + } + if (IS_ZEBRA_DEBUG_PACKET) { + if (IS_ZEBRA_DEBUG_SEND && IS_ZEBRA_DEBUG_RECV) { + vty_out(vty, "debug zebra packet%s\n", + IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + write++; + } else { + if (IS_ZEBRA_DEBUG_SEND) + vty_out(vty, "debug zebra packet send%s\n", + IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + else + vty_out(vty, "debug zebra packet recv%s\n", + IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + write++; + } + } + if (IS_ZEBRA_DEBUG_KERNEL) { + vty_out(vty, "debug zebra kernel\n"); + write++; + } + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) { + vty_out(vty, "debug zebra kernel msgdump recv\n"); + write++; + } + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) { + vty_out(vty, "debug zebra kernel msgdump send\n"); + write++; + } + /* Check here using flags as the 'macro' does an OR */ + if (CHECK_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB)) { + vty_out(vty, "debug zebra rib\n"); + write++; + } + if (CHECK_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED)) { + vty_out(vty, "debug zebra rib detailed\n"); + write++; + } + if (IS_ZEBRA_DEBUG_FPM) { + vty_out(vty, "debug zebra fpm\n"); + write++; + } + if (IS_ZEBRA_DEBUG_NHT) { + vty_out(vty, "debug zebra nht\n"); + write++; + } + if (IS_ZEBRA_DEBUG_MPLS) { + vty_out(vty, "debug zebra mpls\n"); + write++; } - else - { - if (IS_ZEBRA_DEBUG_SEND) - vty_out (vty, "debug zebra packet send%s\n", - IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); - else - vty_out (vty, "debug zebra packet recv%s\n", - IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); - write++; + if (IS_ZEBRA_DEBUG_VXLAN) { + vty_out(vty, "debug zebra vxlan\n"); + write++; } - } - if (IS_ZEBRA_DEBUG_KERNEL) - { - vty_out (vty, "debug zebra kernel\n"); - write++; - } - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) - { - vty_out (vty, "debug zebra kernel msgdump recv\n"); - write++; - } - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) - { - vty_out (vty, "debug zebra kernel msgdump send\n"); - write++; - } - /* Check here using flags as the 'macro' does an OR */ - if (CHECK_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB)) - { - vty_out (vty, "debug zebra rib\n"); - write++; - } - if (CHECK_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED)) - { - vty_out (vty, "debug zebra rib detailed\n"); - write++; - } - if (IS_ZEBRA_DEBUG_FPM) - { - vty_out (vty, "debug zebra fpm\n"); - write++; - } - if (IS_ZEBRA_DEBUG_NHT) - { - vty_out (vty, "debug zebra nht\n"); - write++; - } - if (IS_ZEBRA_DEBUG_MPLS) - { - vty_out (vty, "debug zebra mpls\n"); - write++; - } - if (IS_ZEBRA_DEBUG_VXLAN) - { - vty_out (vty, "debug zebra vxlan\n"); - write++; - } - return write; + return write; } -void -zebra_debug_init (void) +void zebra_debug_init(void) { - zebra_debug_event = 0; - zebra_debug_packet = 0; - zebra_debug_kernel = 0; - zebra_debug_rib = 0; - zebra_debug_fpm = 0; - zebra_debug_mpls = 0; - zebra_debug_vxlan = 0; - - install_node (&debug_node, config_write_debug); - - install_element (VIEW_NODE, &show_debugging_zebra_cmd); - - install_element (ENABLE_NODE, &debug_zebra_events_cmd); - install_element (ENABLE_NODE, &debug_zebra_nht_cmd); - install_element (ENABLE_NODE, &debug_zebra_mpls_cmd); - install_element (ENABLE_NODE, &debug_zebra_vxlan_cmd); - install_element (ENABLE_NODE, &debug_zebra_packet_cmd); - install_element (ENABLE_NODE, &debug_zebra_kernel_cmd); - install_element (ENABLE_NODE, &debug_zebra_kernel_msgdump_cmd); - install_element (ENABLE_NODE, &debug_zebra_rib_cmd); - install_element (ENABLE_NODE, &debug_zebra_rib_detailed_cmd); - install_element (ENABLE_NODE, &debug_zebra_fpm_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_events_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_nht_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_mpls_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_vxlan_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_packet_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_kernel_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_kernel_msgdump_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_rib_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_rib_detailed_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_fpm_cmd); - - install_element (CONFIG_NODE, &debug_zebra_events_cmd); - install_element (CONFIG_NODE, &debug_zebra_nht_cmd); - install_element (CONFIG_NODE, &debug_zebra_mpls_cmd); - install_element (CONFIG_NODE, &debug_zebra_vxlan_cmd); - install_element (CONFIG_NODE, &debug_zebra_packet_cmd); - install_element (CONFIG_NODE, &debug_zebra_kernel_cmd); - install_element (CONFIG_NODE, &debug_zebra_kernel_msgdump_cmd); - install_element (CONFIG_NODE, &debug_zebra_rib_cmd); - install_element (CONFIG_NODE, &debug_zebra_rib_detailed_cmd); - install_element (CONFIG_NODE, &debug_zebra_fpm_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_events_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_nht_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_mpls_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_vxlan_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_packet_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_kernel_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_kernel_msgdump_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_rib_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_rib_detailed_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_fpm_cmd); + zebra_debug_event = 0; + zebra_debug_packet = 0; + zebra_debug_kernel = 0; + zebra_debug_rib = 0; + zebra_debug_fpm = 0; + zebra_debug_mpls = 0; + zebra_debug_vxlan = 0; + + install_node(&debug_node, config_write_debug); + + install_element(VIEW_NODE, &show_debugging_zebra_cmd); + + install_element(ENABLE_NODE, &debug_zebra_events_cmd); + install_element(ENABLE_NODE, &debug_zebra_nht_cmd); + install_element(ENABLE_NODE, &debug_zebra_mpls_cmd); + install_element(ENABLE_NODE, &debug_zebra_vxlan_cmd); + install_element(ENABLE_NODE, &debug_zebra_packet_cmd); + install_element(ENABLE_NODE, &debug_zebra_kernel_cmd); + install_element(ENABLE_NODE, &debug_zebra_kernel_msgdump_cmd); + install_element(ENABLE_NODE, &debug_zebra_rib_cmd); + install_element(ENABLE_NODE, &debug_zebra_rib_detailed_cmd); + install_element(ENABLE_NODE, &debug_zebra_fpm_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_events_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_nht_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_mpls_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_vxlan_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_packet_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_kernel_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_kernel_msgdump_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_rib_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_rib_detailed_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_fpm_cmd); + + install_element(CONFIG_NODE, &debug_zebra_events_cmd); + install_element(CONFIG_NODE, &debug_zebra_nht_cmd); + install_element(CONFIG_NODE, &debug_zebra_mpls_cmd); + install_element(CONFIG_NODE, &debug_zebra_vxlan_cmd); + install_element(CONFIG_NODE, &debug_zebra_packet_cmd); + install_element(CONFIG_NODE, &debug_zebra_kernel_cmd); + install_element(CONFIG_NODE, &debug_zebra_kernel_msgdump_cmd); + install_element(CONFIG_NODE, &debug_zebra_rib_cmd); + install_element(CONFIG_NODE, &debug_zebra_rib_detailed_cmd); + install_element(CONFIG_NODE, &debug_zebra_fpm_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_events_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_nht_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_mpls_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_vxlan_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_packet_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_kernel_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_kernel_msgdump_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_rib_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_rib_detailed_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_fpm_cmd); } diff --git a/zebra/debug.h b/zebra/debug.h index 5687a3516..b52bb7d0e 100644 --- a/zebra/debug.h +++ b/zebra/debug.h @@ -53,13 +53,13 @@ #define IS_ZEBRA_DEBUG_DETAIL (zebra_debug_packet & ZEBRA_DEBUG_DETAIL) #define IS_ZEBRA_DEBUG_KERNEL (zebra_debug_kernel & ZEBRA_DEBUG_KERNEL) -#define IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND \ - (zebra_debug_kernel & ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) -#define IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV \ - (zebra_debug_kernel & ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) +#define IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND \ + (zebra_debug_kernel & ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) +#define IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV \ + (zebra_debug_kernel & ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) -#define IS_ZEBRA_DEBUG_RIB \ - (zebra_debug_rib & (ZEBRA_DEBUG_RIB | ZEBRA_DEBUG_RIB_DETAILED)) +#define IS_ZEBRA_DEBUG_RIB \ + (zebra_debug_rib & (ZEBRA_DEBUG_RIB | ZEBRA_DEBUG_RIB_DETAILED)) #define IS_ZEBRA_DEBUG_RIB_DETAILED (zebra_debug_rib & ZEBRA_DEBUG_RIB_DETAILED) #define IS_ZEBRA_DEBUG_FPM (zebra_debug_fpm & ZEBRA_DEBUG_FPM) @@ -76,6 +76,6 @@ extern unsigned long zebra_debug_nht; extern unsigned long zebra_debug_mpls; extern unsigned long zebra_debug_vxlan; -extern void zebra_debug_init (void); +extern void zebra_debug_init(void); #endif /* _ZEBRA_DEBUG_H */ diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index 73da04965..2d5d604a8 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -38,306 +38,293 @@ #include <ifaddrs.h> /* Interface looking up using infamous SIOCGIFCONF. */ -static int -interface_list_ioctl (void) +static int interface_list_ioctl(void) { - int ret; - int sock; + int ret; + int sock; #define IFNUM_BASE 32 - int ifnum; - struct ifreq *ifreq; - struct ifconf ifconf; - struct interface *ifp; - int n; - int lastlen; - - /* Normally SIOCGIFCONF works with AF_INET socket. */ - sock = socket (AF_INET, SOCK_DGRAM, 0); - if (sock < 0) - { - zlog_warn ("Can't make AF_INET socket stream: %s", safe_strerror (errno)); - return -1; - } - - /* Set initial ifreq count. This will be double when SIOCGIFCONF - fail. Solaris has SIOCGIFNUM. */ + int ifnum; + struct ifreq *ifreq; + struct ifconf ifconf; + struct interface *ifp; + int n; + int lastlen; + + /* Normally SIOCGIFCONF works with AF_INET socket. */ + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + zlog_warn("Can't make AF_INET socket stream: %s", + safe_strerror(errno)); + return -1; + } + +/* Set initial ifreq count. This will be double when SIOCGIFCONF + fail. Solaris has SIOCGIFNUM. */ #ifdef SIOCGIFNUM - ret = ioctl (sock, SIOCGIFNUM, &ifnum); - if (ret < 0) - ifnum = IFNUM_BASE; - else - ifnum++; + ret = ioctl(sock, SIOCGIFNUM, &ifnum); + if (ret < 0) + ifnum = IFNUM_BASE; + else + ifnum++; #else - ifnum = IFNUM_BASE; + ifnum = IFNUM_BASE; #endif /* SIOCGIFNUM */ - ifconf.ifc_buf = NULL; - - lastlen = 0; - /* Loop until SIOCGIFCONF success. */ - for (;;) - { - ifconf.ifc_len = sizeof (struct ifreq) * ifnum; - ifconf.ifc_buf = XREALLOC(MTYPE_TMP, ifconf.ifc_buf, ifconf.ifc_len); - - ret = ioctl(sock, SIOCGIFCONF, &ifconf); - - if (ret < 0) - { - zlog_warn ("SIOCGIFCONF: %s", safe_strerror(errno)); - goto end; - } - /* Repeatedly get info til buffer fails to grow. */ - if (ifconf.ifc_len > lastlen) - { - lastlen = ifconf.ifc_len; - ifnum += 10; - continue; + ifconf.ifc_buf = NULL; + + lastlen = 0; + /* Loop until SIOCGIFCONF success. */ + for (;;) { + ifconf.ifc_len = sizeof(struct ifreq) * ifnum; + ifconf.ifc_buf = + XREALLOC(MTYPE_TMP, ifconf.ifc_buf, ifconf.ifc_len); + + ret = ioctl(sock, SIOCGIFCONF, &ifconf); + + if (ret < 0) { + zlog_warn("SIOCGIFCONF: %s", safe_strerror(errno)); + goto end; + } + /* Repeatedly get info til buffer fails to grow. */ + if (ifconf.ifc_len > lastlen) { + lastlen = ifconf.ifc_len; + ifnum += 10; + continue; + } + /* Success. */ + break; } - /* Success. */ - break; - } - /* Allocate interface. */ - ifreq = ifconf.ifc_req; + /* Allocate interface. */ + ifreq = ifconf.ifc_req; #ifdef OPEN_BSD - for (n = 0; n < ifconf.ifc_len; ) - { - unsigned int size; - - ifreq = (struct ifreq *)((caddr_t) ifconf.ifc_req + n); - ifp = if_get_by_name_len(ifreq->ifr_name, - strnlen(ifreq->ifr_name, - sizeof(ifreq->ifr_name)), - VRF_DEFAULT, 0); - if_add_update (ifp); - size = ifreq->ifr_addr.sa_len; - if (size < sizeof (ifreq->ifr_addr)) - size = sizeof (ifreq->ifr_addr); - size += sizeof (ifreq->ifr_name); - n += size; - } + for (n = 0; n < ifconf.ifc_len;) { + unsigned int size; + + ifreq = (struct ifreq *)((caddr_t)ifconf.ifc_req + n); + ifp = if_get_by_name_len( + ifreq->ifr_name, + strnlen(ifreq->ifr_name, sizeof(ifreq->ifr_name)), + VRF_DEFAULT, 0); + if_add_update(ifp); + size = ifreq->ifr_addr.sa_len; + if (size < sizeof(ifreq->ifr_addr)) + size = sizeof(ifreq->ifr_addr); + size += sizeof(ifreq->ifr_name); + n += size; + } #else - for (n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq)) - { - ifp = if_get_by_name_len(ifreq->ifr_name, - strnlen(ifreq->ifr_name, - sizeof(ifreq->ifr_name)), - VRF_DEFAULT, 0); - if_add_update (ifp); - ifreq++; - } + for (n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq)) { + ifp = if_get_by_name_len( + ifreq->ifr_name, + strnlen(ifreq->ifr_name, sizeof(ifreq->ifr_name)), + VRF_DEFAULT, 0); + if_add_update(ifp); + ifreq++; + } #endif /* OPEN_BSD */ - end: - close (sock); - XFREE (MTYPE_TMP, ifconf.ifc_buf); +end: + close(sock); + XFREE(MTYPE_TMP, ifconf.ifc_buf); - return ret; + return ret; } /* Get interface's index by ioctl. */ -static int -if_get_index (struct interface *ifp) +static int if_get_index(struct interface *ifp) { - ifp->ifindex = if_nametoindex(ifp->name); - return ifp->ifindex; + ifp->ifindex = if_nametoindex(ifp->name); + return ifp->ifindex; } #ifdef SIOCGIFHWADDR -static int -if_get_hwaddr (struct interface *ifp) +static int if_get_hwaddr(struct interface *ifp) { - int ret; - struct ifreq ifreq; - int i; - - strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ); - ifreq.ifr_addr.sa_family = AF_INET; - - /* Fetch Hardware address if available. */ - ret = if_ioctl (SIOCGIFHWADDR, (caddr_t) &ifreq); - if (ret < 0) - ifp->hw_addr_len = 0; - else - { - memcpy (ifp->hw_addr, ifreq.ifr_hwaddr.sa_data, 6); - - for (i = 0; i < 6; i++) - if (ifp->hw_addr[i] != 0) - break; - - if (i == 6) - ifp->hw_addr_len = 0; - else - ifp->hw_addr_len = 6; - } - return 0; + int ret; + struct ifreq ifreq; + int i; + + strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ); + ifreq.ifr_addr.sa_family = AF_INET; + + /* Fetch Hardware address if available. */ + ret = if_ioctl(SIOCGIFHWADDR, (caddr_t)&ifreq); + if (ret < 0) + ifp->hw_addr_len = 0; + else { + memcpy(ifp->hw_addr, ifreq.ifr_hwaddr.sa_data, 6); + + for (i = 0; i < 6; i++) + if (ifp->hw_addr[i] != 0) + break; + + if (i == 6) + ifp->hw_addr_len = 0; + else + ifp->hw_addr_len = 6; + } + return 0; } #endif /* SIOCGIFHWADDR */ -static int -if_getaddrs (void) +static int if_getaddrs(void) { - int ret; - struct ifaddrs *ifap; - struct ifaddrs *ifapfree; - struct interface *ifp; - int prefixlen; - - ret = getifaddrs (&ifap); - if (ret != 0) - { - zlog_err ("getifaddrs(): %s", safe_strerror (errno)); - return -1; - } - - for (ifapfree = ifap; ifap; ifap = ifap->ifa_next) - { - if (ifap->ifa_addr == NULL) - { - zlog_err ("%s: nonsensical ifaddr with NULL ifa_addr, ifname %s", - __func__, (ifap->ifa_name ? ifap->ifa_name : "(null)")); - continue; - } - - ifp = if_lookup_by_name (ifap->ifa_name, VRF_DEFAULT); - if (ifp == NULL) - { - zlog_err ("if_getaddrs(): Can't lookup interface %s\n", - ifap->ifa_name); - continue; + int ret; + struct ifaddrs *ifap; + struct ifaddrs *ifapfree; + struct interface *ifp; + int prefixlen; + + ret = getifaddrs(&ifap); + if (ret != 0) { + zlog_err("getifaddrs(): %s", safe_strerror(errno)); + return -1; } - if (ifap->ifa_addr->sa_family == AF_INET) - { - struct sockaddr_in *addr; - struct sockaddr_in *mask; - struct sockaddr_in *dest; - struct in_addr *dest_pnt; - int flags = 0; - - addr = (struct sockaddr_in *) ifap->ifa_addr; - mask = (struct sockaddr_in *) ifap->ifa_netmask; - prefixlen = ip_masklen (mask->sin_addr); - - dest_pnt = NULL; - - if (ifap->ifa_dstaddr && - !IPV4_ADDR_SAME(&addr->sin_addr, - &((struct sockaddr_in *) - ifap->ifa_dstaddr)->sin_addr)) - { - dest = (struct sockaddr_in *) ifap->ifa_dstaddr; - dest_pnt = &dest->sin_addr; - flags = ZEBRA_IFA_PEER; - } - else if (ifap->ifa_broadaddr && - !IPV4_ADDR_SAME(&addr->sin_addr, - &((struct sockaddr_in *) - ifap->ifa_broadaddr)->sin_addr)) - { - dest = (struct sockaddr_in *) ifap->ifa_broadaddr; - dest_pnt = &dest->sin_addr; - } - - connected_add_ipv4 (ifp, flags, &addr->sin_addr, - prefixlen, dest_pnt, NULL); - } - if (ifap->ifa_addr->sa_family == AF_INET6) - { - struct sockaddr_in6 *addr; - struct sockaddr_in6 *mask; - struct sockaddr_in6 *dest; - struct in6_addr *dest_pnt; - int flags = 0; - - addr = (struct sockaddr_in6 *) ifap->ifa_addr; - mask = (struct sockaddr_in6 *) ifap->ifa_netmask; - prefixlen = ip6_masklen (mask->sin6_addr); - - dest_pnt = NULL; - - if (ifap->ifa_dstaddr && - !IPV6_ADDR_SAME(&addr->sin6_addr, - &((struct sockaddr_in6 *) - ifap->ifa_dstaddr)->sin6_addr)) - { - dest = (struct sockaddr_in6 *) ifap->ifa_dstaddr; - dest_pnt = &dest->sin6_addr; - flags = ZEBRA_IFA_PEER; - } - else if (ifap->ifa_broadaddr && - !IPV6_ADDR_SAME(&addr->sin6_addr, - &((struct sockaddr_in6 *) - ifap->ifa_broadaddr)->sin6_addr)) - { - dest = (struct sockaddr_in6 *) ifap->ifa_broadaddr; - dest_pnt = &dest->sin6_addr; - } + for (ifapfree = ifap; ifap; ifap = ifap->ifa_next) { + if (ifap->ifa_addr == NULL) { + zlog_err( + "%s: nonsensical ifaddr with NULL ifa_addr, ifname %s", + __func__, + (ifap->ifa_name ? ifap->ifa_name : "(null)")); + continue; + } + + ifp = if_lookup_by_name(ifap->ifa_name, VRF_DEFAULT); + if (ifp == NULL) { + zlog_err("if_getaddrs(): Can't lookup interface %s\n", + ifap->ifa_name); + continue; + } + + if (ifap->ifa_addr->sa_family == AF_INET) { + struct sockaddr_in *addr; + struct sockaddr_in *mask; + struct sockaddr_in *dest; + struct in_addr *dest_pnt; + int flags = 0; + + addr = (struct sockaddr_in *)ifap->ifa_addr; + mask = (struct sockaddr_in *)ifap->ifa_netmask; + prefixlen = ip_masklen(mask->sin_addr); + + dest_pnt = NULL; + + if (ifap->ifa_dstaddr + && !IPV4_ADDR_SAME(&addr->sin_addr, + &((struct sockaddr_in *) + ifap->ifa_dstaddr) + ->sin_addr)) { + dest = (struct sockaddr_in *)ifap->ifa_dstaddr; + dest_pnt = &dest->sin_addr; + flags = ZEBRA_IFA_PEER; + } else if (ifap->ifa_broadaddr + && !IPV4_ADDR_SAME( + &addr->sin_addr, + &((struct sockaddr_in *) + ifap->ifa_broadaddr) + ->sin_addr)) { + dest = (struct sockaddr_in *) + ifap->ifa_broadaddr; + dest_pnt = &dest->sin_addr; + } + + connected_add_ipv4(ifp, flags, &addr->sin_addr, + prefixlen, dest_pnt, NULL); + } + if (ifap->ifa_addr->sa_family == AF_INET6) { + struct sockaddr_in6 *addr; + struct sockaddr_in6 *mask; + struct sockaddr_in6 *dest; + struct in6_addr *dest_pnt; + int flags = 0; + + addr = (struct sockaddr_in6 *)ifap->ifa_addr; + mask = (struct sockaddr_in6 *)ifap->ifa_netmask; + prefixlen = ip6_masklen(mask->sin6_addr); + + dest_pnt = NULL; + + if (ifap->ifa_dstaddr + && !IPV6_ADDR_SAME(&addr->sin6_addr, + &((struct sockaddr_in6 *) + ifap->ifa_dstaddr) + ->sin6_addr)) { + dest = (struct sockaddr_in6 *)ifap->ifa_dstaddr; + dest_pnt = &dest->sin6_addr; + flags = ZEBRA_IFA_PEER; + } else if (ifap->ifa_broadaddr + && !IPV6_ADDR_SAME( + &addr->sin6_addr, + &((struct sockaddr_in6 *) + ifap->ifa_broadaddr) + ->sin6_addr)) { + dest = (struct sockaddr_in6 *) + ifap->ifa_broadaddr; + dest_pnt = &dest->sin6_addr; + } #if defined(KAME) - if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) - { - addr->sin6_scope_id = - ntohs(*(u_int16_t *)&addr->sin6_addr.s6_addr[2]); - addr->sin6_addr.s6_addr[2] = addr->sin6_addr.s6_addr[3] = 0; - } -#endif - - connected_add_ipv6 (ifp, flags, &addr->sin6_addr, prefixlen, - dest_pnt, NULL); + if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { + addr->sin6_scope_id = + ntohs(*(u_int16_t *)&addr->sin6_addr + .s6_addr[2]); + addr->sin6_addr.s6_addr[2] = + addr->sin6_addr.s6_addr[3] = 0; + } +#endif + + connected_add_ipv6(ifp, flags, &addr->sin6_addr, + prefixlen, dest_pnt, NULL); + } } - } - freeifaddrs (ifapfree); + freeifaddrs(ifapfree); - return 0; + return 0; } /* Fetch interface information via ioctl(). */ -static void -interface_info_ioctl () +static void interface_info_ioctl() { - struct listnode *node, *nnode; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - { - if_get_index (ifp); + struct listnode *node, *nnode; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) { + if_get_index(ifp); #ifdef SIOCGIFHWADDR - if_get_hwaddr (ifp); + if_get_hwaddr(ifp); #endif /* SIOCGIFHWADDR */ - if_get_flags (ifp); - if_get_mtu (ifp); - if_get_metric (ifp); - } + if_get_flags(ifp); + if_get_mtu(ifp); + if_get_metric(ifp); + } } /* Lookup all interface information. */ -void -interface_list (struct zebra_ns *zns) +void interface_list(struct zebra_ns *zns) { - zlog_info ("interface_list: NS %u", zns->ns_id); + zlog_info("interface_list: NS %u", zns->ns_id); - /* Linux can do both proc & ioctl, ioctl is the only way to get - interface aliases in 2.2 series kernels. */ +/* Linux can do both proc & ioctl, ioctl is the only way to get + interface aliases in 2.2 series kernels. */ #ifdef HAVE_PROC_NET_DEV - interface_list_proc (); + interface_list_proc(); #endif /* HAVE_PROC_NET_DEV */ - interface_list_ioctl (); + interface_list_ioctl(); - /* After listing is done, get index, address, flags and other - interface's information. */ - interface_info_ioctl (); + /* After listing is done, get index, address, flags and other + interface's information. */ + interface_info_ioctl(); - if_getaddrs (); + if_getaddrs(); #if defined(HAVE_PROC_NET_IF_INET6) - /* Linux provides interface's IPv6 address via - /proc/net/if_inet6. */ - ifaddr_proc_ipv6 (); + /* Linux provides interface's IPv6 address via + /proc/net/if_inet6. */ + ifaddr_proc_ipv6(); #endif /* HAVE_PROC_NET_IF_INET6 */ } diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c index 08af2aa35..fce36ebc1 100644 --- a/zebra/if_ioctl_solaris.c +++ b/zebra/if_ioctl_solaris.c @@ -37,338 +37,324 @@ #include "zebra/ioctl_solaris.h" #include "zebra/rib.h" -static int if_get_addr (struct interface *, struct sockaddr *, const char *); -static void interface_info_ioctl (struct interface *); +static int if_get_addr(struct interface *, struct sockaddr *, const char *); +static void interface_info_ioctl(struct interface *); extern struct zebra_privs_t zserv_privs; -static int -interface_list_ioctl (int af) +static int interface_list_ioctl(int af) { - int ret; - int sock; + int ret; + int sock; #define IFNUM_BASE 32 - struct lifnum lifn; - int ifnum; - struct lifreq *lifreq; - struct lifconf lifconf; - struct interface *ifp; - int n; - int save_errno; - size_t needed, lastneeded = 0; - char *buf = NULL; - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - - sock = socket (af, SOCK_DGRAM, 0); - if (sock < 0) - { - zlog_warn ("Can't make %s socket stream: %s", - (af == AF_INET ? "AF_INET" : "AF_INET6"), safe_strerror (errno)); - - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - return -1; - } - -calculate_lifc_len: /* must hold privileges to enter here */ - lifn.lifn_family = af; - lifn.lifn_flags = LIFC_NOXMIT; /* we want NOXMIT interfaces too */ - ret = ioctl (sock, SIOCGLIFNUM, &lifn); - save_errno = errno; - - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - if (ret < 0) - { - zlog_warn ("interface_list_ioctl: SIOCGLIFNUM failed %s", - safe_strerror (save_errno)); - close (sock); - return -1; - } - ifnum = lifn.lifn_count; - - /* - * When calculating the buffer size needed, add a small number - * of interfaces to those we counted. We do this to capture - * the interface status of potential interfaces which may have - * been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF. - */ - needed = (ifnum + 4) * sizeof (struct lifreq); - if (needed > lastneeded || needed < lastneeded / 2) - { - if (buf != NULL) - XFREE (MTYPE_TMP, buf); - if ((buf = XMALLOC (MTYPE_TMP, needed)) == NULL) - { - zlog_warn ("interface_list_ioctl: malloc failed"); - close (sock); - return -1; - } - } - lastneeded = needed; - - lifconf.lifc_family = af; - lifconf.lifc_flags = LIFC_NOXMIT; - lifconf.lifc_len = needed; - lifconf.lifc_buf = buf; - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - - ret = ioctl (sock, SIOCGLIFCONF, &lifconf); - - if (ret < 0) - { - if (errno == EINVAL) - goto calculate_lifc_len; /* deliberately hold privileges */ - - zlog_warn ("SIOCGLIFCONF: %s", safe_strerror (errno)); - - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - goto end; - } - - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - /* Allocate interface. */ - lifreq = lifconf.lifc_req; - - for (n = 0; n < lifconf.lifc_len; n += sizeof (struct lifreq)) - { - /* we treat Solaris logical interfaces as addresses, because that is - * how PF_ROUTE on Solaris treats them. Hence we can not directly use - * the lifreq_name to get the ifp. We need to normalise the name - * before attempting get. - * - * Solaris logical interface names are in the form of: - * <interface name>:<logical interface id> - */ - unsigned int normallen = 0; - uint64_t lifflags; - - /* We should exclude ~IFF_UP interfaces, as we'll find out about them - * coming up later through RTM_NEWADDR message on the route socket. - */ - if (if_get_flags_direct (lifreq->lifr_name, &lifflags, - lifreq->lifr_addr.ss_family) - || !CHECK_FLAG (lifflags, IFF_UP)) - { - lifreq++; - continue; - } - - /* Find the normalised name */ - while ( (normallen < sizeof(lifreq->lifr_name)) - && ( *(lifreq->lifr_name + normallen) != '\0') - && ( *(lifreq->lifr_name + normallen) != ':') ) - normallen++; - - ifp = if_get_by_name_len(lifreq->lifr_name, normallen, VRF_DEFAULT, 0); - - if (lifreq->lifr_addr.ss_family == AF_INET) - ifp->flags |= IFF_IPV4; - - if (lifreq->lifr_addr.ss_family == AF_INET6) - { - ifp->flags |= IFF_IPV6; - } - - if_add_update (ifp); - - interface_info_ioctl (ifp); - - /* If a logical interface pass the full name so it can be - * as a label on the address - */ - if ( *(lifreq->lifr_name + normallen) != '\0') - if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr, - lifreq->lifr_name); - else - if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr, NULL); - - /* Poke the interface flags. Lets IFF_UP mangling kick in */ - if_flags_update (ifp, ifp->flags); - - lifreq++; - } + struct lifnum lifn; + int ifnum; + struct lifreq *lifreq; + struct lifconf lifconf; + struct interface *ifp; + int n; + int save_errno; + size_t needed, lastneeded = 0; + char *buf = NULL; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + + sock = socket(af, SOCK_DGRAM, 0); + if (sock < 0) { + zlog_warn("Can't make %s socket stream: %s", + (af == AF_INET ? "AF_INET" : "AF_INET6"), + safe_strerror(errno)); + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + return -1; + } + +calculate_lifc_len: /* must hold privileges to enter here */ + lifn.lifn_family = af; + lifn.lifn_flags = LIFC_NOXMIT; /* we want NOXMIT interfaces too */ + ret = ioctl(sock, SIOCGLIFNUM, &lifn); + save_errno = errno; + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + if (ret < 0) { + zlog_warn("interface_list_ioctl: SIOCGLIFNUM failed %s", + safe_strerror(save_errno)); + close(sock); + return -1; + } + ifnum = lifn.lifn_count; + + /* + * When calculating the buffer size needed, add a small number + * of interfaces to those we counted. We do this to capture + * the interface status of potential interfaces which may have + * been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF. + */ + needed = (ifnum + 4) * sizeof(struct lifreq); + if (needed > lastneeded || needed < lastneeded / 2) { + if (buf != NULL) + XFREE(MTYPE_TMP, buf); + if ((buf = XMALLOC(MTYPE_TMP, needed)) == NULL) { + zlog_warn("interface_list_ioctl: malloc failed"); + close(sock); + return -1; + } + } + lastneeded = needed; + + lifconf.lifc_family = af; + lifconf.lifc_flags = LIFC_NOXMIT; + lifconf.lifc_len = needed; + lifconf.lifc_buf = buf; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + + ret = ioctl(sock, SIOCGLIFCONF, &lifconf); + + if (ret < 0) { + if (errno == EINVAL) + goto calculate_lifc_len; /* deliberately hold privileges + */ + + zlog_warn("SIOCGLIFCONF: %s", safe_strerror(errno)); + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + goto end; + } + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + /* Allocate interface. */ + lifreq = lifconf.lifc_req; + + for (n = 0; n < lifconf.lifc_len; n += sizeof(struct lifreq)) { + /* we treat Solaris logical interfaces as addresses, because + * that is + * how PF_ROUTE on Solaris treats them. Hence we can not + * directly use + * the lifreq_name to get the ifp. We need to normalise the + * name + * before attempting get. + * + * Solaris logical interface names are in the form of: + * <interface name>:<logical interface id> + */ + unsigned int normallen = 0; + uint64_t lifflags; + + /* We should exclude ~IFF_UP interfaces, as we'll find out about + * them + * coming up later through RTM_NEWADDR message on the route + * socket. + */ + if (if_get_flags_direct(lifreq->lifr_name, &lifflags, + lifreq->lifr_addr.ss_family) + || !CHECK_FLAG(lifflags, IFF_UP)) { + lifreq++; + continue; + } + + /* Find the normalised name */ + while ((normallen < sizeof(lifreq->lifr_name)) + && (*(lifreq->lifr_name + normallen) != '\0') + && (*(lifreq->lifr_name + normallen) != ':')) + normallen++; + + ifp = if_get_by_name_len(lifreq->lifr_name, normallen, + VRF_DEFAULT, 0); + + if (lifreq->lifr_addr.ss_family == AF_INET) + ifp->flags |= IFF_IPV4; + + if (lifreq->lifr_addr.ss_family == AF_INET6) { + ifp->flags |= IFF_IPV6; + } + + if_add_update(ifp); + + interface_info_ioctl(ifp); + + /* If a logical interface pass the full name so it can be + * as a label on the address + */ + if (*(lifreq->lifr_name + normallen) != '\0') + if_get_addr(ifp, (struct sockaddr *)&lifreq->lifr_addr, + lifreq->lifr_name); + else + if_get_addr(ifp, (struct sockaddr *)&lifreq->lifr_addr, + NULL); + + /* Poke the interface flags. Lets IFF_UP mangling kick in */ + if_flags_update(ifp, ifp->flags); + + lifreq++; + } end: - close (sock); - XFREE (MTYPE_TMP, lifconf.lifc_buf); - return ret; + close(sock); + XFREE(MTYPE_TMP, lifconf.lifc_buf); + return ret; } /* Get interface's index by ioctl. */ -static int -if_get_index (struct interface *ifp) +static int if_get_index(struct interface *ifp) { - int ret; - struct lifreq lifreq; + int ret; + struct lifreq lifreq; - lifreq_set_name (&lifreq, ifp->name); + lifreq_set_name(&lifreq, ifp->name); - if (ifp->flags & IFF_IPV4) - ret = AF_IOCTL (AF_INET, SIOCGLIFINDEX, (caddr_t) & lifreq); - else if (ifp->flags & IFF_IPV6) - ret = AF_IOCTL (AF_INET6, SIOCGLIFINDEX, (caddr_t) & lifreq); - else - ret = -1; + if (ifp->flags & IFF_IPV4) + ret = AF_IOCTL(AF_INET, SIOCGLIFINDEX, (caddr_t)&lifreq); + else if (ifp->flags & IFF_IPV6) + ret = AF_IOCTL(AF_INET6, SIOCGLIFINDEX, (caddr_t)&lifreq); + else + ret = -1; - if (ret < 0) - { - zlog_warn ("SIOCGLIFINDEX(%s) failed", ifp->name); - return ret; - } + if (ret < 0) { + zlog_warn("SIOCGLIFINDEX(%s) failed", ifp->name); + return ret; + } - /* OK we got interface index. */ +/* OK we got interface index. */ #ifdef ifr_ifindex - ifp->ifindex = lifreq.lifr_ifindex; + ifp->ifindex = lifreq.lifr_ifindex; #else - ifp->ifindex = lifreq.lifr_index; + ifp->ifindex = lifreq.lifr_index; #endif - return ifp->ifindex; - + return ifp->ifindex; } /* Interface address lookup by ioctl. This function only looks up IPv4 address. */ -#define ADDRLEN(sa) (((sa)->sa_family == AF_INET ? \ - sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6))) +#define ADDRLEN(sa) \ + (((sa)->sa_family == AF_INET ? sizeof(struct sockaddr_in) \ + : sizeof(struct sockaddr_in6))) #define SIN(s) ((struct sockaddr_in *)(s)) #define SIN6(s) ((struct sockaddr_in6 *)(s)) /* Retrieve address information for the given ifp */ -static int -if_get_addr (struct interface *ifp, struct sockaddr *addr, const char *label) +static int if_get_addr(struct interface *ifp, struct sockaddr *addr, + const char *label) { - int ret; - struct lifreq lifreq; - struct sockaddr_storage mask, dest; - char *dest_pnt = NULL; - u_char prefixlen = 0; - afi_t af; - int flags = 0; - - /* Interface's name and address family. - * We need to use the logical interface name / label, if we've been - * given one, in order to get the right address - */ - strncpy (lifreq.lifr_name, (label ? label : ifp->name), IFNAMSIZ); - - /* Interface's address. */ - memcpy (&lifreq.lifr_addr, addr, ADDRLEN (addr)); - af = addr->sa_family; - - /* Point to point or broad cast address pointer init. */ - dest_pnt = NULL; - - if (AF_IOCTL (af, SIOCGLIFDSTADDR, (caddr_t) & lifreq) >= 0) - { - memcpy (&dest, &lifreq.lifr_dstaddr, ADDRLEN (addr)); - if (af == AF_INET) - dest_pnt = (char *) &(SIN (&dest)->sin_addr); - else - dest_pnt = (char *) &(SIN6 (&dest)->sin6_addr); - flags = ZEBRA_IFA_PEER; - } - - if (af == AF_INET) - { - ret = if_ioctl (SIOCGLIFNETMASK, (caddr_t) & lifreq); - - if (ret < 0) - { - if (errno != EADDRNOTAVAIL) - { - zlog_warn ("SIOCGLIFNETMASK (%s) fail: %s", ifp->name, - safe_strerror (errno)); - return ret; - } - return 0; - } - memcpy (&mask, &lifreq.lifr_addr, ADDRLEN (addr)); - - prefixlen = ip_masklen (SIN (&mask)->sin_addr); - if (!dest_pnt && (if_ioctl (SIOCGLIFBRDADDR, (caddr_t) & lifreq) >= 0)) - { - memcpy (&dest, &lifreq.lifr_broadaddr, sizeof (struct sockaddr_in)); - dest_pnt = (char *) &SIN (&dest)->sin_addr; - } - } - else if (af == AF_INET6) - { - if (if_ioctl_ipv6 (SIOCGLIFSUBNET, (caddr_t) & lifreq) < 0) - { - if (ifp->flags & IFF_POINTOPOINT) - prefixlen = IPV6_MAX_BITLEN; - else - zlog_warn ("SIOCGLIFSUBNET (%s) fail: %s", - ifp->name, safe_strerror (errno)); + int ret; + struct lifreq lifreq; + struct sockaddr_storage mask, dest; + char *dest_pnt = NULL; + u_char prefixlen = 0; + afi_t af; + int flags = 0; + + /* Interface's name and address family. + * We need to use the logical interface name / label, if we've been + * given one, in order to get the right address + */ + strncpy(lifreq.lifr_name, (label ? label : ifp->name), IFNAMSIZ); + + /* Interface's address. */ + memcpy(&lifreq.lifr_addr, addr, ADDRLEN(addr)); + af = addr->sa_family; + + /* Point to point or broad cast address pointer init. */ + dest_pnt = NULL; + + if (AF_IOCTL(af, SIOCGLIFDSTADDR, (caddr_t)&lifreq) >= 0) { + memcpy(&dest, &lifreq.lifr_dstaddr, ADDRLEN(addr)); + if (af == AF_INET) + dest_pnt = (char *)&(SIN(&dest)->sin_addr); + else + dest_pnt = (char *)&(SIN6(&dest)->sin6_addr); + flags = ZEBRA_IFA_PEER; } - else - { - prefixlen = lifreq.lifr_addrlen; + + if (af == AF_INET) { + ret = if_ioctl(SIOCGLIFNETMASK, (caddr_t)&lifreq); + + if (ret < 0) { + if (errno != EADDRNOTAVAIL) { + zlog_warn("SIOCGLIFNETMASK (%s) fail: %s", + ifp->name, safe_strerror(errno)); + return ret; + } + return 0; + } + memcpy(&mask, &lifreq.lifr_addr, ADDRLEN(addr)); + + prefixlen = ip_masklen(SIN(&mask)->sin_addr); + if (!dest_pnt + && (if_ioctl(SIOCGLIFBRDADDR, (caddr_t)&lifreq) >= 0)) { + memcpy(&dest, &lifreq.lifr_broadaddr, + sizeof(struct sockaddr_in)); + dest_pnt = (char *)&SIN(&dest)->sin_addr; + } + } else if (af == AF_INET6) { + if (if_ioctl_ipv6(SIOCGLIFSUBNET, (caddr_t)&lifreq) < 0) { + if (ifp->flags & IFF_POINTOPOINT) + prefixlen = IPV6_MAX_BITLEN; + else + zlog_warn("SIOCGLIFSUBNET (%s) fail: %s", + ifp->name, safe_strerror(errno)); + } else { + prefixlen = lifreq.lifr_addrlen; + } } - } - /* Set address to the interface. */ - if (af == AF_INET) - connected_add_ipv4 (ifp, flags, &SIN (addr)->sin_addr, prefixlen, - (struct in_addr *) dest_pnt, label); - else if (af == AF_INET6) - connected_add_ipv6 (ifp, flags, &SIN6 (addr)->sin6_addr, prefixlen, - (struct in6_addr *) dest_pnt, label); + /* Set address to the interface. */ + if (af == AF_INET) + connected_add_ipv4(ifp, flags, &SIN(addr)->sin_addr, prefixlen, + (struct in_addr *)dest_pnt, label); + else if (af == AF_INET6) + connected_add_ipv6(ifp, flags, &SIN6(addr)->sin6_addr, + prefixlen, (struct in6_addr *)dest_pnt, + label); - return 0; + return 0; } /* Fetch interface information via ioctl(). */ -static void -interface_info_ioctl (struct interface *ifp) +static void interface_info_ioctl(struct interface *ifp) { - if_get_index (ifp); - if_get_flags (ifp); - if_get_mtu (ifp); - if_get_metric (ifp); + if_get_index(ifp); + if_get_flags(ifp); + if_get_mtu(ifp); + if_get_metric(ifp); } /* Lookup all interface information. */ -void -interface_list (struct zebra_ns *zns) +void interface_list(struct zebra_ns *zns) { - if (zns->ns_id != NS_DEFAULT) - { - zlog_warn ("interface_list: ignore NS %u", zns->ns_id); - return; - } - interface_list_ioctl (AF_INET); - interface_list_ioctl (AF_INET6); - interface_list_ioctl (AF_UNSPEC); + if (zns->ns_id != NS_DEFAULT) { + zlog_warn("interface_list: ignore NS %u", zns->ns_id); + return; + } + interface_list_ioctl(AF_INET); + interface_list_ioctl(AF_INET6); + interface_list_ioctl(AF_UNSPEC); } -struct connected * -if_lookup_linklocal (struct interface *ifp) +struct connected *if_lookup_linklocal(struct interface *ifp) { - struct listnode *node; - struct connected *ifc; + struct listnode *node; + struct connected *ifc; - if (ifp == NULL) - return NULL; + if (ifp == NULL) + return NULL; - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) - { - if ((ifc->address->family == AF_INET6) && - (IN6_IS_ADDR_LINKLOCAL (&ifc->address->u.prefix6))) - return ifc; - } + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + if ((ifc->address->family == AF_INET6) + && (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6))) + return ifc; + } - return NULL; + return NULL; } diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index d0907a267..acec2db52 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -66,143 +66,192 @@ /* Note: on netlink systems, there should be a 1-to-1 mapping between interface names and ifindex values. */ -static void -set_ifindex(struct interface *ifp, ifindex_t ifi_index, struct zebra_ns *zns) +static void set_ifindex(struct interface *ifp, ifindex_t ifi_index, + struct zebra_ns *zns) { - struct interface *oifp; - - if (((oifp = if_lookup_by_index_per_ns (zns, ifi_index)) != NULL) && (oifp != ifp)) - { - if (ifi_index == IFINDEX_INTERNAL) - zlog_err("Netlink is setting interface %s ifindex to reserved " - "internal value %u", ifp->name, ifi_index); - else - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("interface index %d was renamed from %s to %s", - ifi_index, oifp->name, ifp->name); - if (if_is_up(oifp)) - zlog_err("interface rename detected on up interface: index %d " - "was renamed from %s to %s, results are uncertain!", - ifi_index, oifp->name, ifp->name); - if_delete_update(oifp); - } - } - ifp->ifindex = ifi_index; + struct interface *oifp; + + if (((oifp = if_lookup_by_index_per_ns(zns, ifi_index)) != NULL) + && (oifp != ifp)) { + if (ifi_index == IFINDEX_INTERNAL) + zlog_err( + "Netlink is setting interface %s ifindex to reserved " + "internal value %u", + ifp->name, ifi_index); + else { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "interface index %d was renamed from %s to %s", + ifi_index, oifp->name, ifp->name); + if (if_is_up(oifp)) + zlog_err( + "interface rename detected on up interface: index %d " + "was renamed from %s to %s, results are uncertain!", + ifi_index, oifp->name, ifp->name); + if_delete_update(oifp); + } + } + ifp->ifindex = ifi_index; } /* Utility function to parse hardware link-layer address and update ifp */ -static void -netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp) +static void netlink_interface_update_hw_addr(struct rtattr **tb, + struct interface *ifp) { - int i; - - if (tb[IFLA_ADDRESS]) - { - int hw_addr_len; - - hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]); - - if (hw_addr_len > INTERFACE_HWADDR_MAX) - zlog_warn ("Hardware address is too large: %d", hw_addr_len); - else - { - ifp->hw_addr_len = hw_addr_len; - memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len); - - for (i = 0; i < hw_addr_len; i++) - if (ifp->hw_addr[i] != 0) - break; - - if (i == hw_addr_len) - ifp->hw_addr_len = 0; - else - ifp->hw_addr_len = hw_addr_len; - } - } + int i; + + if (tb[IFLA_ADDRESS]) { + int hw_addr_len; + + hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]); + + if (hw_addr_len > INTERFACE_HWADDR_MAX) + zlog_warn("Hardware address is too large: %d", + hw_addr_len); + else { + ifp->hw_addr_len = hw_addr_len; + memcpy(ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]), + hw_addr_len); + + for (i = 0; i < hw_addr_len; i++) + if (ifp->hw_addr[i] != 0) + break; + + if (i == hw_addr_len) + ifp->hw_addr_len = 0; + else + ifp->hw_addr_len = hw_addr_len; + } + } } -static enum zebra_link_type -netlink_to_zebra_link_type (unsigned int hwt) +static enum zebra_link_type netlink_to_zebra_link_type(unsigned int hwt) { - switch (hwt) - { - case ARPHRD_ETHER: return ZEBRA_LLT_ETHER; - case ARPHRD_EETHER: return ZEBRA_LLT_EETHER; - case ARPHRD_AX25: return ZEBRA_LLT_AX25; - case ARPHRD_PRONET: return ZEBRA_LLT_PRONET; - case ARPHRD_IEEE802: return ZEBRA_LLT_IEEE802; - case ARPHRD_ARCNET: return ZEBRA_LLT_ARCNET; - case ARPHRD_APPLETLK: return ZEBRA_LLT_APPLETLK; - case ARPHRD_DLCI: return ZEBRA_LLT_DLCI; - case ARPHRD_ATM: return ZEBRA_LLT_ATM; - case ARPHRD_METRICOM: return ZEBRA_LLT_METRICOM; - case ARPHRD_IEEE1394: return ZEBRA_LLT_IEEE1394; - case ARPHRD_EUI64: return ZEBRA_LLT_EUI64; - case ARPHRD_INFINIBAND: return ZEBRA_LLT_INFINIBAND; - case ARPHRD_SLIP: return ZEBRA_LLT_SLIP; - case ARPHRD_CSLIP: return ZEBRA_LLT_CSLIP; - case ARPHRD_SLIP6: return ZEBRA_LLT_SLIP6; - case ARPHRD_CSLIP6: return ZEBRA_LLT_CSLIP6; - case ARPHRD_RSRVD: return ZEBRA_LLT_RSRVD; - case ARPHRD_ADAPT: return ZEBRA_LLT_ADAPT; - case ARPHRD_ROSE: return ZEBRA_LLT_ROSE; - case ARPHRD_X25: return ZEBRA_LLT_X25; - case ARPHRD_PPP: return ZEBRA_LLT_PPP; - case ARPHRD_CISCO: return ZEBRA_LLT_CHDLC; - case ARPHRD_LAPB: return ZEBRA_LLT_LAPB; - case ARPHRD_RAWHDLC: return ZEBRA_LLT_RAWHDLC; - case ARPHRD_TUNNEL: return ZEBRA_LLT_IPIP; - case ARPHRD_TUNNEL6: return ZEBRA_LLT_IPIP6; - case ARPHRD_FRAD: return ZEBRA_LLT_FRAD; - case ARPHRD_SKIP: return ZEBRA_LLT_SKIP; - case ARPHRD_LOOPBACK: return ZEBRA_LLT_LOOPBACK; - case ARPHRD_LOCALTLK: return ZEBRA_LLT_LOCALTLK; - case ARPHRD_FDDI: return ZEBRA_LLT_FDDI; - case ARPHRD_SIT: return ZEBRA_LLT_SIT; - case ARPHRD_IPDDP: return ZEBRA_LLT_IPDDP; - case ARPHRD_IPGRE: return ZEBRA_LLT_IPGRE; - case ARPHRD_PIMREG: return ZEBRA_LLT_PIMREG; - case ARPHRD_HIPPI: return ZEBRA_LLT_HIPPI; - case ARPHRD_ECONET: return ZEBRA_LLT_ECONET; - case ARPHRD_IRDA: return ZEBRA_LLT_IRDA; - case ARPHRD_FCPP: return ZEBRA_LLT_FCPP; - case ARPHRD_FCAL: return ZEBRA_LLT_FCAL; - case ARPHRD_FCPL: return ZEBRA_LLT_FCPL; - case ARPHRD_FCFABRIC: return ZEBRA_LLT_FCFABRIC; - case ARPHRD_IEEE802_TR: return ZEBRA_LLT_IEEE802_TR; - case ARPHRD_IEEE80211: return ZEBRA_LLT_IEEE80211; - case ARPHRD_IEEE802154: return ZEBRA_LLT_IEEE802154; + switch (hwt) { + case ARPHRD_ETHER: + return ZEBRA_LLT_ETHER; + case ARPHRD_EETHER: + return ZEBRA_LLT_EETHER; + case ARPHRD_AX25: + return ZEBRA_LLT_AX25; + case ARPHRD_PRONET: + return ZEBRA_LLT_PRONET; + case ARPHRD_IEEE802: + return ZEBRA_LLT_IEEE802; + case ARPHRD_ARCNET: + return ZEBRA_LLT_ARCNET; + case ARPHRD_APPLETLK: + return ZEBRA_LLT_APPLETLK; + case ARPHRD_DLCI: + return ZEBRA_LLT_DLCI; + case ARPHRD_ATM: + return ZEBRA_LLT_ATM; + case ARPHRD_METRICOM: + return ZEBRA_LLT_METRICOM; + case ARPHRD_IEEE1394: + return ZEBRA_LLT_IEEE1394; + case ARPHRD_EUI64: + return ZEBRA_LLT_EUI64; + case ARPHRD_INFINIBAND: + return ZEBRA_LLT_INFINIBAND; + case ARPHRD_SLIP: + return ZEBRA_LLT_SLIP; + case ARPHRD_CSLIP: + return ZEBRA_LLT_CSLIP; + case ARPHRD_SLIP6: + return ZEBRA_LLT_SLIP6; + case ARPHRD_CSLIP6: + return ZEBRA_LLT_CSLIP6; + case ARPHRD_RSRVD: + return ZEBRA_LLT_RSRVD; + case ARPHRD_ADAPT: + return ZEBRA_LLT_ADAPT; + case ARPHRD_ROSE: + return ZEBRA_LLT_ROSE; + case ARPHRD_X25: + return ZEBRA_LLT_X25; + case ARPHRD_PPP: + return ZEBRA_LLT_PPP; + case ARPHRD_CISCO: + return ZEBRA_LLT_CHDLC; + case ARPHRD_LAPB: + return ZEBRA_LLT_LAPB; + case ARPHRD_RAWHDLC: + return ZEBRA_LLT_RAWHDLC; + case ARPHRD_TUNNEL: + return ZEBRA_LLT_IPIP; + case ARPHRD_TUNNEL6: + return ZEBRA_LLT_IPIP6; + case ARPHRD_FRAD: + return ZEBRA_LLT_FRAD; + case ARPHRD_SKIP: + return ZEBRA_LLT_SKIP; + case ARPHRD_LOOPBACK: + return ZEBRA_LLT_LOOPBACK; + case ARPHRD_LOCALTLK: + return ZEBRA_LLT_LOCALTLK; + case ARPHRD_FDDI: + return ZEBRA_LLT_FDDI; + case ARPHRD_SIT: + return ZEBRA_LLT_SIT; + case ARPHRD_IPDDP: + return ZEBRA_LLT_IPDDP; + case ARPHRD_IPGRE: + return ZEBRA_LLT_IPGRE; + case ARPHRD_PIMREG: + return ZEBRA_LLT_PIMREG; + case ARPHRD_HIPPI: + return ZEBRA_LLT_HIPPI; + case ARPHRD_ECONET: + return ZEBRA_LLT_ECONET; + case ARPHRD_IRDA: + return ZEBRA_LLT_IRDA; + case ARPHRD_FCPP: + return ZEBRA_LLT_FCPP; + case ARPHRD_FCAL: + return ZEBRA_LLT_FCAL; + case ARPHRD_FCPL: + return ZEBRA_LLT_FCPL; + case ARPHRD_FCFABRIC: + return ZEBRA_LLT_FCFABRIC; + case ARPHRD_IEEE802_TR: + return ZEBRA_LLT_IEEE802_TR; + case ARPHRD_IEEE80211: + return ZEBRA_LLT_IEEE80211; + case ARPHRD_IEEE802154: + return ZEBRA_LLT_IEEE802154; #ifdef ARPHRD_IP6GRE - case ARPHRD_IP6GRE: return ZEBRA_LLT_IP6GRE; + case ARPHRD_IP6GRE: + return ZEBRA_LLT_IP6GRE; #endif #ifdef ARPHRD_IEEE802154_PHY - case ARPHRD_IEEE802154_PHY: return ZEBRA_LLT_IEEE802154_PHY; + case ARPHRD_IEEE802154_PHY: + return ZEBRA_LLT_IEEE802154_PHY; #endif - default: return ZEBRA_LLT_UNKNOWN; - } + default: + return ZEBRA_LLT_UNKNOWN; + } } -static void -netlink_determine_zebra_iftype (char *kind, zebra_iftype_t *zif_type) +static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type) { - *zif_type = ZEBRA_IF_OTHER; - - if (!kind) - return; - - if (strcmp(kind, "vrf") == 0) - *zif_type = ZEBRA_IF_VRF; - else if (strcmp(kind, "bridge") == 0) - *zif_type = ZEBRA_IF_BRIDGE; - else if (strcmp(kind, "vlan") == 0) - *zif_type = ZEBRA_IF_VLAN; - else if (strcmp(kind, "vxlan") == 0) - *zif_type = ZEBRA_IF_VXLAN; + *zif_type = ZEBRA_IF_OTHER; + + if (!kind) + return; + + if (strcmp(kind, "vrf") == 0) + *zif_type = ZEBRA_IF_VRF; + else if (strcmp(kind, "bridge") == 0) + *zif_type = ZEBRA_IF_BRIDGE; + else if (strcmp(kind, "vlan") == 0) + *zif_type = ZEBRA_IF_VLAN; + else if (strcmp(kind, "vxlan") == 0) + *zif_type = ZEBRA_IF_VXLAN; } -//Temporary Assignments to compile on older platforms. +// Temporary Assignments to compile on older platforms. #ifndef IFLA_BR_MAX #define IFLA_BR_MAX 39 #endif @@ -243,198 +292,196 @@ netlink_determine_zebra_iftype (char *kind, zebra_iftype_t *zif_type) #define IFLA_BR_VLAN_FILTERING 7 #endif -#define parse_rtattr_nested(tb, max, rta) \ - netlink_parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)) +#define parse_rtattr_nested(tb, max, rta) \ + netlink_parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)) -static void -netlink_vrf_change (struct nlmsghdr *h, struct rtattr *tb, const char *name) +static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb, + const char *name) { - struct ifinfomsg *ifi; - struct rtattr *linkinfo[IFLA_INFO_MAX+1]; - struct rtattr *attr[IFLA_VRF_MAX+1]; - struct vrf *vrf; - struct zebra_vrf *zvrf; - u_int32_t nl_table_id; - - ifi = NLMSG_DATA (h); - - memset (linkinfo, 0, sizeof linkinfo); - parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); - - if (!linkinfo[IFLA_INFO_DATA]) { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: IFLA_INFO_DATA missing from VRF message: %s", __func__, name); - return; - } - - memset (attr, 0, sizeof attr); - parse_rtattr_nested(attr, IFLA_VRF_MAX, linkinfo[IFLA_INFO_DATA]); - if (!attr[IFLA_VRF_TABLE]) { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: IFLA_VRF_TABLE missing from VRF message: %s", __func__, name); - return; - } - - nl_table_id = *(u_int32_t *)RTA_DATA(attr[IFLA_VRF_TABLE]); - - if (h->nlmsg_type == RTM_NEWLINK) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_NEWLINK for VRF %s(%u) table %u", - name, ifi->ifi_index, nl_table_id); - - /* - * vrf_get is implied creation if it does not exist - */ - vrf = vrf_get((vrf_id_t)ifi->ifi_index, name); // It would create vrf - if (!vrf) - { - zlog_err ("VRF %s id %u not created", name, ifi->ifi_index); - return; - } - - /* Enable the created VRF. */ - if (!vrf_enable (vrf)) - { - zlog_err ("Failed to enable VRF %s id %u", name, ifi->ifi_index); - return; - } - - /* - * This is the only place that we get the actual kernel table_id - * being used. We need it to set the table_id of the routes - * we are passing to the kernel.... And to throw some totally - * awesome parties. that too. - */ - zvrf = (struct zebra_vrf *)vrf->info; - zvrf->table_id = nl_table_id; - } - else //h->nlmsg_type == RTM_DELLINK - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_DELLINK for VRF %s(%u)", name, ifi->ifi_index); - - vrf = vrf_lookup_by_id ((vrf_id_t)ifi->ifi_index); - - if (!vrf) - { - zlog_warn ("%s: vrf not found", __func__); - return; + struct ifinfomsg *ifi; + struct rtattr *linkinfo[IFLA_INFO_MAX + 1]; + struct rtattr *attr[IFLA_VRF_MAX + 1]; + struct vrf *vrf; + struct zebra_vrf *zvrf; + u_int32_t nl_table_id; + + ifi = NLMSG_DATA(h); + + memset(linkinfo, 0, sizeof linkinfo); + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); + + if (!linkinfo[IFLA_INFO_DATA]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: IFLA_INFO_DATA missing from VRF message: %s", + __func__, name); + return; + } + + memset(attr, 0, sizeof attr); + parse_rtattr_nested(attr, IFLA_VRF_MAX, linkinfo[IFLA_INFO_DATA]); + if (!attr[IFLA_VRF_TABLE]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: IFLA_VRF_TABLE missing from VRF message: %s", + __func__, name); + return; } - vrf_delete (vrf); - } + nl_table_id = *(u_int32_t *)RTA_DATA(attr[IFLA_VRF_TABLE]); + + if (h->nlmsg_type == RTM_NEWLINK) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("RTM_NEWLINK for VRF %s(%u) table %u", name, + ifi->ifi_index, nl_table_id); + + /* + * vrf_get is implied creation if it does not exist + */ + vrf = vrf_get((vrf_id_t)ifi->ifi_index, + name); // It would create vrf + if (!vrf) { + zlog_err("VRF %s id %u not created", name, + ifi->ifi_index); + return; + } + + /* Enable the created VRF. */ + if (!vrf_enable(vrf)) { + zlog_err("Failed to enable VRF %s id %u", name, + ifi->ifi_index); + return; + } + + /* + * This is the only place that we get the actual kernel table_id + * being used. We need it to set the table_id of the routes + * we are passing to the kernel.... And to throw some totally + * awesome parties. that too. + */ + zvrf = (struct zebra_vrf *)vrf->info; + zvrf->table_id = nl_table_id; + } else // h->nlmsg_type == RTM_DELLINK + { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("RTM_DELLINK for VRF %s(%u)", name, + ifi->ifi_index); + + vrf = vrf_lookup_by_id((vrf_id_t)ifi->ifi_index); + + if (!vrf) { + zlog_warn("%s: vrf not found", __func__); + return; + } + + vrf_delete(vrf); + } } -static int -get_iflink_speed (const char *ifname) +static int get_iflink_speed(const char *ifname) { - struct ifreq ifdata; - struct ethtool_cmd ecmd; - int sd; - int rc; - - /* initialize struct */ - memset(&ifdata, 0, sizeof(ifdata)); - - /* set interface name */ - strcpy(ifdata.ifr_name, ifname); - - /* initialize ethtool interface */ - memset(&ecmd, 0, sizeof(ecmd)); - ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */ - ifdata.ifr_data = (__caddr_t) &ecmd; - - /* use ioctl to get IP address of an interface */ - sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); - if(sd < 0) { - zlog_debug ("Failure to read interface %s speed: %d %s", - ifname, errno, safe_strerror(errno)); - return 0; - } - - /* Get the current link state for the interface */ - rc = ioctl(sd, SIOCETHTOOL, (char *)&ifdata); - if(rc < 0) { - zlog_debug("IOCTL failure to read interface %s speed: %d %s", - ifname, errno, safe_strerror(errno)); - ecmd.speed_hi = 0; - ecmd.speed = 0; - } - - close(sd); - - return (ecmd.speed_hi << 16 ) | ecmd.speed; + struct ifreq ifdata; + struct ethtool_cmd ecmd; + int sd; + int rc; + + /* initialize struct */ + memset(&ifdata, 0, sizeof(ifdata)); + + /* set interface name */ + strcpy(ifdata.ifr_name, ifname); + + /* initialize ethtool interface */ + memset(&ecmd, 0, sizeof(ecmd)); + ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */ + ifdata.ifr_data = (__caddr_t)&ecmd; + + /* use ioctl to get IP address of an interface */ + sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + if (sd < 0) { + zlog_debug("Failure to read interface %s speed: %d %s", ifname, + errno, safe_strerror(errno)); + return 0; + } + + /* Get the current link state for the interface */ + rc = ioctl(sd, SIOCETHTOOL, (char *)&ifdata); + if (rc < 0) { + zlog_debug("IOCTL failure to read interface %s speed: %d %s", + ifname, errno, safe_strerror(errno)); + ecmd.speed_hi = 0; + ecmd.speed = 0; + } + + close(sd); + + return (ecmd.speed_hi << 16) | ecmd.speed; } -static int -netlink_extract_bridge_info (struct rtattr *link_data, - struct zebra_l2info_bridge *bridge_info) +static int netlink_extract_bridge_info(struct rtattr *link_data, + struct zebra_l2info_bridge *bridge_info) { - struct rtattr *attr[IFLA_BR_MAX+1]; - - memset (bridge_info, 0, sizeof (*bridge_info)); - memset (attr, 0, sizeof attr); - parse_rtattr_nested(attr, IFLA_BR_MAX, link_data); - if (attr[IFLA_BR_VLAN_FILTERING]) - bridge_info->vlan_aware = *(u_char *)RTA_DATA(attr[IFLA_BR_VLAN_FILTERING]); - return 0; + struct rtattr *attr[IFLA_BR_MAX + 1]; + + memset(bridge_info, 0, sizeof(*bridge_info)); + memset(attr, 0, sizeof attr); + parse_rtattr_nested(attr, IFLA_BR_MAX, link_data); + if (attr[IFLA_BR_VLAN_FILTERING]) + bridge_info->vlan_aware = + *(u_char *)RTA_DATA(attr[IFLA_BR_VLAN_FILTERING]); + return 0; } -static int -netlink_extract_vlan_info (struct rtattr *link_data, - struct zebra_l2info_vlan *vlan_info) +static int netlink_extract_vlan_info(struct rtattr *link_data, + struct zebra_l2info_vlan *vlan_info) { - struct rtattr *attr[IFLA_VLAN_MAX+1]; - vlanid_t vid_in_msg; - - memset (vlan_info, 0, sizeof (*vlan_info)); - memset (attr, 0, sizeof attr); - parse_rtattr_nested(attr, IFLA_VLAN_MAX, link_data); - if (!attr[IFLA_VLAN_ID]) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("IFLA_VLAN_ID missing from VLAN IF message"); - return -1; - } - - vid_in_msg = *(vlanid_t *)RTA_DATA(attr[IFLA_VLAN_ID]); - vlan_info->vid = vid_in_msg; - return 0; + struct rtattr *attr[IFLA_VLAN_MAX + 1]; + vlanid_t vid_in_msg; + + memset(vlan_info, 0, sizeof(*vlan_info)); + memset(attr, 0, sizeof attr); + parse_rtattr_nested(attr, IFLA_VLAN_MAX, link_data); + if (!attr[IFLA_VLAN_ID]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("IFLA_VLAN_ID missing from VLAN IF message"); + return -1; + } + + vid_in_msg = *(vlanid_t *)RTA_DATA(attr[IFLA_VLAN_ID]); + vlan_info->vid = vid_in_msg; + return 0; } -static int -netlink_extract_vxlan_info (struct rtattr *link_data, - struct zebra_l2info_vxlan *vxl_info) +static int netlink_extract_vxlan_info(struct rtattr *link_data, + struct zebra_l2info_vxlan *vxl_info) { - struct rtattr *attr[IFLA_VXLAN_MAX+1]; - vni_t vni_in_msg; - struct in_addr vtep_ip_in_msg; - - memset (vxl_info, 0, sizeof (*vxl_info)); - memset (attr, 0, sizeof attr); - parse_rtattr_nested(attr, IFLA_VXLAN_MAX, link_data); - if (!attr[IFLA_VXLAN_ID]) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("IFLA_VXLAN_ID missing from VXLAN IF message"); - return -1; - } - - vni_in_msg = *(vni_t *)RTA_DATA(attr[IFLA_VXLAN_ID]); - vxl_info->vni = vni_in_msg; - if (!attr[IFLA_VXLAN_LOCAL]) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("IFLA_VXLAN_LOCAL missing from VXLAN IF message"); - } - else - { - vtep_ip_in_msg = *(struct in_addr *)RTA_DATA(attr[IFLA_VXLAN_LOCAL]); - vxl_info->vtep_ip = vtep_ip_in_msg; - } - - return 0; + struct rtattr *attr[IFLA_VXLAN_MAX + 1]; + vni_t vni_in_msg; + struct in_addr vtep_ip_in_msg; + + memset(vxl_info, 0, sizeof(*vxl_info)); + memset(attr, 0, sizeof attr); + parse_rtattr_nested(attr, IFLA_VXLAN_MAX, link_data); + if (!attr[IFLA_VXLAN_ID]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "IFLA_VXLAN_ID missing from VXLAN IF message"); + return -1; + } + + vni_in_msg = *(vni_t *)RTA_DATA(attr[IFLA_VXLAN_ID]); + vxl_info->vni = vni_in_msg; + if (!attr[IFLA_VXLAN_LOCAL]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "IFLA_VXLAN_LOCAL missing from VXLAN IF message"); + } else { + vtep_ip_in_msg = + *(struct in_addr *)RTA_DATA(attr[IFLA_VXLAN_LOCAL]); + vxl_info->vtep_ip = vtep_ip_in_msg; + } + + return 0; } /* @@ -442,756 +489,732 @@ netlink_extract_vxlan_info (struct rtattr *link_data, * bridge interface is added or updated, take further actions to map * its members. Likewise, for VxLAN interface. */ -static void -netlink_interface_update_l2info (struct interface *ifp, - struct rtattr *link_data, - int add) +static void netlink_interface_update_l2info(struct interface *ifp, + struct rtattr *link_data, int add) { - if (!link_data) - return; - - if (IS_ZEBRA_IF_BRIDGE(ifp)) - { - struct zebra_l2info_bridge bridge_info; - - netlink_extract_bridge_info (link_data, &bridge_info); - zebra_l2_bridge_add_update (ifp, &bridge_info, add); - } - else if (IS_ZEBRA_IF_VLAN(ifp)) - { - struct zebra_l2info_vlan vlan_info; - - netlink_extract_vlan_info (link_data, &vlan_info); - zebra_l2_vlanif_update (ifp, &vlan_info); - } - else if (IS_ZEBRA_IF_VXLAN(ifp)) - { - struct zebra_l2info_vxlan vxlan_info; - - netlink_extract_vxlan_info (link_data, &vxlan_info); - zebra_l2_vxlanif_add_update (ifp, &vxlan_info, add); - } + if (!link_data) + return; + + if (IS_ZEBRA_IF_BRIDGE(ifp)) { + struct zebra_l2info_bridge bridge_info; + + netlink_extract_bridge_info(link_data, &bridge_info); + zebra_l2_bridge_add_update(ifp, &bridge_info, add); + } else if (IS_ZEBRA_IF_VLAN(ifp)) { + struct zebra_l2info_vlan vlan_info; + + netlink_extract_vlan_info(link_data, &vlan_info); + zebra_l2_vlanif_update(ifp, &vlan_info); + } else if (IS_ZEBRA_IF_VXLAN(ifp)) { + struct zebra_l2info_vxlan vxlan_info; + + netlink_extract_vxlan_info(link_data, &vxlan_info); + zebra_l2_vxlanif_add_update(ifp, &vxlan_info, add); + } } -static int -netlink_bridge_interface (struct nlmsghdr *h, int len, - ns_id_t ns_id, int startup) +static int netlink_bridge_interface(struct nlmsghdr *h, int len, ns_id_t ns_id, + int startup) { - char *name = NULL; - struct ifinfomsg *ifi; - struct rtattr *tb[IFLA_MAX + 1]; - struct interface *ifp; - struct rtattr *aftb[IFLA_BRIDGE_MAX + 1]; - struct - { - u_int16_t flags; - u_int16_t vid; - } *vinfo; - vlanid_t access_vlan; - - /* Fetch name and ifindex */ - ifi = NLMSG_DATA (h); - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); - - if (tb[IFLA_IFNAME] == NULL) - return -1; - name = (char *) RTA_DATA (tb[IFLA_IFNAME]); - - /* The interface should already be known, if not discard. */ - ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (ns_id), - ifi->ifi_index); - if (!ifp) - { - zlog_warn ("Cannot find bridge IF %s(%u)", - name, ifi->ifi_index); - return 0; - } - if (!IS_ZEBRA_IF_VXLAN(ifp)) - return 0; - - /* We are only interested in the access VLAN i.e., AF_SPEC */ - if (!tb[IFLA_AF_SPEC]) - return 0; - - /* There is a 1-to-1 mapping of VLAN to VxLAN - hence - * only 1 access VLAN is accepted. - */ - memset (aftb, 0, sizeof aftb); - parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, tb[IFLA_AF_SPEC]); - if (!aftb[IFLA_BRIDGE_VLAN_INFO]) - return 0; - - vinfo = RTA_DATA(aftb[IFLA_BRIDGE_VLAN_INFO]); - if (!(vinfo->flags & BRIDGE_VLAN_INFO_PVID)) - return 0; - - access_vlan = (vlanid_t) vinfo->vid; - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Access VLAN %u for VxLAN IF %s(%u)", - access_vlan, name, ifi->ifi_index); - zebra_l2_vxlanif_update_access_vlan (ifp, access_vlan); - return 0; + char *name = NULL; + struct ifinfomsg *ifi; + struct rtattr *tb[IFLA_MAX + 1]; + struct interface *ifp; + struct rtattr *aftb[IFLA_BRIDGE_MAX + 1]; + struct { + u_int16_t flags; + u_int16_t vid; + } * vinfo; + vlanid_t access_vlan; + + /* Fetch name and ifindex */ + ifi = NLMSG_DATA(h); + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); + + if (tb[IFLA_IFNAME] == NULL) + return -1; + name = (char *)RTA_DATA(tb[IFLA_IFNAME]); + + /* The interface should already be known, if not discard. */ + ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), ifi->ifi_index); + if (!ifp) { + zlog_warn("Cannot find bridge IF %s(%u)", name, ifi->ifi_index); + return 0; + } + if (!IS_ZEBRA_IF_VXLAN(ifp)) + return 0; + + /* We are only interested in the access VLAN i.e., AF_SPEC */ + if (!tb[IFLA_AF_SPEC]) + return 0; + + /* There is a 1-to-1 mapping of VLAN to VxLAN - hence + * only 1 access VLAN is accepted. + */ + memset(aftb, 0, sizeof aftb); + parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, tb[IFLA_AF_SPEC]); + if (!aftb[IFLA_BRIDGE_VLAN_INFO]) + return 0; + + vinfo = RTA_DATA(aftb[IFLA_BRIDGE_VLAN_INFO]); + if (!(vinfo->flags & BRIDGE_VLAN_INFO_PVID)) + return 0; + + access_vlan = (vlanid_t)vinfo->vid; + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Access VLAN %u for VxLAN IF %s(%u)", access_vlan, + name, ifi->ifi_index); + zebra_l2_vxlanif_update_access_vlan(ifp, access_vlan); + return 0; } /* Called from interface_lookup_netlink(). This function is only used during bootstrap. */ -static int -netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +static int netlink_interface(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct ifinfomsg *ifi; - struct rtattr *tb[IFLA_MAX + 1]; - struct rtattr *linkinfo[IFLA_MAX + 1]; - struct interface *ifp; - char *name = NULL; - char *kind = NULL; - char *slave_kind = NULL; - struct zebra_ns *zns; - vrf_id_t vrf_id = VRF_DEFAULT; - zebra_iftype_t zif_type = ZEBRA_IF_OTHER; - zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE; - ifindex_t bridge_ifindex = IFINDEX_INTERNAL; - ifindex_t link_ifindex = IFINDEX_INTERNAL; - - zns = zebra_ns_lookup (ns_id); - ifi = NLMSG_DATA (h); - - if (h->nlmsg_type != RTM_NEWLINK) - return 0; - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg)); - if (len < 0) - return -1; - - /* We are interested in some AF_BRIDGE notifications. */ - if (ifi->ifi_family == AF_BRIDGE) - return netlink_bridge_interface (h, len, ns_id, startup); - - /* Looking up interface name. */ - memset (tb, 0, sizeof tb); - memset (linkinfo, 0, sizeof linkinfo); - netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); + int len; + struct ifinfomsg *ifi; + struct rtattr *tb[IFLA_MAX + 1]; + struct rtattr *linkinfo[IFLA_MAX + 1]; + struct interface *ifp; + char *name = NULL; + char *kind = NULL; + char *slave_kind = NULL; + struct zebra_ns *zns; + vrf_id_t vrf_id = VRF_DEFAULT; + zebra_iftype_t zif_type = ZEBRA_IF_OTHER; + zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE; + ifindex_t bridge_ifindex = IFINDEX_INTERNAL; + ifindex_t link_ifindex = IFINDEX_INTERNAL; + + zns = zebra_ns_lookup(ns_id); + ifi = NLMSG_DATA(h); + + if (h->nlmsg_type != RTM_NEWLINK) + return 0; + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg)); + if (len < 0) + return -1; + + /* We are interested in some AF_BRIDGE notifications. */ + if (ifi->ifi_family == AF_BRIDGE) + return netlink_bridge_interface(h, len, ns_id, startup); + + /* Looking up interface name. */ + memset(tb, 0, sizeof tb); + memset(linkinfo, 0, sizeof linkinfo); + netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); #ifdef IFLA_WIRELESS - /* check for wireless messages to ignore */ - if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__); - return 0; - } + /* check for wireless messages to ignore */ + if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: ignoring IFLA_WIRELESS message", + __func__); + return 0; + } #endif /* IFLA_WIRELESS */ - if (tb[IFLA_IFNAME] == NULL) - return -1; - name = (char *) RTA_DATA (tb[IFLA_IFNAME]); + if (tb[IFLA_IFNAME] == NULL) + return -1; + name = (char *)RTA_DATA(tb[IFLA_IFNAME]); - if (tb[IFLA_LINKINFO]) - { - parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); + if (tb[IFLA_LINKINFO]) { + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); - if (linkinfo[IFLA_INFO_KIND]) - kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); + if (linkinfo[IFLA_INFO_KIND]) + kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); #if HAVE_DECL_IFLA_INFO_SLAVE_KIND - if (linkinfo[IFLA_INFO_SLAVE_KIND]) - slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); + if (linkinfo[IFLA_INFO_SLAVE_KIND]) + slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); #endif - netlink_determine_zebra_iftype (kind, &zif_type); - } - - /* If VRF, create the VRF structure itself. */ - if (zif_type == ZEBRA_IF_VRF) - { - netlink_vrf_change(h, tb[IFLA_LINKINFO], name); - vrf_id = (vrf_id_t)ifi->ifi_index; - } - - if (tb[IFLA_MASTER]) - { - if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) - { - zif_slave_type = ZEBRA_IF_SLAVE_VRF; - vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); - } - else if (slave_kind && (strcmp(slave_kind, "bridge") == 0)) - { - zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE; - bridge_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); - } - else - zif_slave_type = ZEBRA_IF_SLAVE_OTHER; - } - - /* If linking to another interface, note it. */ - if (tb[IFLA_LINK]) - link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]); - - /* Add interface. */ - ifp = if_get_by_name (name, vrf_id); - set_ifindex(ifp, ifi->ifi_index, zns); - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (IS_ZEBRA_IF_VRF(ifp)) - SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); - ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 0; - ifp->speed = get_iflink_speed (name); - ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; - - /* Set zebra interface type */ - zebra_if_set_ziftype (ifp, zif_type, zif_slave_type); - - /* Update link. */ - zebra_if_update_link (ifp, link_ifindex); - - /* Hardware type and address. */ - ifp->ll_type = netlink_to_zebra_link_type (ifi->ifi_type); - netlink_interface_update_hw_addr (tb, ifp); - - if_add_update (ifp); - - /* Extract and save L2 interface information, take additional actions. */ - netlink_interface_update_l2info (ifp, linkinfo[IFLA_INFO_DATA], 1); - if (IS_ZEBRA_IF_BRIDGE_SLAVE (ifp)) - zebra_l2if_update_bridge_slave (ifp, bridge_ifindex); - - return 0; + netlink_determine_zebra_iftype(kind, &zif_type); + } + + /* If VRF, create the VRF structure itself. */ + if (zif_type == ZEBRA_IF_VRF) { + netlink_vrf_change(h, tb[IFLA_LINKINFO], name); + vrf_id = (vrf_id_t)ifi->ifi_index; + } + + if (tb[IFLA_MASTER]) { + if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) { + zif_slave_type = ZEBRA_IF_SLAVE_VRF; + vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); + } else if (slave_kind && (strcmp(slave_kind, "bridge") == 0)) { + zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE; + bridge_ifindex = + *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); + } else + zif_slave_type = ZEBRA_IF_SLAVE_OTHER; + } + + /* If linking to another interface, note it. */ + if (tb[IFLA_LINK]) + link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]); + + /* Add interface. */ + ifp = if_get_by_name(name, vrf_id); + set_ifindex(ifp, ifi->ifi_index, zns); + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (IS_ZEBRA_IF_VRF(ifp)) + SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); + ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]); + ifp->metric = 0; + ifp->speed = get_iflink_speed(name); + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + + /* Set zebra interface type */ + zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); + + /* Update link. */ + zebra_if_update_link(ifp, link_ifindex); + + /* Hardware type and address. */ + ifp->ll_type = netlink_to_zebra_link_type(ifi->ifi_type); + netlink_interface_update_hw_addr(tb, ifp); + + if_add_update(ifp); + + /* Extract and save L2 interface information, take additional actions. + */ + netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA], 1); + if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) + zebra_l2if_update_bridge_slave(ifp, bridge_ifindex); + + return 0; } /* Request for specific interface or address information from the kernel */ -static int -netlink_request_intf_addr (struct zebra_ns *zns, - int family, int type, - u_int32_t filter_mask) +static int netlink_request_intf_addr(struct zebra_ns *zns, int family, int type, + u_int32_t filter_mask) { - struct - { - struct nlmsghdr n; - struct ifinfomsg ifm; - char buf[256]; - } req; - - /* Form the request, specifying filter (rtattr) if needed. */ - memset (&req, 0, sizeof (req)); - req.n.nlmsg_type = type; - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); - req.ifm.ifi_family = family; - - /* Include filter, if specified. */ - if (filter_mask) - addattr32 (&req.n, sizeof(req), IFLA_EXT_MASK, filter_mask); - - return netlink_request (&zns->netlink_cmd, &req.n); + struct { + struct nlmsghdr n; + struct ifinfomsg ifm; + char buf[256]; + } req; + + /* Form the request, specifying filter (rtattr) if needed. */ + memset(&req, 0, sizeof(req)); + req.n.nlmsg_type = type; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.ifm.ifi_family = family; + + /* Include filter, if specified. */ + if (filter_mask) + addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filter_mask); + + return netlink_request(&zns->netlink_cmd, &req.n); } /* Interface lookup by netlink socket. */ -int -interface_lookup_netlink (struct zebra_ns *zns) +int interface_lookup_netlink(struct zebra_ns *zns) { - int ret; - - /* Get interface information. */ - ret = netlink_request_intf_addr (zns, AF_PACKET, RTM_GETLINK, 0); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0, 1); - if (ret < 0) - return ret; - - /* Get interface information - for bridge interfaces. */ - ret = netlink_request_intf_addr (zns, AF_BRIDGE, RTM_GETLINK, - RTEXT_FILTER_BRVLAN); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0, 0); - if (ret < 0) - return ret; - - /* Get interface information - for bridge interfaces. */ - ret = netlink_request_intf_addr (zns, AF_BRIDGE, RTM_GETLINK, - RTEXT_FILTER_BRVLAN); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0, 0); - if (ret < 0) - return ret; - - /* Get IPv4 address of the interfaces. */ - ret = netlink_request_intf_addr (zns, AF_INET, RTM_GETADDR, 0); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1); - if (ret < 0) - return ret; - - /* Get IPv6 address of the interfaces. */ - ret = netlink_request_intf_addr (zns, AF_INET6, RTM_GETADDR, 0); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1); - if (ret < 0) - return ret; - - return 0; + int ret; + + /* Get interface information. */ + ret = netlink_request_intf_addr(zns, AF_PACKET, RTM_GETLINK, 0); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_interface, &zns->netlink_cmd, zns, 0, + 1); + if (ret < 0) + return ret; + + /* Get interface information - for bridge interfaces. */ + ret = netlink_request_intf_addr(zns, AF_BRIDGE, RTM_GETLINK, + RTEXT_FILTER_BRVLAN); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_interface, &zns->netlink_cmd, zns, 0, + 0); + if (ret < 0) + return ret; + + /* Get interface information - for bridge interfaces. */ + ret = netlink_request_intf_addr(zns, AF_BRIDGE, RTM_GETLINK, + RTEXT_FILTER_BRVLAN); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_interface, &zns->netlink_cmd, zns, 0, + 0); + if (ret < 0) + return ret; + + /* Get IPv4 address of the interfaces. */ + ret = netlink_request_intf_addr(zns, AF_INET, RTM_GETADDR, 0); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_interface_addr, &zns->netlink_cmd, zns, + 0, 1); + if (ret < 0) + return ret; + + /* Get IPv6 address of the interfaces. */ + ret = netlink_request_intf_addr(zns, AF_INET6, RTM_GETADDR, 0); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_interface_addr, &zns->netlink_cmd, zns, + 0, 1); + if (ret < 0) + return ret; + + return 0; } /* Interface address modification. */ -static int -netlink_address (int cmd, int family, struct interface *ifp, - struct connected *ifc) +static int netlink_address(int cmd, int family, struct interface *ifp, + struct connected *ifc) { - int bytelen; - struct prefix *p; + int bytelen; + struct prefix *p; - struct - { - struct nlmsghdr n; - struct ifaddrmsg ifa; - char buf[NL_PKT_BUF_SIZE]; - } req; + struct { + struct nlmsghdr n; + struct ifaddrmsg ifa; + char buf[NL_PKT_BUF_SIZE]; + } req; - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); - p = ifc->address; - memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); + p = ifc->address; + memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); - bytelen = (family == AF_INET ? 4 : 16); + bytelen = (family == AF_INET ? 4 : 16); - req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = cmd; - req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = cmd; + req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; - req.ifa.ifa_family = family; + req.ifa.ifa_family = family; - req.ifa.ifa_index = ifp->ifindex; - req.ifa.ifa_prefixlen = p->prefixlen; + req.ifa.ifa_index = ifp->ifindex; + req.ifa.ifa_prefixlen = p->prefixlen; - addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen); + addattr_l(&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen); - if (family == AF_INET && cmd == RTM_NEWADDR) - { - if (!CONNECTED_PEER(ifc) && ifc->destination) - { - p = ifc->destination; - addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, - bytelen); - } - } + if (family == AF_INET && cmd == RTM_NEWADDR) { + if (!CONNECTED_PEER(ifc) && ifc->destination) { + p = ifc->destination; + addattr_l(&req.n, sizeof req, IFA_BROADCAST, + &p->u.prefix, bytelen); + } + } - if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY)) - SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY); + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) + SET_FLAG(req.ifa.ifa_flags, IFA_F_SECONDARY); - if (ifc->label) - addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label, - strlen (ifc->label) + 1); + if (ifc->label) + addattr_l(&req.n, sizeof req, IFA_LABEL, ifc->label, + strlen(ifc->label) + 1); - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } -int -kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc) +int kernel_address_add_ipv4(struct interface *ifp, struct connected *ifc) { - return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc); + return netlink_address(RTM_NEWADDR, AF_INET, ifp, ifc); } -int -kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc) +int kernel_address_delete_ipv4(struct interface *ifp, struct connected *ifc) { - return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc); + return netlink_address(RTM_DELADDR, AF_INET, ifp, ifc); } -int -netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +int netlink_interface_addr(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct ifaddrmsg *ifa; - struct rtattr *tb[IFA_MAX + 1]; - struct interface *ifp; - void *addr; - void *broad; - u_char flags = 0; - char *label = NULL; - struct zebra_ns *zns; - - zns = zebra_ns_lookup (ns_id); - ifa = NLMSG_DATA (h); - - if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) - return 0; - - if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR) - return 0; - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg)); - if (len < 0) - return -1; - - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len); - - ifp = if_lookup_by_index_per_ns (zns, ifa->ifa_index); - if (ifp == NULL) - { - zlog_err ("netlink_interface_addr can't find interface by index %d", - ifa->ifa_index); - return -1; - } - - if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */ - { - char buf[BUFSIZ]; - zlog_debug ("netlink_interface_addr %s %s flags 0x%x:", - nl_msg_type_to_str (h->nlmsg_type), ifp->name, - ifa->ifa_flags); - if (tb[IFA_LOCAL]) - zlog_debug (" IFA_LOCAL %s/%d", - inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]), - buf, BUFSIZ), ifa->ifa_prefixlen); - if (tb[IFA_ADDRESS]) - zlog_debug (" IFA_ADDRESS %s/%d", - inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_ADDRESS]), - buf, BUFSIZ), ifa->ifa_prefixlen); - if (tb[IFA_BROADCAST]) - zlog_debug (" IFA_BROADCAST %s/%d", - inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_BROADCAST]), - buf, BUFSIZ), ifa->ifa_prefixlen); - if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL]))) - zlog_debug (" IFA_LABEL %s", (char *)RTA_DATA (tb[IFA_LABEL])); - - if (tb[IFA_CACHEINFO]) - { - struct ifa_cacheinfo *ci = RTA_DATA (tb[IFA_CACHEINFO]); - zlog_debug (" IFA_CACHEINFO pref %d, valid %d", - ci->ifa_prefered, ci->ifa_valid); - } - } - - /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */ - if (tb[IFA_LOCAL] == NULL) - tb[IFA_LOCAL] = tb[IFA_ADDRESS]; - if (tb[IFA_ADDRESS] == NULL) - tb[IFA_ADDRESS] = tb[IFA_LOCAL]; - - /* local interface address */ - addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL); - - /* is there a peer address? */ - if (tb[IFA_ADDRESS] && - memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_ADDRESS]))) - { - broad = RTA_DATA(tb[IFA_ADDRESS]); - SET_FLAG (flags, ZEBRA_IFA_PEER); - } - else - /* seeking a broadcast address */ - broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL); - - /* addr is primary key, SOL if we don't have one */ - if (addr == NULL) - { - zlog_debug ("%s: NULL address", __func__); - return -1; - } - - /* Flags. */ - if (ifa->ifa_flags & IFA_F_SECONDARY) - SET_FLAG (flags, ZEBRA_IFA_SECONDARY); - - /* Label */ - if (tb[IFA_LABEL]) - label = (char *) RTA_DATA (tb[IFA_LABEL]); - - if (ifp && label && strcmp (ifp->name, label) == 0) - label = NULL; - - /* Register interface address to the interface. */ - if (ifa->ifa_family == AF_INET) - { - if (h->nlmsg_type == RTM_NEWADDR) - connected_add_ipv4 (ifp, flags, - (struct in_addr *) addr, ifa->ifa_prefixlen, - (struct in_addr *) broad, label); - else - connected_delete_ipv4 (ifp, flags, - (struct in_addr *) addr, ifa->ifa_prefixlen, - (struct in_addr *) broad); - } - if (ifa->ifa_family == AF_INET6) - { - if (h->nlmsg_type == RTM_NEWADDR) - { - /* Only consider valid addresses; we'll not get a notification from - * the kernel till IPv6 DAD has completed, but at init time, Quagga - * does query for and will receive all addresses. - */ - if (!(ifa->ifa_flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))) - connected_add_ipv6 (ifp, flags, (struct in6_addr *) addr, - ifa->ifa_prefixlen, (struct in6_addr *) broad, label); - } - else - connected_delete_ipv6 (ifp, - (struct in6_addr *) addr, ifa->ifa_prefixlen, - (struct in6_addr *) broad); - } - - return 0; + int len; + struct ifaddrmsg *ifa; + struct rtattr *tb[IFA_MAX + 1]; + struct interface *ifp; + void *addr; + void *broad; + u_char flags = 0; + char *label = NULL; + struct zebra_ns *zns; + + zns = zebra_ns_lookup(ns_id); + ifa = NLMSG_DATA(h); + + if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) + return 0; + + if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR) + return 0; + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + if (len < 0) + return -1; + + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len); + + ifp = if_lookup_by_index_per_ns(zns, ifa->ifa_index); + if (ifp == NULL) { + zlog_err( + "netlink_interface_addr can't find interface by index %d", + ifa->ifa_index); + return -1; + } + + if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */ + { + char buf[BUFSIZ]; + zlog_debug("netlink_interface_addr %s %s flags 0x%x:", + nl_msg_type_to_str(h->nlmsg_type), ifp->name, + ifa->ifa_flags); + if (tb[IFA_LOCAL]) + zlog_debug(" IFA_LOCAL %s/%d", + inet_ntop(ifa->ifa_family, + RTA_DATA(tb[IFA_LOCAL]), buf, + BUFSIZ), + ifa->ifa_prefixlen); + if (tb[IFA_ADDRESS]) + zlog_debug(" IFA_ADDRESS %s/%d", + inet_ntop(ifa->ifa_family, + RTA_DATA(tb[IFA_ADDRESS]), buf, + BUFSIZ), + ifa->ifa_prefixlen); + if (tb[IFA_BROADCAST]) + zlog_debug(" IFA_BROADCAST %s/%d", + inet_ntop(ifa->ifa_family, + RTA_DATA(tb[IFA_BROADCAST]), buf, + BUFSIZ), + ifa->ifa_prefixlen); + if (tb[IFA_LABEL] && strcmp(ifp->name, RTA_DATA(tb[IFA_LABEL]))) + zlog_debug(" IFA_LABEL %s", + (char *)RTA_DATA(tb[IFA_LABEL])); + + if (tb[IFA_CACHEINFO]) { + struct ifa_cacheinfo *ci = RTA_DATA(tb[IFA_CACHEINFO]); + zlog_debug(" IFA_CACHEINFO pref %d, valid %d", + ci->ifa_prefered, ci->ifa_valid); + } + } + + /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */ + if (tb[IFA_LOCAL] == NULL) + tb[IFA_LOCAL] = tb[IFA_ADDRESS]; + if (tb[IFA_ADDRESS] == NULL) + tb[IFA_ADDRESS] = tb[IFA_LOCAL]; + + /* local interface address */ + addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL); + + /* is there a peer address? */ + if (tb[IFA_ADDRESS] + && memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), + RTA_PAYLOAD(tb[IFA_ADDRESS]))) { + broad = RTA_DATA(tb[IFA_ADDRESS]); + SET_FLAG(flags, ZEBRA_IFA_PEER); + } else + /* seeking a broadcast address */ + broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) + : NULL); + + /* addr is primary key, SOL if we don't have one */ + if (addr == NULL) { + zlog_debug("%s: NULL address", __func__); + return -1; + } + + /* Flags. */ + if (ifa->ifa_flags & IFA_F_SECONDARY) + SET_FLAG(flags, ZEBRA_IFA_SECONDARY); + + /* Label */ + if (tb[IFA_LABEL]) + label = (char *)RTA_DATA(tb[IFA_LABEL]); + + if (ifp && label && strcmp(ifp->name, label) == 0) + label = NULL; + + /* Register interface address to the interface. */ + if (ifa->ifa_family == AF_INET) { + if (h->nlmsg_type == RTM_NEWADDR) + connected_add_ipv4(ifp, flags, (struct in_addr *)addr, + ifa->ifa_prefixlen, + (struct in_addr *)broad, label); + else + connected_delete_ipv4( + ifp, flags, (struct in_addr *)addr, + ifa->ifa_prefixlen, (struct in_addr *)broad); + } + if (ifa->ifa_family == AF_INET6) { + if (h->nlmsg_type == RTM_NEWADDR) { + /* Only consider valid addresses; we'll not get a + * notification from + * the kernel till IPv6 DAD has completed, but at init + * time, Quagga + * does query for and will receive all addresses. + */ + if (!(ifa->ifa_flags + & (IFA_F_DADFAILED | IFA_F_TENTATIVE))) + connected_add_ipv6( + ifp, flags, (struct in6_addr *)addr, + ifa->ifa_prefixlen, + (struct in6_addr *)broad, label); + } else + connected_delete_ipv6(ifp, (struct in6_addr *)addr, + ifa->ifa_prefixlen, + (struct in6_addr *)broad); + } + + return 0; } -int -netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +int netlink_link_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct ifinfomsg *ifi; - struct rtattr *tb[IFLA_MAX + 1]; - struct rtattr *linkinfo[IFLA_MAX + 1]; - struct interface *ifp; - char *name = NULL; - char *kind = NULL; - char *slave_kind = NULL; - struct zebra_ns *zns; - vrf_id_t vrf_id = VRF_DEFAULT; - zebra_iftype_t zif_type = ZEBRA_IF_OTHER; - zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE; - ifindex_t bridge_ifindex = IFINDEX_INTERNAL; - ifindex_t link_ifindex = IFINDEX_INTERNAL; - - - zns = zebra_ns_lookup (ns_id); - ifi = NLMSG_DATA (h); - - if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) - { - /* If this is not link add/delete message so print warning. */ - zlog_warn ("netlink_link_change: wrong kernel message %d", - h->nlmsg_type); - return 0; - } - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg)); - if (len < 0) - return -1; - - /* We are interested in some AF_BRIDGE notifications. */ - if (ifi->ifi_family == AF_BRIDGE) - return netlink_bridge_interface (h, len, ns_id, startup); - - /* Looking up interface name. */ - memset (tb, 0, sizeof tb); - memset (linkinfo, 0, sizeof linkinfo); - netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); + int len; + struct ifinfomsg *ifi; + struct rtattr *tb[IFLA_MAX + 1]; + struct rtattr *linkinfo[IFLA_MAX + 1]; + struct interface *ifp; + char *name = NULL; + char *kind = NULL; + char *slave_kind = NULL; + struct zebra_ns *zns; + vrf_id_t vrf_id = VRF_DEFAULT; + zebra_iftype_t zif_type = ZEBRA_IF_OTHER; + zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE; + ifindex_t bridge_ifindex = IFINDEX_INTERNAL; + ifindex_t link_ifindex = IFINDEX_INTERNAL; + + + zns = zebra_ns_lookup(ns_id); + ifi = NLMSG_DATA(h); + + if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) { + /* If this is not link add/delete message so print warning. */ + zlog_warn("netlink_link_change: wrong kernel message %d", + h->nlmsg_type); + return 0; + } + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg)); + if (len < 0) + return -1; + + /* We are interested in some AF_BRIDGE notifications. */ + if (ifi->ifi_family == AF_BRIDGE) + return netlink_bridge_interface(h, len, ns_id, startup); + + /* Looking up interface name. */ + memset(tb, 0, sizeof tb); + memset(linkinfo, 0, sizeof linkinfo); + netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); #ifdef IFLA_WIRELESS - /* check for wireless messages to ignore */ - if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__); - return 0; - } + /* check for wireless messages to ignore */ + if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: ignoring IFLA_WIRELESS message", + __func__); + return 0; + } #endif /* IFLA_WIRELESS */ - if (tb[IFLA_IFNAME] == NULL) - return -1; - name = (char *) RTA_DATA (tb[IFLA_IFNAME]); + if (tb[IFLA_IFNAME] == NULL) + return -1; + name = (char *)RTA_DATA(tb[IFLA_IFNAME]); - if (tb[IFLA_LINKINFO]) - { - parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); + if (tb[IFLA_LINKINFO]) { + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); - if (linkinfo[IFLA_INFO_KIND]) - kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); + if (linkinfo[IFLA_INFO_KIND]) + kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); #if HAVE_DECL_IFLA_INFO_SLAVE_KIND - if (linkinfo[IFLA_INFO_SLAVE_KIND]) - slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); + if (linkinfo[IFLA_INFO_SLAVE_KIND]) + slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); #endif - netlink_determine_zebra_iftype (kind, &zif_type); - } - - /* If linking to another interface, note it. */ - if (tb[IFLA_LINK]) - link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]); + netlink_determine_zebra_iftype(kind, &zif_type); + } - /* If VRF, create or update the VRF structure itself. */ - if (zif_type == ZEBRA_IF_VRF) - { - netlink_vrf_change(h, tb[IFLA_LINKINFO], name); - vrf_id = (vrf_id_t)ifi->ifi_index; - } + /* If linking to another interface, note it. */ + if (tb[IFLA_LINK]) + link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]); - /* See if interface is present. */ - ifp = if_lookup_by_name_per_ns (zns, name); + /* If VRF, create or update the VRF structure itself. */ + if (zif_type == ZEBRA_IF_VRF) { + netlink_vrf_change(h, tb[IFLA_LINKINFO], name); + vrf_id = (vrf_id_t)ifi->ifi_index; + } - if (h->nlmsg_type == RTM_NEWLINK) - { - if (tb[IFLA_MASTER]) - { - if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) - { - zif_slave_type = ZEBRA_IF_SLAVE_VRF; - vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); - } - else if (slave_kind && (strcmp(slave_kind, "bridge") == 0)) - { - zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE; - bridge_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); - } - else - zif_slave_type = ZEBRA_IF_SLAVE_OTHER; + /* See if interface is present. */ + ifp = if_lookup_by_name_per_ns(zns, name); + + if (h->nlmsg_type == RTM_NEWLINK) { + if (tb[IFLA_MASTER]) { + if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) { + zif_slave_type = ZEBRA_IF_SLAVE_VRF; + vrf_id = + *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); + } else if (slave_kind + && (strcmp(slave_kind, "bridge") == 0)) { + zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE; + bridge_ifindex = + *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); + } else + zif_slave_type = ZEBRA_IF_SLAVE_OTHER; + } + + if (ifp == NULL + || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + /* Add interface notification from kernel */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d " + "sl_type %d master %u flags 0x%x", + name, ifi->ifi_index, vrf_id, zif_type, + zif_slave_type, bridge_ifindex, + ifi->ifi_flags); + + if (ifp == NULL) { + /* unknown interface */ + ifp = if_get_by_name(name, vrf_id); + } else { + /* pre-configured interface, learnt now */ + if (ifp->vrf_id != vrf_id) + if_update_to_new_vrf(ifp, vrf_id); + } + + /* Update interface information. */ + set_ifindex(ifp, ifi->ifi_index, zns); + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (IS_ZEBRA_IF_VRF(ifp)) + SET_FLAG(ifp->status, + ZEBRA_INTERFACE_VRF_LOOPBACK); + ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]); + ifp->metric = 0; + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + + /* Set interface type */ + zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); + + /* Update link. */ + zebra_if_update_link(ifp, link_ifindex); + + netlink_interface_update_hw_addr(tb, ifp); + + /* Inform clients, install any configured addresses. */ + if_add_update(ifp); + + /* Extract and save L2 interface information, take + * additional actions. */ + netlink_interface_update_l2info( + ifp, linkinfo[IFLA_INFO_DATA], 1); + if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) + zebra_l2if_update_bridge_slave(ifp, + bridge_ifindex); + } else if (ifp->vrf_id != vrf_id) { + /* VRF change for an interface. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK vrf-change for %s(%u) " + "vrf_id %u -> %u flags 0x%x", + name, ifp->ifindex, ifp->vrf_id, vrf_id, + ifi->ifi_flags); + + if_handle_vrf_change(ifp, vrf_id); + } else { + int was_bridge_slave; + + /* Interface update. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK update for %s(%u) " + "sl_type %d master %u flags 0x%x", + name, ifp->ifindex, zif_slave_type, + bridge_ifindex, ifi->ifi_flags); + + set_ifindex(ifp, ifi->ifi_index, zns); + ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]); + ifp->metric = 0; + + /* Update interface type - NOTE: Only slave_type can + * change. */ + was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE(ifp); + zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); + + netlink_interface_update_hw_addr(tb, ifp); + + if (if_is_no_ptm_operative(ifp)) { + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (!if_is_no_ptm_operative(ifp)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "Intf %s(%u) has gone DOWN", + name, ifp->ifindex); + if_down(ifp); + } else if (if_is_operative(ifp)) { + /* Must notify client daemons of new + * interface status. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "Intf %s(%u) PTM up, notifying clients", + name, ifp->ifindex); + zebra_interface_up_update(ifp); + } + } else { + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (if_is_operative(ifp)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "Intf %s(%u) has come UP", + name, ifp->ifindex); + if_up(ifp); + } + } + + /* Extract and save L2 interface information, take + * additional actions. */ + netlink_interface_update_l2info( + ifp, linkinfo[IFLA_INFO_DATA], 0); + if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave) + zebra_l2if_update_bridge_slave(ifp, + bridge_ifindex); + } + } else { + /* Delete interface notification from kernel */ + if (ifp == NULL) { + zlog_warn("RTM_DELLINK for unknown interface %s(%u)", + name, ifi->ifi_index); + return 0; + } + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("RTM_DELLINK for %s(%u)", name, + ifp->ifindex); + + UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); + + /* Special handling for bridge or VxLAN interfaces. */ + if (IS_ZEBRA_IF_BRIDGE(ifp)) + zebra_l2_bridge_del(ifp); + else if (IS_ZEBRA_IF_VXLAN(ifp)) + zebra_l2_vxlanif_del(ifp); + + if (!IS_ZEBRA_IF_VRF(ifp)) + if_delete_update(ifp); } - if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - /* Add interface notification from kernel */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d " - "sl_type %d master %u flags 0x%x", - name, ifi->ifi_index, vrf_id, zif_type, zif_slave_type, - bridge_ifindex, ifi->ifi_flags); - - if (ifp == NULL) - { - /* unknown interface */ - ifp = if_get_by_name (name, vrf_id); - } - else - { - /* pre-configured interface, learnt now */ - if (ifp->vrf_id != vrf_id) - if_update_to_new_vrf (ifp, vrf_id); - } - - /* Update interface information. */ - set_ifindex(ifp, ifi->ifi_index, zns); - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (IS_ZEBRA_IF_VRF(ifp)) - SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); - ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 0; - ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; - - /* Set interface type */ - zebra_if_set_ziftype (ifp, zif_type, zif_slave_type); - - /* Update link. */ - zebra_if_update_link (ifp, link_ifindex); - - netlink_interface_update_hw_addr (tb, ifp); - - /* Inform clients, install any configured addresses. */ - if_add_update (ifp); - - /* Extract and save L2 interface information, take additional actions. */ - netlink_interface_update_l2info (ifp, linkinfo[IFLA_INFO_DATA], 1); - if (IS_ZEBRA_IF_BRIDGE_SLAVE (ifp)) - zebra_l2if_update_bridge_slave (ifp, bridge_ifindex); - } - else if (ifp->vrf_id != vrf_id) - { - /* VRF change for an interface. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_NEWLINK vrf-change for %s(%u) " - "vrf_id %u -> %u flags 0x%x", - name, ifp->ifindex, ifp->vrf_id, - vrf_id, ifi->ifi_flags); - - if_handle_vrf_change (ifp, vrf_id); - } - else - { - int was_bridge_slave; - - /* Interface update. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_NEWLINK update for %s(%u) " - "sl_type %d master %u flags 0x%x", - name, ifp->ifindex, zif_slave_type, - bridge_ifindex, ifi->ifi_flags); - - set_ifindex(ifp, ifi->ifi_index, zns); - ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 0; - - /* Update interface type - NOTE: Only slave_type can change. */ - was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE (ifp); - zebra_if_set_ziftype (ifp, zif_type, zif_slave_type); - - netlink_interface_update_hw_addr (tb, ifp); - - if (if_is_no_ptm_operative (ifp)) - { - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (!if_is_no_ptm_operative (ifp)) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Intf %s(%u) has gone DOWN", - name, ifp->ifindex); - if_down (ifp); - } - else if (if_is_operative (ifp)) - { - /* Must notify client daemons of new interface status. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Intf %s(%u) PTM up, notifying clients", - name, ifp->ifindex); - zebra_interface_up_update (ifp); - } - } - else - { - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (if_is_operative (ifp)) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Intf %s(%u) has come UP", name, ifp->ifindex); - if_up (ifp); - } - } - - /* Extract and save L2 interface information, take additional actions. */ - netlink_interface_update_l2info (ifp, linkinfo[IFLA_INFO_DATA], 0); - if (IS_ZEBRA_IF_BRIDGE_SLAVE (ifp) || was_bridge_slave) - zebra_l2if_update_bridge_slave (ifp, bridge_ifindex); - } - } - else - { - /* Delete interface notification from kernel */ - if (ifp == NULL) - { - zlog_warn ("RTM_DELLINK for unknown interface %s(%u)", - name, ifi->ifi_index); - return 0; - } - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_DELLINK for %s(%u)", name, ifp->ifindex); - - UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); - - /* Special handling for bridge or VxLAN interfaces. */ - if (IS_ZEBRA_IF_BRIDGE (ifp)) - zebra_l2_bridge_del (ifp); - else if (IS_ZEBRA_IF_VXLAN (ifp)) - zebra_l2_vxlanif_del (ifp); - - if (!IS_ZEBRA_IF_VRF(ifp)) - if_delete_update (ifp); - } - - return 0; + return 0; } /* Interface information read by netlink. */ -void -interface_list (struct zebra_ns *zns) +void interface_list(struct zebra_ns *zns) { - interface_lookup_netlink (zns); + interface_lookup_netlink(zns); } diff --git a/zebra/if_netlink.h b/zebra/if_netlink.h index 0c1b488fb..769c68a87 100644 --- a/zebra/if_netlink.h +++ b/zebra/if_netlink.h @@ -23,11 +23,11 @@ #ifdef HAVE_NETLINK -extern int netlink_interface_addr (struct sockaddr_nl *snl, - struct nlmsghdr *h, ns_id_t ns_id, int startup); -extern int netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup); -extern int interface_lookup_netlink (struct zebra_ns *zns); +extern int netlink_interface_addr(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup); +extern int netlink_link_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup); +extern int interface_lookup_netlink(struct zebra_ns *zns); #endif /* HAVE_NETLINK */ diff --git a/zebra/if_sysctl.c b/zebra/if_sysctl.c index dbf5abd12..99b0f9d94 100644 --- a/zebra/if_sysctl.c +++ b/zebra/if_sysctl.c @@ -36,124 +36,101 @@ #include "zebra/kernel_socket.h" #include "zebra/rib.h" -void -ifstat_update_sysctl (void) +void ifstat_update_sysctl(void) { - caddr_t ref, buf, end; - size_t bufsiz; - struct if_msghdr *ifm; - struct interface *ifp; + caddr_t ref, buf, end; + size_t bufsiz; + struct if_msghdr *ifm; + struct interface *ifp; #define MIBSIZ 6 - int mib[MIBSIZ] = - { - CTL_NET, - PF_ROUTE, - 0, - 0, /* AF_INET & AF_INET6 */ - NET_RT_IFLIST, - 0 - }; - - /* Query buffer size. */ - if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) - { - zlog_warn ("sysctl() error by %s", safe_strerror (errno)); - return; - } - - /* We free this memory at the end of this function. */ - ref = buf = XMALLOC (MTYPE_TMP, bufsiz); - - /* Fetch interface informations into allocated buffer. */ - if (sysctl (mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) - { - zlog_warn("sysctl error by %s", safe_strerror(errno)); - XFREE(MTYPE_TMP, ref); - return; - } - - /* Parse both interfaces and addresses. */ - for (end = buf + bufsiz; buf < end; buf += ifm->ifm_msglen) - { - ifm = (struct if_msghdr *) buf; - if (ifm->ifm_type == RTM_IFINFO) - { - ifp = if_lookup_by_index (ifm->ifm_index, VRF_DEFAULT); - if (ifp) - ifp->stats = ifm->ifm_data; + int mib[MIBSIZ] = { + CTL_NET, PF_ROUTE, 0, 0, /* AF_INET & AF_INET6 */ + NET_RT_IFLIST, 0}; + + /* Query buffer size. */ + if (sysctl(mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) { + zlog_warn("sysctl() error by %s", safe_strerror(errno)); + return; } - } - /* Free sysctl buffer. */ - XFREE (MTYPE_TMP, ref); + /* We free this memory at the end of this function. */ + ref = buf = XMALLOC(MTYPE_TMP, bufsiz); - return; + /* Fetch interface informations into allocated buffer. */ + if (sysctl(mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) { + zlog_warn("sysctl error by %s", safe_strerror(errno)); + XFREE(MTYPE_TMP, ref); + return; + } + + /* Parse both interfaces and addresses. */ + for (end = buf + bufsiz; buf < end; buf += ifm->ifm_msglen) { + ifm = (struct if_msghdr *)buf; + if (ifm->ifm_type == RTM_IFINFO) { + ifp = if_lookup_by_index(ifm->ifm_index, VRF_DEFAULT); + if (ifp) + ifp->stats = ifm->ifm_data; + } + } + + /* Free sysctl buffer. */ + XFREE(MTYPE_TMP, ref); + + return; } /* Interface listing up function using sysctl(). */ -void -interface_list (struct zebra_ns *zns) +void interface_list(struct zebra_ns *zns) { - caddr_t ref, buf, end; - size_t bufsiz; - struct if_msghdr *ifm; + caddr_t ref, buf, end; + size_t bufsiz; + struct if_msghdr *ifm; #define MIBSIZ 6 - int mib[MIBSIZ] = - { - CTL_NET, - PF_ROUTE, - 0, - 0, /* AF_INET & AF_INET6 */ - NET_RT_IFLIST, - 0 - }; - - if (zns->ns_id != NS_DEFAULT) - { - zlog_warn ("interface_list: ignore NS %u", zns->ns_id); - return; - } - - /* Query buffer size. */ - if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) - { - zlog_warn("sysctl() error by %s", safe_strerror(errno)); - return; - } - - /* We free this memory at the end of this function. */ - ref = buf = XMALLOC (MTYPE_TMP, bufsiz); - - /* Fetch interface informations into allocated buffer. */ - if (sysctl (mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) - { - zlog_warn("sysctl error by %s", safe_strerror(errno)); - return; - } - - /* Parse both interfaces and addresses. */ - for (end = buf + bufsiz; buf < end; buf += ifm->ifm_msglen) - { - ifm = (struct if_msghdr *) buf; - - switch (ifm->ifm_type) - { - case RTM_IFINFO: - ifm_read (ifm); - break; - case RTM_NEWADDR: - ifam_read ((struct ifa_msghdr *) ifm); - break; - default: - zlog_info ("interfaces_list(): unexpected message type"); - XFREE (MTYPE_TMP, ref); - return; - break; + int mib[MIBSIZ] = { + CTL_NET, PF_ROUTE, 0, 0, /* AF_INET & AF_INET6 */ + NET_RT_IFLIST, 0}; + + if (zns->ns_id != NS_DEFAULT) { + zlog_warn("interface_list: ignore NS %u", zns->ns_id); + return; + } + + /* Query buffer size. */ + if (sysctl(mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) { + zlog_warn("sysctl() error by %s", safe_strerror(errno)); + return; + } + + /* We free this memory at the end of this function. */ + ref = buf = XMALLOC(MTYPE_TMP, bufsiz); + + /* Fetch interface informations into allocated buffer. */ + if (sysctl(mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) { + zlog_warn("sysctl error by %s", safe_strerror(errno)); + return; + } + + /* Parse both interfaces and addresses. */ + for (end = buf + bufsiz; buf < end; buf += ifm->ifm_msglen) { + ifm = (struct if_msghdr *)buf; + + switch (ifm->ifm_type) { + case RTM_IFINFO: + ifm_read(ifm); + break; + case RTM_NEWADDR: + ifam_read((struct ifa_msghdr *)ifm); + break; + default: + zlog_info("interfaces_list(): unexpected message type"); + XFREE(MTYPE_TMP, ref); + return; + break; + } } - } - /* Free sysctl buffer. */ - XFREE (MTYPE_TMP, ref); + /* Free sysctl buffer. */ + XFREE(MTYPE_TMP, ref); } diff --git a/zebra/interface.c b/zebra/interface.c index 9618e9bb1..26b243382 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -51,287 +51,280 @@ #define ZEBRA_PTM_SUPPORT -#if defined (HAVE_RTADV) +#if defined(HAVE_RTADV) /* Order is intentional. Matches RFC4191. This array is also used for command matching, so only modify with care. */ -const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 }; +const char *rtadv_pref_strs[] = {"medium", "high", "INVALID", "low", 0}; #endif /* HAVE_RTADV */ -static void if_down_del_nbr_connected (struct interface *ifp); +static void if_down_del_nbr_connected(struct interface *ifp); -static void -zebra_if_node_destroy (route_table_delegate_t *delegate, - struct route_table *table, struct route_node *node) +static void zebra_if_node_destroy(route_table_delegate_t *delegate, + struct route_table *table, + struct route_node *node) { - if (node->info) - list_delete (node->info); - route_node_destroy (delegate, table, node); + if (node->info) + list_delete(node->info); + route_node_destroy(delegate, table, node); } route_table_delegate_t zebra_if_table_delegate = { - .create_node = route_node_create, - .destroy_node = zebra_if_node_destroy -}; + .create_node = route_node_create, + .destroy_node = zebra_if_node_destroy}; /* Called when new interface is added. */ -static int -if_zebra_new_hook (struct interface *ifp) -{ - struct zebra_if *zebra_if; - - zebra_if = XCALLOC (MTYPE_TMP, sizeof (struct zebra_if)); - - zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC; - zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF; - zebra_ptm_if_init(zebra_if); - - ifp->ptm_enable = zebra_ptm_get_enable_state(); -#if defined (HAVE_RTADV) - { - /* Set default router advertise values. */ - struct rtadvconf *rtadv; - - rtadv = &zebra_if->rtadv; - - rtadv->AdvSendAdvertisements = 0; - rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL; - rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL; - rtadv->AdvIntervalTimer = 0; - rtadv->AdvManagedFlag = 0; - rtadv->AdvOtherConfigFlag = 0; - rtadv->AdvHomeAgentFlag = 0; - rtadv->AdvLinkMTU = 0; - rtadv->AdvReachableTime = 0; - rtadv->AdvRetransTimer = 0; - rtadv->AdvCurHopLimit = 0; - rtadv->AdvDefaultLifetime = -1; /* derive from MaxRtrAdvInterval */ - rtadv->HomeAgentPreference = 0; - rtadv->HomeAgentLifetime = -1; /* derive from AdvDefaultLifetime */ - rtadv->AdvIntervalOption = 0; - rtadv->DefaultPreference = RTADV_PREF_MEDIUM; - - rtadv->AdvPrefixList = list_new (); - } +static int if_zebra_new_hook(struct interface *ifp) +{ + struct zebra_if *zebra_if; + + zebra_if = XCALLOC(MTYPE_TMP, sizeof(struct zebra_if)); + + zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC; + zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF; + zebra_ptm_if_init(zebra_if); + + ifp->ptm_enable = zebra_ptm_get_enable_state(); +#if defined(HAVE_RTADV) + { + /* Set default router advertise values. */ + struct rtadvconf *rtadv; + + rtadv = &zebra_if->rtadv; + + rtadv->AdvSendAdvertisements = 0; + rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL; + rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL; + rtadv->AdvIntervalTimer = 0; + rtadv->AdvManagedFlag = 0; + rtadv->AdvOtherConfigFlag = 0; + rtadv->AdvHomeAgentFlag = 0; + rtadv->AdvLinkMTU = 0; + rtadv->AdvReachableTime = 0; + rtadv->AdvRetransTimer = 0; + rtadv->AdvCurHopLimit = 0; + rtadv->AdvDefaultLifetime = + -1; /* derive from MaxRtrAdvInterval */ + rtadv->HomeAgentPreference = 0; + rtadv->HomeAgentLifetime = + -1; /* derive from AdvDefaultLifetime */ + rtadv->AdvIntervalOption = 0; + rtadv->DefaultPreference = RTADV_PREF_MEDIUM; + + rtadv->AdvPrefixList = list_new(); + } #endif /* HAVE_RTADV */ - /* Initialize installed address chains tree. */ - zebra_if->ipv4_subnets = route_table_init_with_delegate (&zebra_if_table_delegate); + /* Initialize installed address chains tree. */ + zebra_if->ipv4_subnets = + route_table_init_with_delegate(&zebra_if_table_delegate); - ifp->info = zebra_if; + ifp->info = zebra_if; - zebra_vrf_static_route_interface_fixup (ifp); - return 0; + zebra_vrf_static_route_interface_fixup(ifp); + return 0; } /* Called when interface is deleted. */ -static int -if_zebra_delete_hook (struct interface *ifp) +static int if_zebra_delete_hook(struct interface *ifp) { - struct zebra_if *zebra_if; - - if (ifp->info) - { - zebra_if = ifp->info; + struct zebra_if *zebra_if; - /* Free installed address chains tree. */ - if (zebra_if->ipv4_subnets) - route_table_finish (zebra_if->ipv4_subnets); - #if defined (HAVE_RTADV) + if (ifp->info) { + zebra_if = ifp->info; - struct rtadvconf *rtadv; + /* Free installed address chains tree. */ + if (zebra_if->ipv4_subnets) + route_table_finish(zebra_if->ipv4_subnets); +#if defined(HAVE_RTADV) - rtadv = &zebra_if->rtadv; - list_free (rtadv->AdvPrefixList); - #endif /* HAVE_RTADV */ + struct rtadvconf *rtadv; - XFREE (MTYPE_TMP, zebra_if); - } + rtadv = &zebra_if->rtadv; + list_free(rtadv->AdvPrefixList); +#endif /* HAVE_RTADV */ - return 0; + XFREE(MTYPE_TMP, zebra_if); + } + + return 0; } /* Build the table key */ -static void -if_build_key (u_int32_t ifindex, struct prefix *p) +static void if_build_key(u_int32_t ifindex, struct prefix *p) { - p->family = AF_INET; - p->prefixlen = IPV4_MAX_BITLEN; - p->u.prefix4.s_addr = ifindex; + p->family = AF_INET; + p->prefixlen = IPV4_MAX_BITLEN; + p->u.prefix4.s_addr = ifindex; } /* Link an interface in a per NS interface tree */ -struct interface * -if_link_per_ns (struct zebra_ns *ns, struct interface *ifp) +struct interface *if_link_per_ns(struct zebra_ns *ns, struct interface *ifp) { - struct prefix p; - struct route_node *rn; + struct prefix p; + struct route_node *rn; - if (ifp->ifindex == IFINDEX_INTERNAL) - return NULL; + if (ifp->ifindex == IFINDEX_INTERNAL) + return NULL; - if_build_key (ifp->ifindex, &p); - rn = route_node_get (ns->if_table, &p); - if (rn->info) - { - ifp = (struct interface *)rn->info; - route_unlock_node (rn); /* get */ - return ifp; - } + if_build_key(ifp->ifindex, &p); + rn = route_node_get(ns->if_table, &p); + if (rn->info) { + ifp = (struct interface *)rn->info; + route_unlock_node(rn); /* get */ + return ifp; + } - rn->info = ifp; - ifp->node = rn; + rn->info = ifp; + ifp->node = rn; - return ifp; + return ifp; } /* Delete a VRF. This is called in vrf_terminate(). */ -void -if_unlink_per_ns (struct interface *ifp) +void if_unlink_per_ns(struct interface *ifp) { - ifp->node->info = NULL; - route_unlock_node(ifp->node); - ifp->node = NULL; + ifp->node->info = NULL; + route_unlock_node(ifp->node); + ifp->node = NULL; } /* Look up an interface by identifier within a NS */ -struct interface * -if_lookup_by_index_per_ns (struct zebra_ns *ns, u_int32_t ifindex) -{ - struct prefix p; - struct route_node *rn; - struct interface *ifp = NULL; - - if_build_key (ifindex, &p); - rn = route_node_lookup (ns->if_table, &p); - if (rn) - { - ifp = (struct interface *)rn->info; - route_unlock_node (rn); /* lookup */ - } - return ifp; +struct interface *if_lookup_by_index_per_ns(struct zebra_ns *ns, + u_int32_t ifindex) +{ + struct prefix p; + struct route_node *rn; + struct interface *ifp = NULL; + + if_build_key(ifindex, &p); + rn = route_node_lookup(ns->if_table, &p); + if (rn) { + ifp = (struct interface *)rn->info; + route_unlock_node(rn); /* lookup */ + } + return ifp; } /* Look up an interface by name within a NS */ -struct interface * -if_lookup_by_name_per_ns (struct zebra_ns *ns, const char *ifname) +struct interface *if_lookup_by_name_per_ns(struct zebra_ns *ns, + const char *ifname) { - struct route_node *rn; - struct interface *ifp; + struct route_node *rn; + struct interface *ifp; - for (rn = route_top (ns->if_table); rn; rn = route_next (rn)) - { - ifp = (struct interface *)rn->info; - if (ifp && strcmp (ifp->name, ifname) == 0) - return (ifp); - } + for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) { + ifp = (struct interface *)rn->info; + if (ifp && strcmp(ifp->name, ifname) == 0) + return (ifp); + } - return NULL; + return NULL; } -const char * -ifindex2ifname_per_ns (struct zebra_ns *zns, unsigned int ifindex) +const char *ifindex2ifname_per_ns(struct zebra_ns *zns, unsigned int ifindex) { - struct interface *ifp; + struct interface *ifp; - return ((ifp = if_lookup_by_index_per_ns (zns, ifindex)) != NULL) ? - ifp->name : "unknown"; + return ((ifp = if_lookup_by_index_per_ns(zns, ifindex)) != NULL) + ? ifp->name + : "unknown"; } /* Tie an interface address to its derived subnet list of addresses. */ -int -if_subnet_add (struct interface *ifp, struct connected *ifc) -{ - struct route_node *rn; - struct zebra_if *zebra_if; - struct prefix cp; - struct list *addr_list; - - assert (ifp && ifp->info && ifc); - zebra_if = ifp->info; - - /* Get address derived subnet node and associated address list, while marking - address secondary attribute appropriately. */ - cp = *ifc->address; - apply_mask (&cp); - rn = route_node_get (zebra_if->ipv4_subnets, &cp); - - if ((addr_list = rn->info)) - SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY); - else - { - UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY); - rn->info = addr_list = list_new (); - route_lock_node (rn); - } - - /* Tie address at the tail of address list. */ - listnode_add (addr_list, ifc); - - /* Return list element count. */ - return (addr_list->count); +int if_subnet_add(struct interface *ifp, struct connected *ifc) +{ + struct route_node *rn; + struct zebra_if *zebra_if; + struct prefix cp; + struct list *addr_list; + + assert(ifp && ifp->info && ifc); + zebra_if = ifp->info; + + /* Get address derived subnet node and associated address list, while + marking + address secondary attribute appropriately. */ + cp = *ifc->address; + apply_mask(&cp); + rn = route_node_get(zebra_if->ipv4_subnets, &cp); + + if ((addr_list = rn->info)) + SET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY); + else { + UNSET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY); + rn->info = addr_list = list_new(); + route_lock_node(rn); + } + + /* Tie address at the tail of address list. */ + listnode_add(addr_list, ifc); + + /* Return list element count. */ + return (addr_list->count); } /* Untie an interface address from its derived subnet list of addresses. */ -int -if_subnet_delete (struct interface *ifp, struct connected *ifc) -{ - struct route_node *rn; - struct zebra_if *zebra_if; - struct list *addr_list; - - assert (ifp && ifp->info && ifc); - zebra_if = ifp->info; - - /* Get address derived subnet node. */ - rn = route_node_lookup (zebra_if->ipv4_subnets, ifc->address); - if (! (rn && rn->info)) - { - zlog_warn("Trying to remove an address from an unknown subnet." - " (please report this bug)"); - return -1; - } - route_unlock_node (rn); - - /* Untie address from subnet's address list. */ - addr_list = rn->info; - - /* Deleting an address that is not registered is a bug. - * In any case, we shouldn't decrement the lock counter if the address - * is unknown. */ - if (!listnode_lookup(addr_list, ifc)) - { - zlog_warn("Trying to remove an address from a subnet where it is not" - " currently registered. (please report this bug)"); - return -1; - } - - listnode_delete (addr_list, ifc); - route_unlock_node (rn); - - /* Return list element count, if not empty. */ - if (addr_list->count) - { - /* If deleted address is primary, mark subsequent one as such and distribute. */ - if (! CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY)) - { - ifc = listgetdata ((struct listnode *)listhead (addr_list)); - zebra_interface_address_delete_update (ifp, ifc); - UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY); - /* XXX: Linux kernel removes all the secondary addresses when the primary - * address is removed. We could try to work around that, though this is - * non-trivial. */ - zebra_interface_address_add_update (ifp, ifc); - } - - return addr_list->count; - } - - /* Otherwise, free list and route node. */ - list_free (addr_list); - rn->info = NULL; - route_unlock_node (rn); - - return 0; +int if_subnet_delete(struct interface *ifp, struct connected *ifc) +{ + struct route_node *rn; + struct zebra_if *zebra_if; + struct list *addr_list; + + assert(ifp && ifp->info && ifc); + zebra_if = ifp->info; + + /* Get address derived subnet node. */ + rn = route_node_lookup(zebra_if->ipv4_subnets, ifc->address); + if (!(rn && rn->info)) { + zlog_warn( + "Trying to remove an address from an unknown subnet." + " (please report this bug)"); + return -1; + } + route_unlock_node(rn); + + /* Untie address from subnet's address list. */ + addr_list = rn->info; + + /* Deleting an address that is not registered is a bug. + * In any case, we shouldn't decrement the lock counter if the address + * is unknown. */ + if (!listnode_lookup(addr_list, ifc)) { + zlog_warn( + "Trying to remove an address from a subnet where it is not" + " currently registered. (please report this bug)"); + return -1; + } + + listnode_delete(addr_list, ifc); + route_unlock_node(rn); + + /* Return list element count, if not empty. */ + if (addr_list->count) { + /* If deleted address is primary, mark subsequent one as such + * and distribute. */ + if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) { + ifc = listgetdata( + (struct listnode *)listhead(addr_list)); + zebra_interface_address_delete_update(ifp, ifc); + UNSET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY); + /* XXX: Linux kernel removes all the secondary addresses + * when the primary + * address is removed. We could try to work around that, + * though this is + * non-trivial. */ + zebra_interface_address_add_update(ifp, ifc); + } + + return addr_list->count; + } + + /* Otherwise, free list and route node. */ + list_free(addr_list); + rn->info = NULL; + route_unlock_node(rn); + + return 0; } /* if_flags_mangle: A place for hacks that require mangling @@ -340,10 +333,10 @@ if_subnet_delete (struct interface *ifp, struct connected *ifc) * ******************** Solaris flags hacks ************************** * * Solaris IFF_UP flag reflects only the primary interface as the - * routing socket only sends IFINFO for the primary interface. Hence - * ~IFF_UP does not per se imply all the logical interfaces are also + * routing socket only sends IFINFO for the primary interface. Hence + * ~IFF_UP does not per se imply all the logical interfaces are also * down - which we only know of as addresses. Instead we must determine - * whether the interface really is up or not according to how many + * whether the interface really is up or not according to how many * addresses are still attached. (Solaris always sends RTM_DELADDR if * an interface, logical or not, goes ~IFF_UP). * @@ -358,19 +351,18 @@ if_subnet_delete (struct interface *ifp, struct connected *ifc) * interface will affect only the primary interface/address on Solaris. ************************End Solaris flags hacks *********************** */ -static void -if_flags_mangle (struct interface *ifp, uint64_t *newflags) +static void if_flags_mangle(struct interface *ifp, uint64_t *newflags) { #ifdef SUNOS_5 - struct zebra_if *zif = ifp->info; - - zif->primary_state = *newflags & (IFF_UP & 0xff); - - if (CHECK_FLAG (zif->primary_state, IFF_UP) - || listcount(ifp->connected) > 0) - SET_FLAG (*newflags, IFF_UP); - else - UNSET_FLAG (*newflags, IFF_UP); + struct zebra_if *zif = ifp->info; + + zif->primary_state = *newflags & (IFF_UP & 0xff); + + if (CHECK_FLAG(zif->primary_state, IFF_UP) + || listcount(ifp->connected) > 0) + SET_FLAG(*newflags, IFF_UP); + else + UNSET_FLAG(*newflags, IFF_UP); #endif /* SUNOS_5 */ } @@ -380,1034 +372,1003 @@ if_flags_mangle (struct interface *ifp, uint64_t *newflags) * * newflags should be the raw value, as obtained from the OS. */ -void -if_flags_update (struct interface *ifp, uint64_t newflags) -{ - if_flags_mangle (ifp, &newflags); - - if (if_is_no_ptm_operative (ifp)) - { - /* operative -> inoperative? */ - ifp->flags = newflags; - if (!if_is_operative (ifp)) - if_down (ifp); - } - else - { - /* inoperative -> operative? */ - ifp->flags = newflags; - if (if_is_operative (ifp)) - if_up (ifp); - } +void if_flags_update(struct interface *ifp, uint64_t newflags) +{ + if_flags_mangle(ifp, &newflags); + + if (if_is_no_ptm_operative(ifp)) { + /* operative -> inoperative? */ + ifp->flags = newflags; + if (!if_is_operative(ifp)) + if_down(ifp); + } else { + /* inoperative -> operative? */ + ifp->flags = newflags; + if (if_is_operative(ifp)) + if_up(ifp); + } } /* Wake up configured address if it is not in current kernel address. */ -static void -if_addr_wakeup (struct interface *ifp) -{ - struct listnode *node, *nnode; - struct connected *ifc; - struct prefix *p; - int ret; - - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc)) - { - p = ifc->address; - - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED) - && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED)) - { - /* Address check. */ - if (p->family == AF_INET) - { - if (! if_is_up (ifp)) - { - /* Assume zebra is configured like following: - * - * interface gre0 - * ip addr 192.0.2.1/24 - * ! - * - * As soon as zebra becomes first aware that gre0 exists in the - * kernel, it will set gre0 up and configure its addresses. - * - * (This may happen at startup when the interface already exists - * or during runtime when the interface is added to the kernel) - * - * XXX: IRDP code is calling here via if_add_update - this seems - * somewhat weird. - * XXX: RUNNING is not a settable flag on any system - * I (paulj) am aware of. - */ - if_set_flags (ifp, IFF_UP | IFF_RUNNING); - if_refresh (ifp); - } - - ret = if_set_prefix (ifp, ifc); - if (ret < 0) - { - zlog_warn ("Can't set interface's address: %s", - safe_strerror(errno)); - continue; - } +static void if_addr_wakeup(struct interface *ifp) +{ + struct listnode *node, *nnode; + struct connected *ifc; + struct prefix *p; + int ret; - SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - /* The address will be advertised to zebra clients when the notification - * from the kernel has been received. - * It will also be added to the interface's subnet list then. */ - } - if (p->family == AF_INET6) - { - if (! if_is_up (ifp)) - { - /* See long comment above */ - if_set_flags (ifp, IFF_UP | IFF_RUNNING); - if_refresh (ifp); - } + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, ifc)) { + p = ifc->address; - ret = if_prefix_add_ipv6 (ifp, ifc); - if (ret < 0) - { - zlog_warn ("Can't set interface's address: %s", - safe_strerror(errno)); - continue; + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED) + && !CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)) { + /* Address check. */ + if (p->family == AF_INET) { + if (!if_is_up(ifp)) { + /* Assume zebra is configured like + * following: + * + * interface gre0 + * ip addr 192.0.2.1/24 + * ! + * + * As soon as zebra becomes first aware + * that gre0 exists in the + * kernel, it will set gre0 up and + * configure its addresses. + * + * (This may happen at startup when the + * interface already exists + * or during runtime when the interface + * is added to the kernel) + * + * XXX: IRDP code is calling here via + * if_add_update - this seems + * somewhat weird. + * XXX: RUNNING is not a settable flag + * on any system + * I (paulj) am aware of. + */ + if_set_flags(ifp, IFF_UP | IFF_RUNNING); + if_refresh(ifp); + } + + ret = if_set_prefix(ifp, ifc); + if (ret < 0) { + zlog_warn( + "Can't set interface's address: %s", + safe_strerror(errno)); + continue; + } + + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra + * clients when the notification + * from the kernel has been received. + * It will also be added to the interface's + * subnet list then. */ + } + if (p->family == AF_INET6) { + if (!if_is_up(ifp)) { + /* See long comment above */ + if_set_flags(ifp, IFF_UP | IFF_RUNNING); + if_refresh(ifp); + } + + ret = if_prefix_add_ipv6(ifp, ifc); + if (ret < 0) { + zlog_warn( + "Can't set interface's address: %s", + safe_strerror(errno)); + continue; + } + + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra + * clients when the notification + * from the kernel has been received. */ + } } - - SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - /* The address will be advertised to zebra clients when the notification - * from the kernel has been received. */ - } } - } } /* Handle interface addition */ -void -if_add_update (struct interface *ifp) +void if_add_update(struct interface *ifp) { - struct zebra_if *if_data; + struct zebra_if *if_data; - if_link_per_ns(zebra_ns_lookup (NS_DEFAULT), ifp); + if_link_per_ns(zebra_ns_lookup(NS_DEFAULT), ifp); - if_data = ifp->info; - assert(if_data); + if_data = ifp->info; + assert(if_data); - if (if_data->multicast == IF_ZEBRA_MULTICAST_ON) - if_set_flags (ifp, IFF_MULTICAST); - else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF) - if_unset_flags (ifp, IFF_MULTICAST); + if (if_data->multicast == IF_ZEBRA_MULTICAST_ON) + if_set_flags(ifp, IFF_MULTICAST); + else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF) + if_unset_flags(ifp, IFF_MULTICAST); - zebra_ptm_if_set_ptm_state(ifp, if_data); + zebra_ptm_if_set_ptm_state(ifp, if_data); - zebra_interface_add_update (ifp); + zebra_interface_add_update(ifp); - if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - SET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE); + if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + SET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE); - if (if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("interface %s vrf %u index %d is shutdown. " - "Won't wake it up.", - ifp->name, ifp->vrf_id, ifp->ifindex); - return; - } + if (if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "interface %s vrf %u index %d is shutdown. " + "Won't wake it up.", + ifp->name, ifp->vrf_id, ifp->ifindex); + return; + } - if_addr_wakeup (ifp); + if_addr_wakeup(ifp); - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("interface %s vrf %u index %d becomes active.", - ifp->name, ifp->vrf_id, ifp->ifindex); - } - else - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("interface %s vrf %u index %d is added.", - ifp->name, ifp->vrf_id, ifp->ifindex); - } + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "interface %s vrf %u index %d becomes active.", + ifp->name, ifp->vrf_id, ifp->ifindex); + } else { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("interface %s vrf %u index %d is added.", + ifp->name, ifp->vrf_id, ifp->ifindex); + } } /* Install connected routes corresponding to an interface. */ -static void -if_install_connected (struct interface *ifp) -{ - struct listnode *node; - struct listnode *next; - struct connected *ifc; - struct prefix *p; - - if (ifp->connected) - { - for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc)) - { - if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) - zebra_interface_address_add_update (ifp, ifc); - - p = ifc->address; - if (p->family == AF_INET) - connected_up_ipv4 (ifp, ifc); - else if (p->family == AF_INET6) - connected_up_ipv6 (ifp, ifc); +static void if_install_connected(struct interface *ifp) +{ + struct listnode *node; + struct listnode *next; + struct connected *ifc; + struct prefix *p; + + if (ifp->connected) { + for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) { + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + zebra_interface_address_add_update(ifp, ifc); + + p = ifc->address; + if (p->family == AF_INET) + connected_up_ipv4(ifp, ifc); + else if (p->family == AF_INET6) + connected_up_ipv6(ifp, ifc); + } } - } } /* Uninstall connected routes corresponding to an interface. */ -static void -if_uninstall_connected (struct interface *ifp) -{ - struct listnode *node; - struct listnode *next; - struct connected *ifc; - struct prefix *p; - - if (ifp->connected) - { - for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc)) - { - p = ifc->address; - zebra_interface_address_delete_update (ifp, ifc); - - if (p->family == AF_INET) - connected_down_ipv4 (ifp, ifc); - else if (p->family == AF_INET6) - connected_down_ipv6 (ifp, ifc); +static void if_uninstall_connected(struct interface *ifp) +{ + struct listnode *node; + struct listnode *next; + struct connected *ifc; + struct prefix *p; + + if (ifp->connected) { + for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) { + p = ifc->address; + zebra_interface_address_delete_update(ifp, ifc); + + if (p->family == AF_INET) + connected_down_ipv4(ifp, ifc); + else if (p->family == AF_INET6) + connected_down_ipv6(ifp, ifc); + } } - } } /* Uninstall and delete connected routes corresponding to an interface. */ /* TODO - Check why IPv4 handling here is different from install or if_down */ -static void -if_delete_connected (struct interface *ifp) -{ - struct connected *ifc; - struct prefix *p; - struct route_node *rn; - struct zebra_if *zebra_if; - - zebra_if = ifp->info; - - if (ifp->connected) - { - struct listnode *node; - struct listnode *last = NULL; - - while ((node = (last ? last->next : listhead (ifp->connected)))) - { - ifc = listgetdata (node); - p = ifc->address; - - if (p->family == AF_INET - && (rn = route_node_lookup (zebra_if->ipv4_subnets, p))) - { - struct listnode *anode; - struct listnode *next; - struct listnode *first; - struct list *addr_list; - - route_unlock_node (rn); - addr_list = (struct list *) rn->info; - - /* Remove addresses, secondaries first. */ - first = listhead (addr_list); - for (anode = first->next; anode || first; anode = next) - { - if (!anode) - { - anode = first; - first = NULL; - } - next = anode->next; - - ifc = listgetdata (anode); - connected_down_ipv4 (ifp, ifc); - - /* XXX: We have to send notifications here explicitly, because we destroy - * the ifc before receiving the notification about the address being deleted. - */ - zebra_interface_address_delete_update (ifp, ifc); - - UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - - /* Remove from subnet chain. */ - list_delete_node (addr_list, anode); - route_unlock_node (rn); - - /* Remove from interface address list (unconditionally). */ - if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - { - listnode_delete (ifp->connected, ifc); - connected_free (ifc); - } - else - last = node; - } - - /* Free chain list and respective route node. */ - list_delete (addr_list); - rn->info = NULL; - route_unlock_node (rn); - } - else if (p->family == AF_INET6) - { - connected_down_ipv6 (ifp, ifc); - - zebra_interface_address_delete_update (ifp, ifc); - - UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - last = node; - else - { - listnode_delete (ifp->connected, ifc); - connected_free (ifc); +static void if_delete_connected(struct interface *ifp) +{ + struct connected *ifc; + struct prefix *p; + struct route_node *rn; + struct zebra_if *zebra_if; + + zebra_if = ifp->info; + + if (ifp->connected) { + struct listnode *node; + struct listnode *last = NULL; + + while ((node = (last ? last->next + : listhead(ifp->connected)))) { + ifc = listgetdata(node); + p = ifc->address; + + if (p->family == AF_INET + && (rn = route_node_lookup(zebra_if->ipv4_subnets, + p))) { + struct listnode *anode; + struct listnode *next; + struct listnode *first; + struct list *addr_list; + + route_unlock_node(rn); + addr_list = (struct list *)rn->info; + + /* Remove addresses, secondaries first. */ + first = listhead(addr_list); + for (anode = first->next; anode || first; + anode = next) { + if (!anode) { + anode = first; + first = NULL; + } + next = anode->next; + + ifc = listgetdata(anode); + connected_down_ipv4(ifp, ifc); + + /* XXX: We have to send notifications + * here explicitly, because we destroy + * the ifc before receiving the + * notification about the address being + * deleted. + */ + zebra_interface_address_delete_update( + ifp, ifc); + + UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL); + UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + + /* Remove from subnet chain. */ + list_delete_node(addr_list, anode); + route_unlock_node(rn); + + /* Remove from interface address list + * (unconditionally). */ + if (!CHECK_FLAG(ifc->conf, + ZEBRA_IFC_CONFIGURED)) { + listnode_delete(ifp->connected, + ifc); + connected_free(ifc); + } else + last = node; + } + + /* Free chain list and respective route node. */ + list_delete(addr_list); + rn->info = NULL; + route_unlock_node(rn); + } else if (p->family == AF_INET6) { + connected_down_ipv6(ifp, ifc); + + zebra_interface_address_delete_update(ifp, ifc); + + UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL); + UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) + last = node; + else { + listnode_delete(ifp->connected, ifc); + connected_free(ifc); + } + } else { + last = node; + } } - } - else - { - last = node; - } } - } } /* Handle an interface delete event */ -void -if_delete_update (struct interface *ifp) +void if_delete_update(struct interface *ifp) { - struct zebra_if *zif; - - if (if_is_up(ifp)) - { - zlog_err ("interface %s vrf %u index %d is still up while being deleted.", - ifp->name, ifp->vrf_id, ifp->ifindex); - return; - } - - /* Mark interface as inactive */ - UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE); - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("interface %s vrf %u index %d is now inactive.", - ifp->name, ifp->vrf_id, ifp->ifindex); - - /* Delete connected routes from the kernel. */ - if_delete_connected (ifp); - - /* Send out notification on interface delete. */ - zebra_interface_delete_update (ifp); + struct zebra_if *zif; - if_unlink_per_ns(ifp); - - /* Update ifindex after distributing the delete message. This is in - case any client needs to have the old value of ifindex available - while processing the deletion. Each client daemon is responsible - for setting ifindex to IFINDEX_INTERNAL after processing the - interface deletion message. */ - ifp->ifindex = IFINDEX_INTERNAL; - ifp->node = NULL; - - /* if the ifp is in a vrf, move it to default so vrf can be deleted if desired */ - if (ifp->vrf_id) - if_handle_vrf_change (ifp, VRF_DEFAULT); + if (if_is_up(ifp)) { + zlog_err( + "interface %s vrf %u index %d is still up while being deleted.", + ifp->name, ifp->vrf_id, ifp->ifindex); + return; + } - /* Reset some zebra interface params to default values. */ - zif = ifp->info; - if (zif) - { - zif->zif_type = ZEBRA_IF_OTHER; - zif->zif_slave_type = ZEBRA_IF_SLAVE_NONE; - memset (&zif->l2info, 0, sizeof (union zebra_l2if_info)); - memset (&zif->brslave_info, 0, sizeof (struct zebra_l2info_brslave)); - } + /* Mark interface as inactive */ + UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("interface %s vrf %u index %d is now inactive.", + ifp->name, ifp->vrf_id, ifp->ifindex); + + /* Delete connected routes from the kernel. */ + if_delete_connected(ifp); + + /* Send out notification on interface delete. */ + zebra_interface_delete_update(ifp); + + if_unlink_per_ns(ifp); + + /* Update ifindex after distributing the delete message. This is in + case any client needs to have the old value of ifindex available + while processing the deletion. Each client daemon is responsible + for setting ifindex to IFINDEX_INTERNAL after processing the + interface deletion message. */ + ifp->ifindex = IFINDEX_INTERNAL; + ifp->node = NULL; + + /* if the ifp is in a vrf, move it to default so vrf can be deleted if + * desired */ + if (ifp->vrf_id) + if_handle_vrf_change(ifp, VRF_DEFAULT); + + /* Reset some zebra interface params to default values. */ + zif = ifp->info; + if (zif) { + zif->zif_type = ZEBRA_IF_OTHER; + zif->zif_slave_type = ZEBRA_IF_SLAVE_NONE; + memset(&zif->l2info, 0, sizeof(union zebra_l2if_info)); + memset(&zif->brslave_info, 0, + sizeof(struct zebra_l2info_brslave)); + } } /* VRF change for an interface */ -void -if_handle_vrf_change (struct interface *ifp, vrf_id_t vrf_id) +void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id) { - vrf_id_t old_vrf_id; + vrf_id_t old_vrf_id; - old_vrf_id = ifp->vrf_id; + old_vrf_id = ifp->vrf_id; - /* Uninstall connected routes. */ - if_uninstall_connected (ifp); + /* Uninstall connected routes. */ + if_uninstall_connected(ifp); - /* Delete any IPv4 neighbors created to implement RFC 5549 */ - if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp); + /* Delete any IPv4 neighbors created to implement RFC 5549 */ + if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); - /* Delete all neighbor addresses learnt through IPv6 RA */ - if_down_del_nbr_connected (ifp); + /* Delete all neighbor addresses learnt through IPv6 RA */ + if_down_del_nbr_connected(ifp); - /* Send out notification on interface VRF change. */ - /* This is to issue an UPDATE or a DELETE, as appropriate. */ - zebra_interface_vrf_update_del (ifp, vrf_id); + /* Send out notification on interface VRF change. */ + /* This is to issue an UPDATE or a DELETE, as appropriate. */ + zebra_interface_vrf_update_del(ifp, vrf_id); - /* update VRF */ - if_update_to_new_vrf (ifp, vrf_id); + /* update VRF */ + if_update_to_new_vrf(ifp, vrf_id); - /* Send out notification on interface VRF change. */ - /* This is to issue an ADD, if needed. */ - zebra_interface_vrf_update_add (ifp, old_vrf_id); + /* Send out notification on interface VRF change. */ + /* This is to issue an ADD, if needed. */ + zebra_interface_vrf_update_add(ifp, old_vrf_id); - /* Install connected routes (in new VRF). */ - if_install_connected (ifp); + /* Install connected routes (in new VRF). */ + if_install_connected(ifp); - /* Due to connected route change, schedule RIB processing for both old - * and new VRF. - */ - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s VRF change, scheduling RIB processing", - ifp->vrf_id, ifp->name); - rib_update (old_vrf_id, RIB_UPDATE_IF_CHANGE); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + /* Due to connected route change, schedule RIB processing for both old + * and new VRF. + */ + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("%u: IF %s VRF change, scheduling RIB processing", + ifp->vrf_id, ifp->name); + rib_update(old_vrf_id, RIB_UPDATE_IF_CHANGE); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - zebra_vrf_static_route_interface_fixup (ifp); + zebra_vrf_static_route_interface_fixup(ifp); } -static void -ipv6_ll_address_to_mac (struct in6_addr *address, u_char *mac) +static void ipv6_ll_address_to_mac(struct in6_addr *address, u_char *mac) { - mac[0] = address->s6_addr[8] ^ 0x02; - mac[1] = address->s6_addr[9]; - mac[2] = address->s6_addr[10]; - mac[3] = address->s6_addr[13]; - mac[4] = address->s6_addr[14]; - mac[5] = address->s6_addr[15]; + mac[0] = address->s6_addr[8] ^ 0x02; + mac[1] = address->s6_addr[9]; + mac[2] = address->s6_addr[10]; + mac[3] = address->s6_addr[13]; + mac[4] = address->s6_addr[14]; + mac[5] = address->s6_addr[15]; } -void -if_nbr_ipv6ll_to_ipv4ll_neigh_update (struct interface *ifp, - struct in6_addr *address, - int add) +void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp, + struct in6_addr *address, int add) { - struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); - char buf[16] = "169.254.0.1"; - struct in_addr ipv4_ll; - char mac[6]; + struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); + char buf[16] = "169.254.0.1"; + struct in_addr ipv4_ll; + char mac[6]; - inet_pton (AF_INET, buf, &ipv4_ll); + inet_pton(AF_INET, buf, &ipv4_ll); - ipv6_ll_address_to_mac(address, (u_char *)mac); - kernel_neigh_update (add, ifp->ifindex, ipv4_ll.s_addr, mac, 6); - zvrf->neigh_updates++; + ipv6_ll_address_to_mac(address, (u_char *)mac); + kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr, mac, 6); + zvrf->neigh_updates++; } -static void -if_nbr_ipv6ll_to_ipv4ll_neigh_add_all (struct interface *ifp) +static void if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(struct interface *ifp) { - if (listhead(ifp->nbr_connected)) - { - struct nbr_connected *nbr_connected; - struct listnode *node; + if (listhead(ifp->nbr_connected)) { + struct nbr_connected *nbr_connected; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (ifp->nbr_connected, node, nbr_connected)) - if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, - &nbr_connected->address->u.prefix6, - 1); - } + for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, + nbr_connected)) + if_nbr_ipv6ll_to_ipv4ll_neigh_update( + ifp, &nbr_connected->address->u.prefix6, 1); + } } -void -if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (struct interface *ifp) +void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(struct interface *ifp) { - if (listhead(ifp->nbr_connected)) - { - struct nbr_connected *nbr_connected; - struct listnode *node; + if (listhead(ifp->nbr_connected)) { + struct nbr_connected *nbr_connected; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (ifp->nbr_connected, node, nbr_connected)) - if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, - &nbr_connected->address->u.prefix6, - 0); - } + for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, + nbr_connected)) + if_nbr_ipv6ll_to_ipv4ll_neigh_update( + ifp, &nbr_connected->address->u.prefix6, 0); + } } -static void -if_down_del_nbr_connected (struct interface *ifp) +static void if_down_del_nbr_connected(struct interface *ifp) { - struct nbr_connected *nbr_connected; - struct listnode *node, *nnode; + struct nbr_connected *nbr_connected; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nbr_connected)) - { - listnode_delete (ifp->nbr_connected, nbr_connected); - nbr_connected_free (nbr_connected); - } + for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, + nbr_connected)) { + listnode_delete(ifp->nbr_connected, nbr_connected); + nbr_connected_free(nbr_connected); + } } /* Interface is up. */ -void -if_up (struct interface *ifp) -{ - struct zebra_if *zif; - struct interface *link_if; - - zif = ifp->info; - zif->up_count++; - quagga_timestamp (2, zif->up_last, sizeof (zif->up_last)); - - /* Notify the protocol daemons. */ - if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) { - zlog_warn("%s: interface %s hasn't passed ptm check\n", __func__, - ifp->name); - return; - } - zebra_interface_up_update (ifp); - - if_nbr_ipv6ll_to_ipv4ll_neigh_add_all (ifp); - -#if defined (HAVE_RTADV) - /* Enable fast tx of RA if enabled && RA interval is not in msecs */ - if (zif->rtadv.AdvSendAdvertisements && - (zif->rtadv.MaxRtrAdvInterval >= 1000)) - { - zif->rtadv.inFastRexmit = 1; - zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS; - } +void if_up(struct interface *ifp) +{ + struct zebra_if *zif; + struct interface *link_if; + + zif = ifp->info; + zif->up_count++; + quagga_timestamp(2, zif->up_last, sizeof(zif->up_last)); + + /* Notify the protocol daemons. */ + if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) { + zlog_warn("%s: interface %s hasn't passed ptm check\n", + __func__, ifp->name); + return; + } + zebra_interface_up_update(ifp); + + if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(ifp); + +#if defined(HAVE_RTADV) + /* Enable fast tx of RA if enabled && RA interval is not in msecs */ + if (zif->rtadv.AdvSendAdvertisements + && (zif->rtadv.MaxRtrAdvInterval >= 1000)) { + zif->rtadv.inFastRexmit = 1; + zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS; + } #endif - /* Install connected routes to the kernel. */ - if_install_connected (ifp); - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s up, scheduling RIB processing", - ifp->vrf_id, ifp->name); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - - zebra_vrf_static_route_interface_fixup (ifp); - - /* Handle interface up for specific types for EVPN. Non-VxLAN interfaces - * are checked to see if (remote) neighbor entries need to be installed - * on them for ARP suppression. - */ - if (IS_ZEBRA_IF_VXLAN (ifp)) - zebra_vxlan_if_up (ifp); - else if (IS_ZEBRA_IF_BRIDGE (ifp)) - { - link_if = ifp; - zebra_vxlan_svi_up (ifp, link_if); - } - else if (IS_ZEBRA_IF_VLAN (ifp)) - { - link_if = zif->link; - if (link_if) - zebra_vxlan_svi_up (ifp, link_if); - } + /* Install connected routes to the kernel. */ + if_install_connected(ifp); + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("%u: IF %s up, scheduling RIB processing", + ifp->vrf_id, ifp->name); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + + zebra_vrf_static_route_interface_fixup(ifp); + + /* Handle interface up for specific types for EVPN. Non-VxLAN interfaces + * are checked to see if (remote) neighbor entries need to be installed + * on them for ARP suppression. + */ + if (IS_ZEBRA_IF_VXLAN(ifp)) + zebra_vxlan_if_up(ifp); + else if (IS_ZEBRA_IF_BRIDGE(ifp)) { + link_if = ifp; + zebra_vxlan_svi_up(ifp, link_if); + } else if (IS_ZEBRA_IF_VLAN(ifp)) { + link_if = zif->link; + if (link_if) + zebra_vxlan_svi_up(ifp, link_if); + } } /* Interface goes down. We have to manage different behavior of based OS. */ -void -if_down (struct interface *ifp) -{ - struct zebra_if *zif; - struct interface *link_if; - - zif = ifp->info; - zif->down_count++; - quagga_timestamp (2, zif->down_last, sizeof (zif->down_last)); - - /* Handle interface down for specific types for EVPN. Non-VxLAN interfaces - * are checked to see if (remote) neighbor entries need to be purged - * for ARP suppression. - */ - if (IS_ZEBRA_IF_VXLAN (ifp)) - zebra_vxlan_if_down (ifp); - else if (IS_ZEBRA_IF_BRIDGE (ifp)) - { - link_if = ifp; - zebra_vxlan_svi_down (ifp, link_if); - } - else if (IS_ZEBRA_IF_VLAN (ifp)) - { - link_if = zif->link; - if (link_if) - zebra_vxlan_svi_down (ifp, link_if); - } +void if_down(struct interface *ifp) +{ + struct zebra_if *zif; + struct interface *link_if; + + zif = ifp->info; + zif->down_count++; + quagga_timestamp(2, zif->down_last, sizeof(zif->down_last)); + + /* Handle interface down for specific types for EVPN. Non-VxLAN + * interfaces + * are checked to see if (remote) neighbor entries need to be purged + * for ARP suppression. + */ + if (IS_ZEBRA_IF_VXLAN(ifp)) + zebra_vxlan_if_down(ifp); + else if (IS_ZEBRA_IF_BRIDGE(ifp)) { + link_if = ifp; + zebra_vxlan_svi_down(ifp, link_if); + } else if (IS_ZEBRA_IF_VLAN(ifp)) { + link_if = zif->link; + if (link_if) + zebra_vxlan_svi_down(ifp, link_if); + } - /* Notify to the protocol daemons. */ - zebra_interface_down_update (ifp); + /* Notify to the protocol daemons. */ + zebra_interface_down_update(ifp); - /* Uninstall connected routes from the kernel. */ - if_uninstall_connected (ifp); + /* Uninstall connected routes from the kernel. */ + if_uninstall_connected(ifp); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s down, scheduling RIB processing", - ifp->vrf_id, ifp->name); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("%u: IF %s down, scheduling RIB processing", + ifp->vrf_id, ifp->name); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp); + if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); - /* Delete all neighbor addresses learnt through IPv6 RA */ - if_down_del_nbr_connected (ifp); + /* Delete all neighbor addresses learnt through IPv6 RA */ + if_down_del_nbr_connected(ifp); } -void -if_refresh (struct interface *ifp) +void if_refresh(struct interface *ifp) { - if_get_flags (ifp); + if_get_flags(ifp); } -void -zebra_if_update_link (struct interface *ifp, ifindex_t link_ifindex) +void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex) { - struct zebra_if *zif; + struct zebra_if *zif; - zif = (struct zebra_if *)ifp->info; - zif->link_ifindex = link_ifindex; - zif->link = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), - link_ifindex); + zif = (struct zebra_if *)ifp->info; + zif->link_ifindex = link_ifindex; + zif->link = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), + link_ifindex); } /* Output prefix string to vty. */ -static int -prefix_vty_out (struct vty *vty, struct prefix *p) +static int prefix_vty_out(struct vty *vty, struct prefix *p) { - char str[INET6_ADDRSTRLEN]; + char str[INET6_ADDRSTRLEN]; - inet_ntop (p->family, &p->u.prefix, str, sizeof (str)); - vty_out (vty, "%s", str); - return strlen (str); + inet_ntop(p->family, &p->u.prefix, str, sizeof(str)); + vty_out(vty, "%s", str); + return strlen(str); } /* Dump if address information to vty. */ -static void -connected_dump_vty (struct vty *vty, struct connected *connected) +static void connected_dump_vty(struct vty *vty, struct connected *connected) { - struct prefix *p; + struct prefix *p; - /* Print interface address. */ - p = connected->address; - vty_out (vty, " %s ", prefix_family_str (p)); - prefix_vty_out (vty, p); - vty_out (vty, "/%d", p->prefixlen); + /* Print interface address. */ + p = connected->address; + vty_out(vty, " %s ", prefix_family_str(p)); + prefix_vty_out(vty, p); + vty_out(vty, "/%d", p->prefixlen); - /* If there is destination address, print it. */ - if (connected->destination) - { - vty_out (vty, (CONNECTED_PEER(connected) ? " peer " : " broadcast ")); - prefix_vty_out (vty, connected->destination); - } + /* If there is destination address, print it. */ + if (connected->destination) { + vty_out(vty, + (CONNECTED_PEER(connected) ? " peer " : " broadcast ")); + prefix_vty_out(vty, connected->destination); + } - if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY)) - vty_out (vty, " secondary"); + if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY)) + vty_out(vty, " secondary"); - if (CHECK_FLAG (connected->flags, ZEBRA_IFA_UNNUMBERED)) - vty_out (vty, " unnumbered"); + if (CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED)) + vty_out(vty, " unnumbered"); - if (connected->label) - vty_out (vty, " %s", connected->label); + if (connected->label) + vty_out(vty, " %s", connected->label); - vty_out (vty, "\n"); + vty_out(vty, "\n"); } /* Dump interface neighbor address information to vty. */ -static void -nbr_connected_dump_vty (struct vty *vty, struct nbr_connected *connected) +static void nbr_connected_dump_vty(struct vty *vty, + struct nbr_connected *connected) { - struct prefix *p; + struct prefix *p; - /* Print interface address. */ - p = connected->address; - vty_out (vty, " %s ", prefix_family_str (p)); - prefix_vty_out (vty, p); - vty_out (vty, "/%d", p->prefixlen); + /* Print interface address. */ + p = connected->address; + vty_out(vty, " %s ", prefix_family_str(p)); + prefix_vty_out(vty, p); + vty_out(vty, "/%d", p->prefixlen); - vty_out (vty, "\n"); + vty_out(vty, "\n"); } -#if defined (HAVE_RTADV) +#if defined(HAVE_RTADV) /* Dump interface ND information to vty. */ -static void -nd_dump_vty (struct vty *vty, struct interface *ifp) -{ - struct zebra_if *zif; - struct rtadvconf *rtadv; - int interval; - - zif = (struct zebra_if *) ifp->info; - rtadv = &zif->rtadv; - - if (rtadv->AdvSendAdvertisements) - { - vty_out (vty, " ND advertised reachable time is %d milliseconds\n", - rtadv->AdvReachableTime); - vty_out (vty, " ND advertised retransmit interval is %d milliseconds\n", - rtadv->AdvRetransTimer); - vty_out (vty, " ND router advertisements sent: %d rcvd: %d\n", - zif->ra_sent, zif->ra_rcvd); - interval = rtadv->MaxRtrAdvInterval; - if (interval % 1000) - vty_out (vty, " ND router advertisements are sent every " - "%d milliseconds\n",interval); - else - vty_out (vty, " ND router advertisements are sent every " - "%d seconds\n",interval / 1000); - if (rtadv->AdvDefaultLifetime != -1) - vty_out (vty, " ND router advertisements live for %d seconds\n", - rtadv->AdvDefaultLifetime); - else - vty_out (vty, - " ND router advertisements lifetime tracks ra-interval\n"); - vty_out (vty, " ND router advertisement default router preference is " - "%s\n",rtadv_pref_strs[rtadv->DefaultPreference]); - if (rtadv->AdvManagedFlag) - vty_out (vty," Hosts use DHCP to obtain routable addresses.\n"); - else - vty_out (vty," Hosts use stateless autoconfig for addresses.\n"); - if (rtadv->AdvHomeAgentFlag) - { - vty_out (vty, - " ND router advertisements with Home Agent flag bit set.\n"); - if (rtadv->HomeAgentLifetime != -1) - vty_out (vty, " Home Agent lifetime is %u seconds\n", - rtadv->HomeAgentLifetime); - else - vty_out (vty," Home Agent lifetime tracks ra-lifetime\n"); - vty_out (vty, " Home Agent preference is %u\n", - rtadv->HomeAgentPreference); - } - if (rtadv->AdvIntervalOption) - vty_out (vty, - " ND router advertisements with Adv. Interval option.\n"); - } +static void nd_dump_vty(struct vty *vty, struct interface *ifp) +{ + struct zebra_if *zif; + struct rtadvconf *rtadv; + int interval; + + zif = (struct zebra_if *)ifp->info; + rtadv = &zif->rtadv; + + if (rtadv->AdvSendAdvertisements) { + vty_out(vty, + " ND advertised reachable time is %d milliseconds\n", + rtadv->AdvReachableTime); + vty_out(vty, + " ND advertised retransmit interval is %d milliseconds\n", + rtadv->AdvRetransTimer); + vty_out(vty, " ND router advertisements sent: %d rcvd: %d\n", + zif->ra_sent, zif->ra_rcvd); + interval = rtadv->MaxRtrAdvInterval; + if (interval % 1000) + vty_out(vty, + " ND router advertisements are sent every " + "%d milliseconds\n", + interval); + else + vty_out(vty, + " ND router advertisements are sent every " + "%d seconds\n", + interval / 1000); + if (rtadv->AdvDefaultLifetime != -1) + vty_out(vty, + " ND router advertisements live for %d seconds\n", + rtadv->AdvDefaultLifetime); + else + vty_out(vty, + " ND router advertisements lifetime tracks ra-interval\n"); + vty_out(vty, + " ND router advertisement default router preference is " + "%s\n", + rtadv_pref_strs[rtadv->DefaultPreference]); + if (rtadv->AdvManagedFlag) + vty_out(vty, + " Hosts use DHCP to obtain routable addresses.\n"); + else + vty_out(vty, + " Hosts use stateless autoconfig for addresses.\n"); + if (rtadv->AdvHomeAgentFlag) { + vty_out(vty, + " ND router advertisements with Home Agent flag bit set.\n"); + if (rtadv->HomeAgentLifetime != -1) + vty_out(vty, + " Home Agent lifetime is %u seconds\n", + rtadv->HomeAgentLifetime); + else + vty_out(vty, + " Home Agent lifetime tracks ra-lifetime\n"); + vty_out(vty, " Home Agent preference is %u\n", + rtadv->HomeAgentPreference); + } + if (rtadv->AdvIntervalOption) + vty_out(vty, + " ND router advertisements with Adv. Interval option.\n"); + } } #endif /* HAVE_RTADV */ -static const char * -zebra_ziftype_2str (zebra_iftype_t zif_type) +static const char *zebra_ziftype_2str(zebra_iftype_t zif_type) { - switch (zif_type) - { - case ZEBRA_IF_OTHER: - return "Other"; - break; + switch (zif_type) { + case ZEBRA_IF_OTHER: + return "Other"; + break; - case ZEBRA_IF_BRIDGE: - return "Bridge"; - break; + case ZEBRA_IF_BRIDGE: + return "Bridge"; + break; - case ZEBRA_IF_VLAN: - return "Vlan"; - break; + case ZEBRA_IF_VLAN: + return "Vlan"; + break; - case ZEBRA_IF_VXLAN: - return "Vxlan"; - break; + case ZEBRA_IF_VXLAN: + return "Vxlan"; + break; - case ZEBRA_IF_VRF: - return "VRF"; - break; + case ZEBRA_IF_VRF: + return "VRF"; + break; - default: - return "Unknown"; - break; - } + default: + return "Unknown"; + break; + } } /* Interface's information print out to vty interface. */ -static void -if_dump_vty (struct vty *vty, struct interface *ifp) -{ - struct connected *connected; - struct nbr_connected *nbr_connected; - struct listnode *node; - struct route_node *rn; - struct zebra_if *zebra_if; - struct vrf *vrf; - - zebra_if = ifp->info; - - vty_out (vty, "Interface %s is ", ifp->name); - if (if_is_up(ifp)) { - vty_out (vty, "up, line protocol "); - - if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) { - if (if_is_running(ifp)) - vty_out (vty, "is up\n"); - else - vty_out (vty, "is down\n"); - } else { - vty_out (vty, "detection is disabled\n"); - } - } else { - vty_out (vty, "down\n"); - } - - vty_out (vty, " Link ups: %5u last: %s\n", zebra_if->up_count, - zebra_if->up_last[0] ? zebra_if->up_last : "(never)"); - vty_out (vty, " Link downs: %5u last: %s\n", zebra_if->down_count, - zebra_if->down_last[0] ? zebra_if->down_last : "(never)"); - - zebra_ptm_show_status(vty, ifp); - - vrf = vrf_lookup_by_id (ifp->vrf_id); - vty_out (vty, " vrf: %s\n", vrf->name); - - if (ifp->desc) - vty_out (vty, " Description: %s\n",ifp->desc); - if (ifp->ifindex == IFINDEX_INTERNAL) - { - vty_out (vty, " pseudo interface\n"); - return; - } - else if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - vty_out (vty, " index %d inactive interface\n", - ifp->ifindex); - return; - } - - vty_out (vty, " index %d metric %d mtu %d speed %u ", - ifp->ifindex, ifp->metric, ifp->mtu, ifp->speed); - if (ifp->mtu6 != ifp->mtu) - vty_out (vty, "mtu6 %d ", ifp->mtu6); - vty_out (vty, "\n flags: %s\n", - if_flag_dump(ifp->flags)); - - /* Hardware address. */ - vty_out (vty, " Type: %s\n", if_link_type_str(ifp->ll_type)); - if (ifp->hw_addr_len != 0) - { - int i; - - vty_out (vty, " HWaddr: "); - for (i = 0; i < ifp->hw_addr_len; i++) - vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]); - vty_out (vty, "\n"); - } - - /* Bandwidth in Mbps */ - if (ifp->bandwidth != 0) - { - vty_out(vty, " bandwidth %u Mbps", ifp->bandwidth); - vty_out (vty, "\n"); - } - - for (rn = route_top (zebra_if->ipv4_subnets); rn; rn = route_next (rn)) - { - if (! rn->info) - continue; - - for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected)) - connected_dump_vty (vty, connected); - } - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) - { - if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) && - (connected->address->family == AF_INET6)) - connected_dump_vty (vty, connected); - } - - vty_out(vty, " Interface Type %s\n", - zebra_ziftype_2str (zebra_if->zif_type)); - if (IS_ZEBRA_IF_BRIDGE (ifp)) - { - struct zebra_l2info_bridge *bridge_info; - - bridge_info = &zebra_if->l2info.br; - vty_out(vty, " Bridge VLAN-aware: %s\n", - bridge_info->vlan_aware ? "yes" : "no"); - } - else if (IS_ZEBRA_IF_VLAN(ifp)) - { - struct zebra_l2info_vlan *vlan_info; - - vlan_info = &zebra_if->l2info.vl; - vty_out(vty, " VLAN Id %u\n", - vlan_info->vid); - } - else if (IS_ZEBRA_IF_VXLAN (ifp)) - { - struct zebra_l2info_vxlan *vxlan_info; - - vxlan_info = &zebra_if->l2info.vxl; - vty_out(vty, " VxLAN Id %u", vxlan_info->vni); - if (vxlan_info->vtep_ip.s_addr != INADDR_ANY) - vty_out(vty, " VTEP IP: %s", inet_ntoa (vxlan_info->vtep_ip)); - if (vxlan_info->access_vlan) - vty_out(vty, " Access VLAN Id %u", vxlan_info->access_vlan); - vty_out(vty, "\n"); - } - - if (IS_ZEBRA_IF_BRIDGE_SLAVE (ifp)) - { - struct zebra_l2info_brslave *br_slave; - - br_slave = &zebra_if->brslave_info; - if (br_slave->bridge_ifindex != IFINDEX_INTERNAL) - vty_out(vty, " Master (bridge) ifindex %u\n", - br_slave->bridge_ifindex); - } - - if (zebra_if->link_ifindex != IFINDEX_INTERNAL) - vty_out(vty, " Link ifindex %u\n", - zebra_if->link_ifindex); - - if (HAS_LINK_PARAMS(ifp)) - { - int i; - struct if_link_params *iflp = ifp->link_params; - vty_out (vty, " Traffic Engineering Link Parameters:\n"); - if (IS_PARAM_SET(iflp, LP_TE_METRIC)) - vty_out (vty, " TE metric %u\n",iflp->te_metric); - if (IS_PARAM_SET(iflp, LP_MAX_BW)) - vty_out (vty, " Maximum Bandwidth %g (Byte/s)\n", iflp->max_bw); - if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)) - vty_out (vty, " Maximum Reservable Bandwidth %g (Byte/s)\n", - iflp->max_rsv_bw); - if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) { - vty_out (vty, " Unreserved Bandwidth per Class Type in Byte/s:\n"); - for (i = 0; i < MAX_CLASS_TYPE; i+=2) - vty_out (vty, " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", - i, iflp->unrsv_bw[i], i+1, iflp->unrsv_bw[i + 1]); - } - - if (IS_PARAM_SET(iflp, LP_ADM_GRP)) - vty_out (vty, " Administrative Group:%u\n", iflp->admin_grp); - if (IS_PARAM_SET(iflp, LP_DELAY)) - { - vty_out(vty, " Link Delay Average: %u (micro-sec.)", iflp->av_delay); - if (IS_PARAM_SET(iflp, LP_MM_DELAY)) - { - vty_out(vty, " Min: %u (micro-sec.)", iflp->min_delay); - vty_out(vty, " Max: %u (micro-sec.)", iflp->max_delay); - } - vty_out (vty, "\n"); - } - if (IS_PARAM_SET(iflp, LP_DELAY_VAR)) - vty_out (vty, " Link Delay Variation %u (micro-sec.)\n", - iflp->delay_var); - if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) - vty_out (vty, " Link Packet Loss %g (in %%)\n", iflp->pkt_loss); - if (IS_PARAM_SET(iflp, LP_AVA_BW)) - vty_out (vty, " Available Bandwidth %g (Byte/s)\n", iflp->ava_bw); - if (IS_PARAM_SET(iflp, LP_RES_BW)) - vty_out (vty, " Residual Bandwidth %g (Byte/s)\n", iflp->res_bw); - if (IS_PARAM_SET(iflp, LP_USE_BW)) - vty_out (vty, " Utilized Bandwidth %g (Byte/s)\n", iflp->use_bw); - if (IS_PARAM_SET(iflp, LP_RMT_AS)) - vty_out (vty, " Neighbor ASBR IP: %s AS: %u \n", inet_ntoa(iflp->rmt_ip), - iflp->rmt_as); - } - - #ifdef RTADV - nd_dump_vty (vty, ifp); - #endif /* RTADV */ -#if defined (HAVE_RTADV) - nd_dump_vty (vty, ifp); +static void if_dump_vty(struct vty *vty, struct interface *ifp) +{ + struct connected *connected; + struct nbr_connected *nbr_connected; + struct listnode *node; + struct route_node *rn; + struct zebra_if *zebra_if; + struct vrf *vrf; + + zebra_if = ifp->info; + + vty_out(vty, "Interface %s is ", ifp->name); + if (if_is_up(ifp)) { + vty_out(vty, "up, line protocol "); + + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) { + if (if_is_running(ifp)) + vty_out(vty, "is up\n"); + else + vty_out(vty, "is down\n"); + } else { + vty_out(vty, "detection is disabled\n"); + } + } else { + vty_out(vty, "down\n"); + } + + vty_out(vty, " Link ups: %5u last: %s\n", zebra_if->up_count, + zebra_if->up_last[0] ? zebra_if->up_last : "(never)"); + vty_out(vty, " Link downs: %5u last: %s\n", zebra_if->down_count, + zebra_if->down_last[0] ? zebra_if->down_last : "(never)"); + + zebra_ptm_show_status(vty, ifp); + + vrf = vrf_lookup_by_id(ifp->vrf_id); + vty_out(vty, " vrf: %s\n", vrf->name); + + if (ifp->desc) + vty_out(vty, " Description: %s\n", ifp->desc); + if (ifp->ifindex == IFINDEX_INTERNAL) { + vty_out(vty, " pseudo interface\n"); + return; + } else if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + vty_out(vty, " index %d inactive interface\n", ifp->ifindex); + return; + } + + vty_out(vty, " index %d metric %d mtu %d speed %u ", ifp->ifindex, + ifp->metric, ifp->mtu, ifp->speed); + if (ifp->mtu6 != ifp->mtu) + vty_out(vty, "mtu6 %d ", ifp->mtu6); + vty_out(vty, "\n flags: %s\n", if_flag_dump(ifp->flags)); + + /* Hardware address. */ + vty_out(vty, " Type: %s\n", if_link_type_str(ifp->ll_type)); + if (ifp->hw_addr_len != 0) { + int i; + + vty_out(vty, " HWaddr: "); + for (i = 0; i < ifp->hw_addr_len; i++) + vty_out(vty, "%s%02x", i == 0 ? "" : ":", + ifp->hw_addr[i]); + vty_out(vty, "\n"); + } + + /* Bandwidth in Mbps */ + if (ifp->bandwidth != 0) { + vty_out(vty, " bandwidth %u Mbps", ifp->bandwidth); + vty_out(vty, "\n"); + } + + for (rn = route_top(zebra_if->ipv4_subnets); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + + for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, + connected)) + connected_dump_vty(vty, connected); + } + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { + if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) + && (connected->address->family == AF_INET6)) + connected_dump_vty(vty, connected); + } + + vty_out(vty, " Interface Type %s\n", + zebra_ziftype_2str(zebra_if->zif_type)); + if (IS_ZEBRA_IF_BRIDGE(ifp)) { + struct zebra_l2info_bridge *bridge_info; + + bridge_info = &zebra_if->l2info.br; + vty_out(vty, " Bridge VLAN-aware: %s\n", + bridge_info->vlan_aware ? "yes" : "no"); + } else if (IS_ZEBRA_IF_VLAN(ifp)) { + struct zebra_l2info_vlan *vlan_info; + + vlan_info = &zebra_if->l2info.vl; + vty_out(vty, " VLAN Id %u\n", vlan_info->vid); + } else if (IS_ZEBRA_IF_VXLAN(ifp)) { + struct zebra_l2info_vxlan *vxlan_info; + + vxlan_info = &zebra_if->l2info.vxl; + vty_out(vty, " VxLAN Id %u", vxlan_info->vni); + if (vxlan_info->vtep_ip.s_addr != INADDR_ANY) + vty_out(vty, " VTEP IP: %s", + inet_ntoa(vxlan_info->vtep_ip)); + if (vxlan_info->access_vlan) + vty_out(vty, " Access VLAN Id %u", + vxlan_info->access_vlan); + vty_out(vty, "\n"); + } + + if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) { + struct zebra_l2info_brslave *br_slave; + + br_slave = &zebra_if->brslave_info; + if (br_slave->bridge_ifindex != IFINDEX_INTERNAL) + vty_out(vty, " Master (bridge) ifindex %u\n", + br_slave->bridge_ifindex); + } + + if (zebra_if->link_ifindex != IFINDEX_INTERNAL) + vty_out(vty, " Link ifindex %u\n", zebra_if->link_ifindex); + + if (HAS_LINK_PARAMS(ifp)) { + int i; + struct if_link_params *iflp = ifp->link_params; + vty_out(vty, " Traffic Engineering Link Parameters:\n"); + if (IS_PARAM_SET(iflp, LP_TE_METRIC)) + vty_out(vty, " TE metric %u\n", iflp->te_metric); + if (IS_PARAM_SET(iflp, LP_MAX_BW)) + vty_out(vty, " Maximum Bandwidth %g (Byte/s)\n", + iflp->max_bw); + if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)) + vty_out(vty, + " Maximum Reservable Bandwidth %g (Byte/s)\n", + iflp->max_rsv_bw); + if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) { + vty_out(vty, + " Unreserved Bandwidth per Class Type in Byte/s:\n"); + for (i = 0; i < MAX_CLASS_TYPE; i += 2) + vty_out(vty, + " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", + i, iflp->unrsv_bw[i], i + 1, + iflp->unrsv_bw[i + 1]); + } + + if (IS_PARAM_SET(iflp, LP_ADM_GRP)) + vty_out(vty, " Administrative Group:%u\n", + iflp->admin_grp); + if (IS_PARAM_SET(iflp, LP_DELAY)) { + vty_out(vty, " Link Delay Average: %u (micro-sec.)", + iflp->av_delay); + if (IS_PARAM_SET(iflp, LP_MM_DELAY)) { + vty_out(vty, " Min: %u (micro-sec.)", + iflp->min_delay); + vty_out(vty, " Max: %u (micro-sec.)", + iflp->max_delay); + } + vty_out(vty, "\n"); + } + if (IS_PARAM_SET(iflp, LP_DELAY_VAR)) + vty_out(vty, + " Link Delay Variation %u (micro-sec.)\n", + iflp->delay_var); + if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) + vty_out(vty, " Link Packet Loss %g (in %%)\n", + iflp->pkt_loss); + if (IS_PARAM_SET(iflp, LP_AVA_BW)) + vty_out(vty, " Available Bandwidth %g (Byte/s)\n", + iflp->ava_bw); + if (IS_PARAM_SET(iflp, LP_RES_BW)) + vty_out(vty, " Residual Bandwidth %g (Byte/s)\n", + iflp->res_bw); + if (IS_PARAM_SET(iflp, LP_USE_BW)) + vty_out(vty, " Utilized Bandwidth %g (Byte/s)\n", + iflp->use_bw); + if (IS_PARAM_SET(iflp, LP_RMT_AS)) + vty_out(vty, " Neighbor ASBR IP: %s AS: %u \n", + inet_ntoa(iflp->rmt_ip), iflp->rmt_as); + } + +#ifdef RTADV + nd_dump_vty(vty, ifp); +#endif /* RTADV */ +#if defined(HAVE_RTADV) + nd_dump_vty(vty, ifp); #endif /* HAVE_RTADV */ - if (listhead(ifp->nbr_connected)) - vty_out (vty, " Neighbor address(s):\n"); - for (ALL_LIST_ELEMENTS_RO (ifp->nbr_connected, node, nbr_connected)) - nbr_connected_dump_vty (vty, nbr_connected); + if (listhead(ifp->nbr_connected)) + vty_out(vty, " Neighbor address(s):\n"); + for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, nbr_connected)) + nbr_connected_dump_vty(vty, nbr_connected); #ifdef HAVE_PROC_NET_DEV - /* Statistics print out using proc file system. */ - vty_out (vty, " %lu input packets (%lu multicast), %lu bytes, " - "%lu dropped\n", - ifp->stats.rx_packets, ifp->stats.rx_multicast, - ifp->stats.rx_bytes, ifp->stats.rx_dropped); - - vty_out (vty, " %lu input errors, %lu length, %lu overrun," - " %lu CRC, %lu frame\n", - ifp->stats.rx_errors, ifp->stats.rx_length_errors, - ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors, - ifp->stats.rx_frame_errors); - - vty_out (vty, " %lu fifo, %lu missed\n", ifp->stats.rx_fifo_errors, - ifp->stats.rx_missed_errors); - - vty_out (vty, " %lu output packets, %lu bytes, %lu dropped\n", - ifp->stats.tx_packets, ifp->stats.tx_bytes, - ifp->stats.tx_dropped); - - vty_out (vty, " %lu output errors, %lu aborted, %lu carrier," - " %lu fifo, %lu heartbeat\n", - ifp->stats.tx_errors, ifp->stats.tx_aborted_errors, - ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors, - ifp->stats.tx_heartbeat_errors); - - vty_out (vty, " %lu window, %lu collisions\n", - ifp->stats.tx_window_errors, ifp->stats.collisions); + /* Statistics print out using proc file system. */ + vty_out(vty, + " %lu input packets (%lu multicast), %lu bytes, " + "%lu dropped\n", + ifp->stats.rx_packets, ifp->stats.rx_multicast, + ifp->stats.rx_bytes, ifp->stats.rx_dropped); + + vty_out(vty, + " %lu input errors, %lu length, %lu overrun," + " %lu CRC, %lu frame\n", + ifp->stats.rx_errors, ifp->stats.rx_length_errors, + ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors, + ifp->stats.rx_frame_errors); + + vty_out(vty, " %lu fifo, %lu missed\n", ifp->stats.rx_fifo_errors, + ifp->stats.rx_missed_errors); + + vty_out(vty, " %lu output packets, %lu bytes, %lu dropped\n", + ifp->stats.tx_packets, ifp->stats.tx_bytes, + ifp->stats.tx_dropped); + + vty_out(vty, + " %lu output errors, %lu aborted, %lu carrier," + " %lu fifo, %lu heartbeat\n", + ifp->stats.tx_errors, ifp->stats.tx_aborted_errors, + ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors, + ifp->stats.tx_heartbeat_errors); + + vty_out(vty, " %lu window, %lu collisions\n", + ifp->stats.tx_window_errors, ifp->stats.collisions); #endif /* HAVE_PROC_NET_DEV */ #ifdef HAVE_NET_RT_IFLIST -#if defined (__bsdi__) || defined (__NetBSD__) - /* Statistics print out using sysctl (). */ - vty_out (vty, " input packets %llu, bytes %llu, dropped %llu," - " multicast packets %llu\n", - (unsigned long long)ifp->stats.ifi_ipackets, - (unsigned long long)ifp->stats.ifi_ibytes, - (unsigned long long)ifp->stats.ifi_iqdrops, - (unsigned long long)ifp->stats.ifi_imcasts); - - vty_out (vty, " input errors %llu\n", - (unsigned long long)ifp->stats.ifi_ierrors); - - vty_out (vty, " output packets %llu, bytes %llu," - " multicast packets %llu\n", - (unsigned long long)ifp->stats.ifi_opackets, - (unsigned long long)ifp->stats.ifi_obytes, - (unsigned long long)ifp->stats.ifi_omcasts); - - vty_out (vty, " output errors %llu\n", - (unsigned long long)ifp->stats.ifi_oerrors); - - vty_out (vty, " collisions %llu\n", - (unsigned long long)ifp->stats.ifi_collisions); +#if defined(__bsdi__) || defined(__NetBSD__) + /* Statistics print out using sysctl (). */ + vty_out(vty, + " input packets %llu, bytes %llu, dropped %llu," + " multicast packets %llu\n", + (unsigned long long)ifp->stats.ifi_ipackets, + (unsigned long long)ifp->stats.ifi_ibytes, + (unsigned long long)ifp->stats.ifi_iqdrops, + (unsigned long long)ifp->stats.ifi_imcasts); + + vty_out(vty, " input errors %llu\n", + (unsigned long long)ifp->stats.ifi_ierrors); + + vty_out(vty, + " output packets %llu, bytes %llu," + " multicast packets %llu\n", + (unsigned long long)ifp->stats.ifi_opackets, + (unsigned long long)ifp->stats.ifi_obytes, + (unsigned long long)ifp->stats.ifi_omcasts); + + vty_out(vty, " output errors %llu\n", + (unsigned long long)ifp->stats.ifi_oerrors); + + vty_out(vty, " collisions %llu\n", + (unsigned long long)ifp->stats.ifi_collisions); #else - /* Statistics print out using sysctl (). */ - vty_out (vty, " input packets %lu, bytes %lu, dropped %lu," - " multicast packets %lu\n", - ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes, - ifp->stats.ifi_iqdrops,ifp->stats.ifi_imcasts); + /* Statistics print out using sysctl (). */ + vty_out(vty, + " input packets %lu, bytes %lu, dropped %lu," + " multicast packets %lu\n", + ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes, + ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts); - vty_out (vty, " input errors %lu\n", - ifp->stats.ifi_ierrors); + vty_out(vty, " input errors %lu\n", ifp->stats.ifi_ierrors); - vty_out (vty, " output packets %lu, bytes %lu, multicast packets %lu\n", - ifp->stats.ifi_opackets, ifp->stats.ifi_obytes, - ifp->stats.ifi_omcasts); + vty_out(vty, + " output packets %lu, bytes %lu, multicast packets %lu\n", + ifp->stats.ifi_opackets, ifp->stats.ifi_obytes, + ifp->stats.ifi_omcasts); - vty_out (vty, " output errors %lu\n", - ifp->stats.ifi_oerrors); + vty_out(vty, " output errors %lu\n", ifp->stats.ifi_oerrors); - vty_out (vty, " collisions %lu\n", - ifp->stats.ifi_collisions); + vty_out(vty, " collisions %lu\n", ifp->stats.ifi_collisions); #endif /* __bsdi__ || __NetBSD__ */ #endif /* HAVE_NET_RT_IFLIST */ } -static void -interface_update_stats (void) +static void interface_update_stats(void) { #ifdef HAVE_PROC_NET_DEV - /* If system has interface statistics via proc file system, update - statistics. */ - ifstat_update_proc (); + /* If system has interface statistics via proc file system, update + statistics. */ + ifstat_update_proc(); #endif /* HAVE_PROC_NET_DEV */ #ifdef HAVE_NET_RT_IFLIST - ifstat_update_sysctl (); + ifstat_update_sysctl(); #endif /* HAVE_NET_RT_IFLIST */ } -struct cmd_node interface_node = -{ - INTERFACE_NODE, - "%s(config-if)# ", - 1 -}; +struct cmd_node interface_node = {INTERFACE_NODE, "%s(config-if)# ", 1}; /* Show all interfaces to vty. */ DEFUN (show_interface, @@ -1417,20 +1378,20 @@ DEFUN (show_interface, "Interface status and configuration\n" VRF_CMD_HELP_STR) { - struct listnode *node; - struct interface *ifp; - vrf_id_t vrf_id = VRF_DEFAULT; + struct listnode *node; + struct interface *ifp; + vrf_id_t vrf_id = VRF_DEFAULT; - interface_update_stats (); + interface_update_stats(); - if (argc > 2) - VRF_GET_ID (vrf_id, argv[3]->arg); + if (argc > 2) + VRF_GET_ID(vrf_id, argv[3]->arg); - /* All interface print. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) - if_dump_vty (vty, ifp); + /* All interface print. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) + if_dump_vty(vty, ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1442,18 +1403,18 @@ DEFUN (show_interface_vrf_all, "Interface status and configuration\n" VRF_ALL_CMD_HELP_STR) { - struct vrf *vrf; - struct listnode *node; - struct interface *ifp; + struct vrf *vrf; + struct listnode *node; + struct interface *ifp; - interface_update_stats (); + interface_update_stats(); - /* All interface print. */ - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) - if_dump_vty (vty, ifp); + /* All interface print. */ + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, ifp)) + if_dump_vty(vty, ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Show specified interface to vty. */ @@ -1466,25 +1427,25 @@ DEFUN (show_interface_name_vrf, "Interface name\n" VRF_CMD_HELP_STR) { - int idx_ifname = 2; - int idx_name = 4; - struct interface *ifp; - vrf_id_t vrf_id = VRF_DEFAULT; + int idx_ifname = 2; + int idx_name = 4; + struct interface *ifp; + vrf_id_t vrf_id = VRF_DEFAULT; - interface_update_stats (); + interface_update_stats(); - VRF_GET_ID (vrf_id, argv[idx_name]->arg); + VRF_GET_ID(vrf_id, argv[idx_name]->arg); - /* Specified interface print. */ - ifp = if_lookup_by_name (argv[idx_ifname]->arg, vrf_id); - if (ifp == NULL) - { - vty_out (vty, "%% Can't find interface %s\n",argv[idx_ifname]->arg); - return CMD_WARNING; - } - if_dump_vty (vty, ifp); + /* Specified interface print. */ + ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id); + if (ifp == NULL) { + vty_out(vty, "%% Can't find interface %s\n", + argv[idx_ifname]->arg); + return CMD_WARNING; + } + if_dump_vty(vty, ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Show specified interface to vty. */ @@ -1496,73 +1457,65 @@ DEFUN (show_interface_name_vrf_all, "Interface name\n" VRF_ALL_CMD_HELP_STR) { - int idx_ifname = 2; - struct vrf *vrf; - struct interface *ifp; - int found = 0; + int idx_ifname = 2; + struct vrf *vrf; + struct interface *ifp; + int found = 0; - interface_update_stats (); + interface_update_stats(); - /* All interface print. */ - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - /* Specified interface print. */ - ifp = if_lookup_by_name (argv[idx_ifname]->arg, vrf->vrf_id); - if (ifp) - { - if_dump_vty (vty, ifp); - found++; - } - } + /* All interface print. */ + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + /* Specified interface print. */ + ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf->vrf_id); + if (ifp) { + if_dump_vty(vty, ifp); + found++; + } + } - if (!found) - { - vty_out (vty, "%% Can't find interface %s\n", argv[idx_ifname]->arg); - return CMD_WARNING; - } + if (!found) { + vty_out(vty, "%% Can't find interface %s\n", + argv[idx_ifname]->arg); + return CMD_WARNING; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -if_show_description (struct vty *vty, vrf_id_t vrf_id) +static void if_show_description(struct vty *vty, vrf_id_t vrf_id) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - vty_out (vty, "Interface Status Protocol Description\n"); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) - { - int len; + vty_out(vty, "Interface Status Protocol Description\n"); + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { + int len; - len = vty_out (vty, "%s", ifp->name); - vty_out (vty, "%*s", (16 - len), " "); - - if (if_is_up(ifp)) - { - vty_out (vty, "up "); - if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) - { - if (if_is_running(ifp)) - vty_out (vty, "up "); - else - vty_out (vty, "down "); - } - else - { - vty_out (vty, "unknown "); - } - } - else - { - vty_out (vty, "down down "); - } + len = vty_out(vty, "%s", ifp->name); + vty_out(vty, "%*s", (16 - len), " "); + + if (if_is_up(ifp)) { + vty_out(vty, "up "); + if (CHECK_FLAG(ifp->status, + ZEBRA_INTERFACE_LINKDETECTION)) { + if (if_is_running(ifp)) + vty_out(vty, "up "); + else + vty_out(vty, "down "); + } else { + vty_out(vty, "unknown "); + } + } else { + vty_out(vty, "down down "); + } - if (ifp->desc) - vty_out (vty, "%s", ifp->desc); - vty_out (vty, "\n"); - } + if (ifp->desc) + vty_out(vty, "%s", ifp->desc); + vty_out(vty, "\n"); + } } DEFUN (show_interface_desc, @@ -1573,14 +1526,14 @@ DEFUN (show_interface_desc, "Interface description\n" VRF_CMD_HELP_STR) { - vrf_id_t vrf_id = VRF_DEFAULT; + vrf_id_t vrf_id = VRF_DEFAULT; - if (argc > 3) - VRF_GET_ID (vrf_id, argv[4]->arg); + if (argc > 3) + VRF_GET_ID(vrf_id, argv[4]->arg); - if_show_description (vty, vrf_id); + if_show_description(vty, vrf_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1592,16 +1545,15 @@ DEFUN (show_interface_desc_vrf_all, "Interface description\n" VRF_ALL_CMD_HELP_STR) { - struct vrf *vrf; + struct vrf *vrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if (!list_isempty (vrf->iflist)) - { - vty_out (vty, "\n\tVRF %u\n\n", vrf->vrf_id); - if_show_description (vty, vrf->vrf_id); - } + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if (!list_isempty(vrf->iflist)) { + vty_out(vty, "\n\tVRF %u\n\n", vrf->vrf_id); + if_show_description(vty, vrf->vrf_id); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (multicast, @@ -1609,24 +1561,22 @@ DEFUN (multicast, "multicast", "Set multicast flag to interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int ret; - struct zebra_if *if_data; + VTY_DECLVAR_CONTEXT(interface, ifp); + int ret; + struct zebra_if *if_data; - if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - ret = if_set_flags (ifp, IFF_MULTICAST); - if (ret < 0) - { - vty_out (vty, "Can't set multicast flag\n"); - return CMD_WARNING_CONFIG_FAILED; + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + ret = if_set_flags(ifp, IFF_MULTICAST); + if (ret < 0) { + vty_out(vty, "Can't set multicast flag\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if_refresh(ifp); } - if_refresh (ifp); - } - if_data = ifp->info; - if_data->multicast = IF_ZEBRA_MULTICAST_ON; + if_data = ifp->info; + if_data->multicast = IF_ZEBRA_MULTICAST_ON; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_multicast, @@ -1635,24 +1585,22 @@ DEFUN (no_multicast, NO_STR "Unset multicast flag to interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int ret; - struct zebra_if *if_data; + VTY_DECLVAR_CONTEXT(interface, ifp); + int ret; + struct zebra_if *if_data; - if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - ret = if_unset_flags (ifp, IFF_MULTICAST); - if (ret < 0) - { - vty_out (vty, "Can't unset multicast flag\n"); - return CMD_WARNING_CONFIG_FAILED; + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + ret = if_unset_flags(ifp, IFF_MULTICAST); + if (ret < 0) { + vty_out(vty, "Can't unset multicast flag\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if_refresh(ifp); } - if_refresh (ifp); - } - if_data = ifp->info; - if_data->multicast = IF_ZEBRA_MULTICAST_OFF; + if_data = ifp->info; + if_data->multicast = IF_ZEBRA_MULTICAST_OFF; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (linkdetect, @@ -1660,19 +1608,20 @@ DEFUN (linkdetect, "link-detect", "Enable link detection on interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int if_was_operative; - - if_was_operative = if_is_no_ptm_operative(ifp); - SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); + VTY_DECLVAR_CONTEXT(interface, ifp); + int if_was_operative; - /* When linkdetection is enabled, if might come down */ - if (!if_is_no_ptm_operative(ifp) && if_was_operative) if_down(ifp); + if_was_operative = if_is_no_ptm_operative(ifp); + SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); - /* FIXME: Will defer status change forwarding if interface - does not come down! */ + /* When linkdetection is enabled, if might come down */ + if (!if_is_no_ptm_operative(ifp) && if_was_operative) + if_down(ifp); - return CMD_SUCCESS; + /* FIXME: Will defer status change forwarding if interface + does not come down! */ + + return CMD_SUCCESS; } @@ -1682,18 +1631,19 @@ DEFUN (no_linkdetect, NO_STR "Disable link detection on interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int if_was_operative; + VTY_DECLVAR_CONTEXT(interface, ifp); + int if_was_operative; + + if_was_operative = if_is_no_ptm_operative(ifp); + UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); - if_was_operative = if_is_no_ptm_operative(ifp); - UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); - - /* Interface may come up after disabling link detection */ - if (if_is_operative(ifp) && !if_was_operative) if_up(ifp); + /* Interface may come up after disabling link detection */ + if (if_is_operative(ifp) && !if_was_operative) + if_up(ifp); - /* FIXME: see linkdetect_cmd */ + /* FIXME: see linkdetect_cmd */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (shutdown_if, @@ -1701,24 +1651,22 @@ DEFUN (shutdown_if, "shutdown", "Shutdown the selected interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int ret; - struct zebra_if *if_data; + VTY_DECLVAR_CONTEXT(interface, ifp); + int ret; + struct zebra_if *if_data; - if (ifp->ifindex != IFINDEX_INTERNAL) - { - ret = if_unset_flags (ifp, IFF_UP); - if (ret < 0) - { - vty_out (vty, "Can't shutdown interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if_refresh (ifp); - } - if_data = ifp->info; - if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON; + if (ifp->ifindex != IFINDEX_INTERNAL) { + ret = if_unset_flags(ifp, IFF_UP); + if (ret < 0) { + vty_out(vty, "Can't shutdown interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if_refresh(ifp); + } + if_data = ifp->info; + if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_shutdown_if, @@ -1727,30 +1675,29 @@ DEFUN (no_shutdown_if, NO_STR "Shutdown the selected interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int ret; - struct zebra_if *if_data; + VTY_DECLVAR_CONTEXT(interface, ifp); + int ret; + struct zebra_if *if_data; - if (ifp->ifindex != IFINDEX_INTERNAL) - { - ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING); - if (ret < 0) - { - vty_out (vty, "Can't up interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if_refresh (ifp); + if (ifp->ifindex != IFINDEX_INTERNAL) { + ret = if_set_flags(ifp, IFF_UP | IFF_RUNNING); + if (ret < 0) { + vty_out(vty, "Can't up interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if_refresh(ifp); - /* Some addresses (in particular, IPv6 addresses on Linux) get - * removed when the interface goes down. They need to be readded. - */ - if_addr_wakeup(ifp); - } + /* Some addresses (in particular, IPv6 addresses on Linux) get + * removed when the interface goes down. They need to be + * readded. + */ + if_addr_wakeup(ifp); + } - if_data = ifp->info; - if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF; + if_data = ifp->info; + if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (bandwidth_if, @@ -1759,26 +1706,25 @@ DEFUN (bandwidth_if, "Set bandwidth informational parameter\n" "Bandwidth in megabits\n") { - int idx_number = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - unsigned int bandwidth; - - bandwidth = strtol(argv[idx_number]->arg, NULL, 10); + int idx_number = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + unsigned int bandwidth; + + bandwidth = strtol(argv[idx_number]->arg, NULL, 10); + + /* bandwidth range is <1-100000> */ + if (bandwidth < 1 || bandwidth > 100000) { + vty_out(vty, "Bandwidth is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ifp->bandwidth = bandwidth; - /* bandwidth range is <1-100000> */ - if (bandwidth < 1 || bandwidth > 100000) - { - vty_out (vty, "Bandwidth is invalid\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ifp->bandwidth = bandwidth; + /* force protocols to recalculate routes due to cost change */ + if (if_is_operative(ifp)) + zebra_interface_up_update(ifp); - /* force protocols to recalculate routes due to cost change */ - if (if_is_operative (ifp)) - zebra_interface_up_update (ifp); - - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bandwidth_if, @@ -1788,69 +1734,63 @@ DEFUN (no_bandwidth_if, "Set bandwidth informational parameter\n" "Bandwidth in megabits\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - ifp->bandwidth = 0; - - /* force protocols to recalculate routes due to cost change */ - if (if_is_operative (ifp)) - zebra_interface_up_update (ifp); + ifp->bandwidth = 0; - return CMD_SUCCESS; + /* force protocols to recalculate routes due to cost change */ + if (if_is_operative(ifp)) + zebra_interface_up_update(ifp); + + return CMD_SUCCESS; } -struct cmd_node link_params_node = -{ - LINK_PARAMS_NODE, - "%s(config-link-params)# ", - 1, +struct cmd_node link_params_node = { + LINK_PARAMS_NODE, "%s(config-link-params)# ", 1, }; -static void -link_param_cmd_set_uint32 (struct interface *ifp, uint32_t *field, - uint32_t type, uint32_t value) +static void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field, + uint32_t type, uint32_t value) { - /* Update field as needed */ - if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) - { - *field = value; - SET_PARAM(ifp->link_params, type); + /* Update field as needed */ + if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) { + *field = value; + SET_PARAM(ifp->link_params, type); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); - } + /* force protocols to update LINK STATE due to parameters change + */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); + } } -static void -link_param_cmd_set_float (struct interface *ifp, float *field, - uint32_t type, float value) +static void link_param_cmd_set_float(struct interface *ifp, float *field, + uint32_t type, float value) { - /* Update field as needed */ - if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) - { - *field = value; - SET_PARAM(ifp->link_params, type); + /* Update field as needed */ + if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) { + *field = value; + SET_PARAM(ifp->link_params, type); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); - } + /* force protocols to update LINK STATE due to parameters change + */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); + } } -static void -link_param_cmd_unset (struct interface *ifp, uint32_t type) +static void link_param_cmd_unset(struct interface *ifp, uint32_t type) { - if (ifp->link_params == NULL) - return; + if (ifp->link_params == NULL) + return; - /* Unset field */ - UNSET_PARAM(ifp->link_params, type); + /* Unset field */ + UNSET_PARAM(ifp->link_params, type); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); } DEFUN_NOSH (link_params, @@ -1858,10 +1798,10 @@ DEFUN_NOSH (link_params, "link-params", LINK_PARAMS_STR) { - /* vty->qobj_index stays the same @ interface pointer */ - vty->node = LINK_PARAMS_NODE; + /* vty->qobj_index stays the same @ interface pointer */ + vty->node = LINK_PARAMS_NODE; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_NOSH (exit_link_params, @@ -1869,9 +1809,9 @@ DEFUN_NOSH (exit_link_params, "exit-link-params", "Exit from Link Params configuration mode\n") { - if (vty->node == LINK_PARAMS_NODE) - vty->node = INTERFACE_NODE; - return CMD_SUCCESS; + if (vty->node == LINK_PARAMS_NODE) + vty->node = INTERFACE_NODE; + return CMD_SUCCESS; } /* Specific Traffic Engineering parameters commands */ @@ -1880,27 +1820,30 @@ DEFUN (link_params_enable, "enable", "Activate link parameters on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* This command could be issue at startup, when activate MPLS TE */ - /* on a new interface or after a ON / OFF / ON toggle */ - /* In all case, TE parameters are reset to their default factory */ - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("Link-params: enable TE link parameters on interface %s", ifp->name); + /* This command could be issue at startup, when activate MPLS TE */ + /* on a new interface or after a ON / OFF / ON toggle */ + /* In all case, TE parameters are reset to their default factory */ + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "Link-params: enable TE link parameters on interface %s", + ifp->name); - if (!if_link_params_get (ifp)) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("Link-params: failed to init TE link parameters %s", ifp->name); + if (!if_link_params_get(ifp)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "Link-params: failed to init TE link parameters %s", + ifp->name); - return CMD_WARNING_CONFIG_FAILED; - } + return CMD_WARNING_CONFIG_FAILED; + } - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_enable, @@ -1909,17 +1852,18 @@ DEFUN (no_link_params_enable, NO_STR "Disable link parameters on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - zlog_debug ("MPLS-TE: disable TE link parameters on interface %s", ifp->name); + zlog_debug("MPLS-TE: disable TE link parameters on interface %s", + ifp->name); - if_link_params_free (ifp); + if_link_params_free(ifp); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* STANDARD TE metrics */ @@ -1929,17 +1873,17 @@ DEFUN (link_params_metric, "Link metric for MPLS-TE purpose\n" "Metric value in decimal\n") { - int idx_number = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - u_int32_t metric; + int idx_number = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + u_int32_t metric; - metric = strtoul(argv[idx_number]->arg, NULL, 10); + metric = strtoul(argv[idx_number]->arg, NULL, 10); - /* Update TE metric if needed */ - link_param_cmd_set_uint32 (ifp, &iflp->te_metric, LP_TE_METRIC, metric); + /* Update TE metric if needed */ + link_param_cmd_set_uint32(ifp, &iflp->te_metric, LP_TE_METRIC, metric); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_metric, @@ -1948,12 +1892,12 @@ DEFUN (no_link_params_metric, NO_STR "Disable Link Metric on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset TE Metric */ - link_param_cmd_unset(ifp, LP_TE_METRIC); + /* Unset TE Metric */ + link_param_cmd_unset(ifp, LP_TE_METRIC); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_maxbw, @@ -1962,41 +1906,35 @@ DEFUN (link_params_maxbw, "Maximum bandwidth that can be used\n" "Bytes/second (IEEE floating point format)\n") { - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - - float bw; - - if (sscanf (argv[idx_bandwidth]->arg, "%g", &bw) != 1) - { - vty_out (vty, "link_params_maxbw: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check that Maximum bandwidth is not lower than other bandwidth parameters */ - if ((bw <= iflp->max_rsv_bw) - || (bw <= iflp->unrsv_bw[0]) - || (bw <= iflp->unrsv_bw[1]) - || (bw <= iflp->unrsv_bw[2]) - || (bw <= iflp->unrsv_bw[3]) - || (bw <= iflp->unrsv_bw[4]) - || (bw <= iflp->unrsv_bw[5]) - || (bw <= iflp->unrsv_bw[6]) - || (bw <= iflp->unrsv_bw[7]) - || (bw <= iflp->ava_bw) - || (bw <= iflp->res_bw) - || (bw <= iflp->use_bw)) - { - vty_out (vty, - "Maximum Bandwidth could not be lower than others bandwidth\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Update Maximum Bandwidth if needed */ - link_param_cmd_set_float (ifp, &iflp->max_bw, LP_MAX_BW, bw); - - return CMD_SUCCESS; + int idx_bandwidth = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + + float bw; + + if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { + vty_out(vty, "link_params_maxbw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check that Maximum bandwidth is not lower than other bandwidth + * parameters */ + if ((bw <= iflp->max_rsv_bw) || (bw <= iflp->unrsv_bw[0]) + || (bw <= iflp->unrsv_bw[1]) || (bw <= iflp->unrsv_bw[2]) + || (bw <= iflp->unrsv_bw[3]) || (bw <= iflp->unrsv_bw[4]) + || (bw <= iflp->unrsv_bw[5]) || (bw <= iflp->unrsv_bw[6]) + || (bw <= iflp->unrsv_bw[7]) || (bw <= iflp->ava_bw) + || (bw <= iflp->res_bw) || (bw <= iflp->use_bw)) { + vty_out(vty, + "Maximum Bandwidth could not be lower than others bandwidth\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Update Maximum Bandwidth if needed */ + link_param_cmd_set_float(ifp, &iflp->max_bw, LP_MAX_BW, bw); + + return CMD_SUCCESS; } DEFUN (link_params_max_rsv_bw, @@ -2005,31 +1943,30 @@ DEFUN (link_params_max_rsv_bw, "Maximum bandwidth that may be reserved\n" "Bytes/second (IEEE floating point format)\n") { - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - float bw; + int idx_bandwidth = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + float bw; - if (sscanf (argv[idx_bandwidth]->arg, "%g", &bw) != 1) - { - vty_out (vty, "link_params_max_rsv_bw: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { + vty_out(vty, "link_params_max_rsv_bw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Check that bandwidth is not greater than maximum bandwidth parameter */ - if (bw > iflp->max_bw) - { - vty_out (vty, - "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } + /* Check that bandwidth is not greater than maximum bandwidth parameter + */ + if (bw > iflp->max_bw) { + vty_out(vty, + "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)\n", + iflp->max_bw); + return CMD_WARNING_CONFIG_FAILED; + } - /* Update Maximum Reservable Bandwidth if needed */ - link_param_cmd_set_float (ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw); + /* Update Maximum Reservable Bandwidth if needed */ + link_param_cmd_set_float(ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_unrsv_bw, @@ -2039,41 +1976,40 @@ DEFUN (link_params_unrsv_bw, "Priority\n" "Bytes/second (IEEE floating point format)\n") { - int idx_number = 1; - int idx_bandwidth = 2; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - int priority; - float bw; - - /* We don't have to consider about range check here. */ - if (sscanf (argv[idx_number]->arg, "%d", &priority) != 1) - { - vty_out (vty, "link_params_unrsv_bw: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - if (sscanf (argv[idx_bandwidth]->arg, "%g", &bw) != 1) - { - vty_out (vty, "link_params_unrsv_bw: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check that bandwidth is not greater than maximum bandwidth parameter */ - if (bw > iflp->max_bw) - { - vty_out (vty, - "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Update Unreserved Bandwidth if needed */ - link_param_cmd_set_float (ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW, bw); - - return CMD_SUCCESS; + int idx_number = 1; + int idx_bandwidth = 2; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + int priority; + float bw; + + /* We don't have to consider about range check here. */ + if (sscanf(argv[idx_number]->arg, "%d", &priority) != 1) { + vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { + vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check that bandwidth is not greater than maximum bandwidth parameter + */ + if (bw > iflp->max_bw) { + vty_out(vty, + "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)\n", + iflp->max_bw); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Update Unreserved Bandwidth if needed */ + link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW, + bw); + + return CMD_SUCCESS; } DEFUN (link_params_admin_grp, @@ -2082,22 +2018,21 @@ DEFUN (link_params_admin_grp, "Administrative group membership\n" "32-bit Hexadecimal value (e.g. 0xa1)\n") { - int idx_bitpattern = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - unsigned long value; + int idx_bitpattern = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + unsigned long value; - if (sscanf (argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) - { - vty_out (vty, "link_params_admin_grp: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) { + vty_out(vty, "link_params_admin_grp: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Update Administrative Group if needed */ - link_param_cmd_set_uint32 (ifp, &iflp->admin_grp, LP_ADM_GRP, value); + /* Update Administrative Group if needed */ + link_param_cmd_set_uint32(ifp, &iflp->admin_grp, LP_ADM_GRP, value); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_admin_grp, @@ -2106,12 +2041,12 @@ DEFUN (no_link_params_admin_grp, NO_STR "Disable Administrative group membership on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset Admin Group */ - link_param_cmd_unset(ifp, LP_ADM_GRP); + /* Unset Admin Group */ + link_param_cmd_unset(ifp, LP_ADM_GRP); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* RFC5392 & RFC5316: INTER-AS */ @@ -2123,37 +2058,35 @@ DEFUN (link_params_inter_as, "Remote AS number\n" "AS number in the range <1-4294967295>\n") { - int idx_ipv4 = 1; - int idx_number = 3; + int idx_ipv4 = 1; + int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - struct in_addr addr; - u_int32_t as; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + struct in_addr addr; + u_int32_t as; - if (!inet_aton (argv[idx_ipv4]->arg, &addr)) - { - vty_out (vty, "Please specify Router-Addr by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!inet_aton(argv[idx_ipv4]->arg, &addr)) { + vty_out(vty, "Please specify Router-Addr by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - as = strtoul(argv[idx_number]->arg, NULL, 10); + as = strtoul(argv[idx_number]->arg, NULL, 10); - /* Update Remote IP and Remote AS fields if needed */ - if (IS_PARAM_UNSET(iflp, LP_RMT_AS) - || iflp->rmt_as != as - || iflp->rmt_ip.s_addr != addr.s_addr) - { + /* Update Remote IP and Remote AS fields if needed */ + if (IS_PARAM_UNSET(iflp, LP_RMT_AS) || iflp->rmt_as != as + || iflp->rmt_ip.s_addr != addr.s_addr) { - iflp->rmt_as = as; - iflp->rmt_ip.s_addr = addr.s_addr; - SET_PARAM(iflp, LP_RMT_AS); + iflp->rmt_as = as; + iflp->rmt_ip.s_addr = addr.s_addr; + SET_PARAM(iflp, LP_RMT_AS); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); - } - return CMD_SUCCESS; + /* force protocols to update LINK STATE due to parameters change + */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); + } + return CMD_SUCCESS; } DEFUN (no_link_params_inter_as, @@ -2162,22 +2095,23 @@ DEFUN (no_link_params_inter_as, NO_STR "Remove Neighbor IP address and AS number for Inter-AS TE\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); - /* Reset Remote IP and AS neighbor */ - iflp->rmt_as = 0; - iflp->rmt_ip.s_addr = 0; - UNSET_PARAM(iflp, LP_RMT_AS); + /* Reset Remote IP and AS neighbor */ + iflp->rmt_as = 0; + iflp->rmt_ip.s_addr = 0; + UNSET_PARAM(iflp, LP_RMT_AS); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } -/* RFC7471: OSPF Traffic Engineering (TE) Metric extensions & draft-ietf-isis-metric-extensions-07.txt */ +/* RFC7471: OSPF Traffic Engineering (TE) Metric extensions & + * draft-ietf-isis-metric-extensions-07.txt */ DEFUN (link_params_delay, link_params_delay_cmd, "delay (0-16777215) [min (0-16777215) max (0-16777215)]", @@ -2188,75 +2122,68 @@ DEFUN (link_params_delay, "Maximum delay\n" "Maximum delay in micro-second as decimal (0...16777215)\n") { - /* Get and Check new delay values */ - u_int32_t delay = 0, low = 0, high = 0; - delay = strtoul(argv[1]->arg, NULL, 10); - if (argc == 6) - { - low = strtoul(argv[3]->arg, NULL, 10); - high = strtoul(argv[5]->arg, NULL, 10); - } - - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - u_int8_t update = 0; - - if (argc == 2) - { - /* Check new delay value against old Min and Max delays if set */ - if (IS_PARAM_SET(iflp, LP_MM_DELAY) - && (delay <= iflp->min_delay || delay >= iflp->max_delay)) - { - vty_out (vty, "Average delay should be comprise between Min (%d) and Max (%d) delay\n", - iflp->min_delay, iflp->max_delay); - return CMD_WARNING_CONFIG_FAILED; - } - /* Update delay if value is not set or change */ - if (IS_PARAM_UNSET(iflp, LP_DELAY)|| iflp->av_delay != delay) - { - iflp->av_delay = delay; - SET_PARAM(iflp, LP_DELAY); - update = 1; - } - /* Unset Min and Max delays if already set */ - if (IS_PARAM_SET(iflp, LP_MM_DELAY)) - { - iflp->min_delay = 0; - iflp->max_delay = 0; - UNSET_PARAM(iflp, LP_MM_DELAY); - update = 1; - } - } - else - { - /* Check new delays value coherency */ - if (delay <= low || delay >= high) - { - vty_out (vty, "Average delay should be comprise between Min (%d) and Max (%d) delay\n", - low, high); - return CMD_WARNING_CONFIG_FAILED; - } - /* Update Delays if needed */ - if (IS_PARAM_UNSET(iflp, LP_DELAY) - || IS_PARAM_UNSET(iflp, LP_MM_DELAY) - || iflp->av_delay != delay - || iflp->min_delay != low - || iflp->max_delay != high) - { - iflp->av_delay = delay; - SET_PARAM(iflp, LP_DELAY); - iflp->min_delay = low; - iflp->max_delay = high; - SET_PARAM(iflp, LP_MM_DELAY); - update = 1; - } - } - - /* force protocols to update LINK STATE due to parameters change */ - if (update == 1 && if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); - - return CMD_SUCCESS; + /* Get and Check new delay values */ + u_int32_t delay = 0, low = 0, high = 0; + delay = strtoul(argv[1]->arg, NULL, 10); + if (argc == 6) { + low = strtoul(argv[3]->arg, NULL, 10); + high = strtoul(argv[5]->arg, NULL, 10); + } + + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + u_int8_t update = 0; + + if (argc == 2) { + /* Check new delay value against old Min and Max delays if set + */ + if (IS_PARAM_SET(iflp, LP_MM_DELAY) + && (delay <= iflp->min_delay || delay >= iflp->max_delay)) { + vty_out(vty, + "Average delay should be comprise between Min (%d) and Max (%d) delay\n", + iflp->min_delay, iflp->max_delay); + return CMD_WARNING_CONFIG_FAILED; + } + /* Update delay if value is not set or change */ + if (IS_PARAM_UNSET(iflp, LP_DELAY) || iflp->av_delay != delay) { + iflp->av_delay = delay; + SET_PARAM(iflp, LP_DELAY); + update = 1; + } + /* Unset Min and Max delays if already set */ + if (IS_PARAM_SET(iflp, LP_MM_DELAY)) { + iflp->min_delay = 0; + iflp->max_delay = 0; + UNSET_PARAM(iflp, LP_MM_DELAY); + update = 1; + } + } else { + /* Check new delays value coherency */ + if (delay <= low || delay >= high) { + vty_out(vty, + "Average delay should be comprise between Min (%d) and Max (%d) delay\n", + low, high); + return CMD_WARNING_CONFIG_FAILED; + } + /* Update Delays if needed */ + if (IS_PARAM_UNSET(iflp, LP_DELAY) + || IS_PARAM_UNSET(iflp, LP_MM_DELAY) + || iflp->av_delay != delay || iflp->min_delay != low + || iflp->max_delay != high) { + iflp->av_delay = delay; + SET_PARAM(iflp, LP_DELAY); + iflp->min_delay = low; + iflp->max_delay = high; + SET_PARAM(iflp, LP_MM_DELAY); + update = 1; + } + } + + /* force protocols to update LINK STATE due to parameters change */ + if (update == 1 && if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); + + return CMD_SUCCESS; } DEFUN (no_link_params_delay, @@ -2265,21 +2192,21 @@ DEFUN (no_link_params_delay, NO_STR "Disable Unidirectional Average, Min & Max Link Delay on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); - /* Unset Delays */ - iflp->av_delay = 0; - UNSET_PARAM(iflp, LP_DELAY); - iflp->min_delay = 0; - iflp->max_delay = 0; - UNSET_PARAM(iflp, LP_MM_DELAY); + /* Unset Delays */ + iflp->av_delay = 0; + UNSET_PARAM(iflp, LP_DELAY); + iflp->min_delay = 0; + iflp->max_delay = 0; + UNSET_PARAM(iflp, LP_MM_DELAY); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_delay_var, @@ -2288,17 +2215,17 @@ DEFUN (link_params_delay_var, "Unidirectional Link Delay Variation\n" "delay variation in micro-second as decimal (0...16777215)\n") { - int idx_number = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - u_int32_t value; + int idx_number = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + u_int32_t value; - value = strtoul(argv[idx_number]->arg, NULL, 10); + value = strtoul(argv[idx_number]->arg, NULL, 10); - /* Update Delay Variation if needed */ - link_param_cmd_set_uint32 (ifp, &iflp->delay_var, LP_DELAY_VAR, value); + /* Update Delay Variation if needed */ + link_param_cmd_set_uint32(ifp, &iflp->delay_var, LP_DELAY_VAR, value); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_delay_var, @@ -2307,12 +2234,12 @@ DEFUN (no_link_params_delay_var, NO_STR "Disable Unidirectional Delay Variation on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset Delay Variation */ - link_param_cmd_unset(ifp, LP_DELAY_VAR); + /* Unset Delay Variation */ + link_param_cmd_unset(ifp, LP_DELAY_VAR); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_pkt_loss, @@ -2321,25 +2248,24 @@ DEFUN (link_params_pkt_loss, "Unidirectional Link Packet Loss\n" "percentage of total traffic by 0.000003% step and less than 50.331642%\n") { - int idx_percentage = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - float fval; + int idx_percentage = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + float fval; - if (sscanf (argv[idx_percentage]->arg, "%g", &fval) != 1) - { - vty_out (vty, "link_params_pkt_loss: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_percentage]->arg, "%g", &fval) != 1) { + vty_out(vty, "link_params_pkt_loss: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - if (fval > MAX_PKT_LOSS) - fval = MAX_PKT_LOSS; + if (fval > MAX_PKT_LOSS) + fval = MAX_PKT_LOSS; - /* Update Packet Loss if needed */ - link_param_cmd_set_float (ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval); + /* Update Packet Loss if needed */ + link_param_cmd_set_float(ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_pkt_loss, @@ -2348,12 +2274,12 @@ DEFUN (no_link_params_pkt_loss, NO_STR "Disable Unidirectional Link Packet Loss on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset Packet Loss */ - link_param_cmd_unset(ifp, LP_PKT_LOSS); + /* Unset Packet Loss */ + link_param_cmd_unset(ifp, LP_PKT_LOSS); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_res_bw, @@ -2362,30 +2288,30 @@ DEFUN (link_params_res_bw, "Unidirectional Residual Bandwidth\n" "Bytes/second (IEEE floating point format)\n") { - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - float bw; + int idx_bandwidth = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + float bw; - if (sscanf (argv[idx_bandwidth]->arg, "%g", &bw) != 1) - { - vty_out (vty, "link_params_res_bw: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { + vty_out(vty, "link_params_res_bw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Check that bandwidth is not greater than maximum bandwidth parameter */ - if (bw > iflp->max_bw) - { - vty_out (vty, - "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } + /* Check that bandwidth is not greater than maximum bandwidth parameter + */ + if (bw > iflp->max_bw) { + vty_out(vty, + "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)\n", + iflp->max_bw); + return CMD_WARNING_CONFIG_FAILED; + } - /* Update Residual Bandwidth if needed */ - link_param_cmd_set_float (ifp, &iflp->res_bw, LP_RES_BW, bw); + /* Update Residual Bandwidth if needed */ + link_param_cmd_set_float(ifp, &iflp->res_bw, LP_RES_BW, bw); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_res_bw, @@ -2394,12 +2320,12 @@ DEFUN (no_link_params_res_bw, NO_STR "Disable Unidirectional Residual Bandwidth on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset Residual Bandwidth */ - link_param_cmd_unset(ifp, LP_RES_BW); + /* Unset Residual Bandwidth */ + link_param_cmd_unset(ifp, LP_RES_BW); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_ava_bw, @@ -2408,30 +2334,30 @@ DEFUN (link_params_ava_bw, "Unidirectional Available Bandwidth\n" "Bytes/second (IEEE floating point format)\n") { - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - float bw; + int idx_bandwidth = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + float bw; - if (sscanf (argv[idx_bandwidth]->arg, "%g", &bw) != 1) - { - vty_out (vty, "link_params_ava_bw: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { + vty_out(vty, "link_params_ava_bw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Check that bandwidth is not greater than maximum bandwidth parameter */ - if (bw > iflp->max_bw) - { - vty_out (vty, - "Available Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } + /* Check that bandwidth is not greater than maximum bandwidth parameter + */ + if (bw > iflp->max_bw) { + vty_out(vty, + "Available Bandwidth could not be greater than Maximum Bandwidth (%g)\n", + iflp->max_bw); + return CMD_WARNING_CONFIG_FAILED; + } - /* Update Residual Bandwidth if needed */ - link_param_cmd_set_float (ifp, &iflp->ava_bw, LP_AVA_BW, bw); + /* Update Residual Bandwidth if needed */ + link_param_cmd_set_float(ifp, &iflp->ava_bw, LP_AVA_BW, bw); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_ava_bw, @@ -2440,12 +2366,12 @@ DEFUN (no_link_params_ava_bw, NO_STR "Disable Unidirectional Available Bandwidth on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset Available Bandwidth */ - link_param_cmd_unset(ifp, LP_AVA_BW); + /* Unset Available Bandwidth */ + link_param_cmd_unset(ifp, LP_AVA_BW); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_use_bw, @@ -2454,30 +2380,30 @@ DEFUN (link_params_use_bw, "Unidirectional Utilised Bandwidth\n" "Bytes/second (IEEE floating point format)\n") { - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - float bw; + int idx_bandwidth = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + float bw; - if (sscanf (argv[idx_bandwidth]->arg, "%g", &bw) != 1) - { - vty_out (vty, "link_params_use_bw: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { + vty_out(vty, "link_params_use_bw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Check that bandwidth is not greater than maximum bandwidth parameter */ - if (bw > iflp->max_bw) - { - vty_out (vty, - "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } + /* Check that bandwidth is not greater than maximum bandwidth parameter + */ + if (bw > iflp->max_bw) { + vty_out(vty, + "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)\n", + iflp->max_bw); + return CMD_WARNING_CONFIG_FAILED; + } - /* Update Utilized Bandwidth if needed */ - link_param_cmd_set_float (ifp, &iflp->use_bw, LP_USE_BW, bw); + /* Update Utilized Bandwidth if needed */ + link_param_cmd_set_float(ifp, &iflp->use_bw, LP_USE_BW, bw); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_use_bw, @@ -2486,153 +2412,142 @@ DEFUN (no_link_params_use_bw, NO_STR "Disable Unidirectional Utilised Bandwidth on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset Utilised Bandwidth */ - link_param_cmd_unset(ifp, LP_USE_BW); + /* Unset Utilised Bandwidth */ + link_param_cmd_unset(ifp, LP_USE_BW); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -ip_address_install (struct vty *vty, struct interface *ifp, - const char *addr_str, const char *peer_str, - const char *label) +static int ip_address_install(struct vty *vty, struct interface *ifp, + const char *addr_str, const char *peer_str, + const char *label) { - struct zebra_if *if_data; - struct prefix_ipv4 cp; - struct connected *ifc; - struct prefix_ipv4 *p; - int ret; + struct zebra_if *if_data; + struct prefix_ipv4 cp; + struct connected *ifc; + struct prefix_ipv4 *p; + int ret; - if_data = ifp->info; + if_data = ifp->info; - ret = str2prefix_ipv4 (addr_str, &cp); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address \n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = str2prefix_ipv4(addr_str, &cp); + if (ret <= 0) { + vty_out(vty, "%% Malformed address \n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ipv4_martian(&cp.prefix)) - { - vty_out (vty, "%% Invalid address\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ipv4_martian(&cp.prefix)) { + vty_out(vty, "%% Invalid address\n"); + return CMD_WARNING_CONFIG_FAILED; + } - ifc = connected_check (ifp, (struct prefix *) &cp); - if (! ifc) - { - ifc = connected_new (); - ifc->ifp = ifp; + ifc = connected_check(ifp, (struct prefix *)&cp); + if (!ifc) { + ifc = connected_new(); + ifc->ifp = ifp; + + /* Address. */ + p = prefix_ipv4_new(); + *p = cp; + ifc->address = (struct prefix *)p; + + /* Broadcast. */ + if (p->prefixlen <= IPV4_MAX_PREFIXLEN - 2) { + p = prefix_ipv4_new(); + *p = cp; + p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr, + p->prefixlen); + ifc->destination = (struct prefix *)p; + } - /* Address. */ - p = prefix_ipv4_new (); - *p = cp; - ifc->address = (struct prefix *) p; + /* Label. */ + if (label) + ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); - /* Broadcast. */ - if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2) - { - p = prefix_ipv4_new (); - *p = cp; - p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen); - ifc->destination = (struct prefix *) p; - } - - /* Label. */ - if (label) - ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); - - /* Add to linked list. */ - listnode_add (ifp->connected, ifc); - } - - /* This address is configured from zebra. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); - - /* In case of this route need to install kernel. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED) - && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE) - && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) - { - /* Some system need to up the interface to set IP address. */ - if (! if_is_up (ifp)) - { - if_set_flags (ifp, IFF_UP | IFF_RUNNING); - if_refresh (ifp); + /* Add to linked list. */ + listnode_add(ifp->connected, ifc); } - ret = if_set_prefix (ifp, ifc); - if (ret < 0) - { - vty_out (vty, "%% Can't set interface IP address: %s.\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - /* The address will be advertised to zebra clients when the notification - * from the kernel has been received. - * It will also be added to the subnet chain list, then. */ - } - - return CMD_SUCCESS; -} - -static int -ip_address_uninstall (struct vty *vty, struct interface *ifp, - const char *addr_str, const char *peer_str, - const char *label) -{ - struct prefix_ipv4 cp; - struct connected *ifc; - int ret; - - /* Convert to prefix structure. */ - ret = str2prefix_ipv4 (addr_str, &cp); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address \n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check current interface address. */ - ifc = connected_check (ifp, (struct prefix *) &cp); - if (! ifc) - { - vty_out (vty, "%% Can't find address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* This is not configured address. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - return CMD_WARNING_CONFIG_FAILED; - - UNSET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); - - /* This is not real address or interface is not active. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED) - || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - listnode_delete (ifp->connected, ifc); - connected_free (ifc); - return CMD_WARNING_CONFIG_FAILED; - } - - /* This is real route. */ - ret = if_unset_prefix (ifp, ifc); - if (ret < 0) - { - vty_out (vty, "%% Can't unset interface IP address: %s.\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - /* we will receive a kernel notification about this route being removed. - * this will trigger its removal from the connected list. */ - return CMD_SUCCESS; + /* This address is configured from zebra. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) + SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); + + /* In case of this route need to install kernel. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) + && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) + && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) { + /* Some system need to up the interface to set IP address. */ + if (!if_is_up(ifp)) { + if_set_flags(ifp, IFF_UP | IFF_RUNNING); + if_refresh(ifp); + } + + ret = if_set_prefix(ifp, ifc); + if (ret < 0) { + vty_out(vty, "%% Can't set interface IP address: %s.\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra clients when the + * notification + * from the kernel has been received. + * It will also be added to the subnet chain list, then. */ + } + + return CMD_SUCCESS; +} + +static int ip_address_uninstall(struct vty *vty, struct interface *ifp, + const char *addr_str, const char *peer_str, + const char *label) +{ + struct prefix_ipv4 cp; + struct connected *ifc; + int ret; + + /* Convert to prefix structure. */ + ret = str2prefix_ipv4(addr_str, &cp); + if (ret <= 0) { + vty_out(vty, "%% Malformed address \n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check current interface address. */ + ifc = connected_check(ifp, (struct prefix *)&cp); + if (!ifc) { + vty_out(vty, "%% Can't find address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* This is not configured address. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) + return CMD_WARNING_CONFIG_FAILED; + + UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); + + /* This is not real address or interface is not active. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) + || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + listnode_delete(ifp->connected, ifc); + connected_free(ifc); + return CMD_WARNING_CONFIG_FAILED; + } + + /* This is real route. */ + ret = if_unset_prefix(ifp, ifc); + if (ret < 0) { + vty_out(vty, "%% Can't unset interface IP address: %s.\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* we will receive a kernel notification about this route being removed. + * this will trigger its removal from the connected list. */ + return CMD_SUCCESS; } DEFUN (ip_address, @@ -2642,9 +2557,10 @@ DEFUN (ip_address, "Set the IP address of an interface\n" "IP address (e.g. 10.0.0.1/8)\n") { - int idx_ipv4_prefixlen = 2; - VTY_DECLVAR_CONTEXT (interface, ifp); - return ip_address_install (vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, NULL); + int idx_ipv4_prefixlen = 2; + VTY_DECLVAR_CONTEXT(interface, ifp); + return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, + NULL); } DEFUN (no_ip_address, @@ -2655,9 +2571,10 @@ DEFUN (no_ip_address, "Set the IP address of an interface\n" "IP Address (e.g. 10.0.0.1/8)") { - int idx_ipv4_prefixlen = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - return ip_address_uninstall (vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, NULL); + int idx_ipv4_prefixlen = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg, + NULL, NULL); } @@ -2671,10 +2588,11 @@ DEFUN (ip_address_label, "Label of this address\n" "Label\n") { - int idx_ipv4_prefixlen = 2; - int idx_line = 4; - VTY_DECLVAR_CONTEXT (interface, ifp); - return ip_address_install (vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, argv[idx_line]->arg); + int idx_ipv4_prefixlen = 2; + int idx_line = 4; + VTY_DECLVAR_CONTEXT(interface, ifp); + return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, + argv[idx_line]->arg); } DEFUN (no_ip_address_label, @@ -2687,162 +2605,152 @@ DEFUN (no_ip_address_label, "Label of this address\n" "Label\n") { - int idx_ipv4_prefixlen = 3; - int idx_line = 5; - VTY_DECLVAR_CONTEXT (interface, ifp); - return ip_address_uninstall (vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, argv[idx_line]->arg); + int idx_ipv4_prefixlen = 3; + int idx_line = 5; + VTY_DECLVAR_CONTEXT(interface, ifp); + return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg, + NULL, argv[idx_line]->arg); } #endif /* HAVE_NETLINK */ -static int -ipv6_address_install (struct vty *vty, struct interface *ifp, - const char *addr_str, const char *peer_str, - const char *label, int secondary) -{ - struct zebra_if *if_data; - struct prefix_ipv6 cp; - struct connected *ifc; - struct prefix_ipv6 *p; - int ret; - - if_data = ifp->info; - - ret = str2prefix_ipv6 (addr_str, &cp); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address \n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (ipv6_martian(&cp.prefix)) - { - vty_out (vty, "%% Invalid address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ifc = connected_check (ifp, (struct prefix *) &cp); - if (! ifc) - { - ifc = connected_new (); - ifc->ifp = ifp; - - /* Address. */ - p = prefix_ipv6_new (); - *p = cp; - ifc->address = (struct prefix *) p; - - /* Secondary. */ - if (secondary) - SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY); - - /* Label. */ - if (label) - ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); - - /* Add to linked list. */ - listnode_add (ifp->connected, ifc); - } - - /* This address is configured from zebra. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); - - /* In case of this route need to install kernel. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED) - && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE) - && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) - { - /* Some system need to up the interface to set IP address. */ - if (! if_is_up (ifp)) - { - if_set_flags (ifp, IFF_UP | IFF_RUNNING); - if_refresh (ifp); +static int ipv6_address_install(struct vty *vty, struct interface *ifp, + const char *addr_str, const char *peer_str, + const char *label, int secondary) +{ + struct zebra_if *if_data; + struct prefix_ipv6 cp; + struct connected *ifc; + struct prefix_ipv6 *p; + int ret; + + if_data = ifp->info; + + ret = str2prefix_ipv6(addr_str, &cp); + if (ret <= 0) { + vty_out(vty, "%% Malformed address \n"); + return CMD_WARNING_CONFIG_FAILED; } - ret = if_prefix_add_ipv6 (ifp, ifc); + if (ipv6_martian(&cp.prefix)) { + vty_out(vty, "%% Invalid address\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ret < 0) - { - vty_out (vty, "%% Can't set interface IP address: %s.\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; + ifc = connected_check(ifp, (struct prefix *)&cp); + if (!ifc) { + ifc = connected_new(); + ifc->ifp = ifp; + + /* Address. */ + p = prefix_ipv6_new(); + *p = cp; + ifc->address = (struct prefix *)p; + + /* Secondary. */ + if (secondary) + SET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY); + + /* Label. */ + if (label) + ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); + + /* Add to linked list. */ + listnode_add(ifp->connected, ifc); } - SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - /* The address will be advertised to zebra clients when the notification - * from the kernel has been received. */ - } + /* This address is configured from zebra. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) + SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); + + /* In case of this route need to install kernel. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) + && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) + && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) { + /* Some system need to up the interface to set IP address. */ + if (!if_is_up(ifp)) { + if_set_flags(ifp, IFF_UP | IFF_RUNNING); + if_refresh(ifp); + } + + ret = if_prefix_add_ipv6(ifp, ifc); + + if (ret < 0) { + vty_out(vty, "%% Can't set interface IP address: %s.\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra clients when the + * notification + * from the kernel has been received. */ + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Return true if an ipv6 address is configured on ifp */ -int -ipv6_address_configured (struct interface *ifp) -{ - struct connected *connected; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) - if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) && (connected->address->family == AF_INET6)) - return 1; - - return 0; -} - -static int -ipv6_address_uninstall (struct vty *vty, struct interface *ifp, - const char *addr_str, const char *peer_str, - const char *label, int secondry) -{ - struct prefix_ipv6 cp; - struct connected *ifc; - int ret; - - /* Convert to prefix structure. */ - ret = str2prefix_ipv6 (addr_str, &cp); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address \n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check current interface address. */ - ifc = connected_check (ifp, (struct prefix *) &cp); - if (! ifc) - { - vty_out (vty, "%% Can't find address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* This is not configured address. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - return CMD_WARNING_CONFIG_FAILED; - - UNSET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); - - /* This is not real address or interface is not active. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED) - || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - listnode_delete (ifp->connected, ifc); - connected_free (ifc); - return CMD_WARNING_CONFIG_FAILED; - } - - /* This is real route. */ - ret = if_prefix_delete_ipv6 (ifp, ifc); - if (ret < 0) - { - vty_out (vty, "%% Can't unset interface IP address: %s.\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - /* This information will be propagated to the zclients when the - * kernel notification is received. */ - return CMD_SUCCESS; +int ipv6_address_configured(struct interface *ifp) +{ + struct connected *connected; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) + if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) + && (connected->address->family == AF_INET6)) + return 1; + + return 0; +} + +static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp, + const char *addr_str, const char *peer_str, + const char *label, int secondry) +{ + struct prefix_ipv6 cp; + struct connected *ifc; + int ret; + + /* Convert to prefix structure. */ + ret = str2prefix_ipv6(addr_str, &cp); + if (ret <= 0) { + vty_out(vty, "%% Malformed address \n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check current interface address. */ + ifc = connected_check(ifp, (struct prefix *)&cp); + if (!ifc) { + vty_out(vty, "%% Can't find address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* This is not configured address. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) + return CMD_WARNING_CONFIG_FAILED; + + UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); + + /* This is not real address or interface is not active. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) + || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + listnode_delete(ifp->connected, ifc); + connected_free(ifc); + return CMD_WARNING_CONFIG_FAILED; + } + + /* This is real route. */ + ret = if_prefix_delete_ipv6(ifp, ifc); + if (ret < 0) { + vty_out(vty, "%% Can't unset interface IP address: %s.\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* This information will be propagated to the zclients when the + * kernel notification is received. */ + return CMD_SUCCESS; } DEFUN (ipv6_address, @@ -2852,9 +2760,10 @@ DEFUN (ipv6_address, "Set the IP address of an interface\n" "IPv6 address (e.g. 3ffe:506::1/48)\n") { - int idx_ipv6_prefixlen = 2; - VTY_DECLVAR_CONTEXT (interface, ifp); - return ipv6_address_install (vty, ifp, argv[idx_ipv6_prefixlen]->arg, NULL, NULL, 0); + int idx_ipv6_prefixlen = 2; + VTY_DECLVAR_CONTEXT(interface, ifp); + return ipv6_address_install(vty, ifp, argv[idx_ipv6_prefixlen]->arg, + NULL, NULL, 0); } DEFUN (no_ipv6_address, @@ -2865,209 +2774,204 @@ DEFUN (no_ipv6_address, "Set the IP address of an interface\n" "IPv6 address (e.g. 3ffe:506::1/48)\n") { - int idx_ipv6_prefixlen = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - return ipv6_address_uninstall (vty, ifp, argv[idx_ipv6_prefixlen]->arg, NULL, NULL, 0); -} - -static int -link_params_config_write (struct vty *vty, struct interface *ifp) -{ - int i; - - if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp)) - return -1; - - struct if_link_params *iflp = ifp->link_params; - - vty_out (vty, " link-params\n"); - vty_out (vty, " enable\n"); - if (IS_PARAM_SET(iflp, LP_TE_METRIC) && iflp->te_metric != ifp->metric) - vty_out (vty, " metric %u\n",iflp->te_metric); - if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw) - vty_out (vty, " max-bw %g\n", iflp->max_bw); - if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW) && iflp->max_rsv_bw != iflp->default_bw) - vty_out (vty, " max-rsv-bw %g\n", iflp->max_rsv_bw); - if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) - { - for (i = 0; i < 8; i++) - if (iflp->unrsv_bw[i] != iflp->default_bw) - vty_out (vty, " unrsv-bw %d %g\n", - i, iflp->unrsv_bw[i]); - } - if (IS_PARAM_SET(iflp, LP_ADM_GRP)) - vty_out (vty, " admin-grp 0x%x\n", iflp->admin_grp); - if (IS_PARAM_SET(iflp, LP_DELAY)) - { - vty_out(vty, " delay %u", iflp->av_delay); - if (IS_PARAM_SET(iflp, LP_MM_DELAY)) - { - vty_out(vty, " min %u", iflp->min_delay); - vty_out(vty, " max %u", iflp->max_delay); - } - vty_out (vty, "\n"); - } - if (IS_PARAM_SET(iflp, LP_DELAY_VAR)) - vty_out (vty, " delay-variation %u\n", iflp->delay_var); - if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) - vty_out (vty, " packet-loss %g\n", iflp->pkt_loss); - if (IS_PARAM_SET(iflp, LP_AVA_BW)) - vty_out (vty, " ava-bw %g\n", iflp->ava_bw); - if (IS_PARAM_SET(iflp, LP_RES_BW)) - vty_out (vty, " res-bw %g\n", iflp->res_bw); - if (IS_PARAM_SET(iflp, LP_USE_BW)) - vty_out (vty, " use-bw %g\n", iflp->use_bw); - if (IS_PARAM_SET(iflp, LP_RMT_AS)) - vty_out (vty, " neighbor %s as %u\n", inet_ntoa(iflp->rmt_ip), - iflp->rmt_as); - vty_out (vty, " exit-link-params\n"); - return 0; -} - -static int -if_config_write (struct vty *vty) -{ - struct vrf *vrf; - struct listnode *node; - struct interface *ifp; - - zebra_ptm_write (vty); - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) - { - struct zebra_if *if_data; - struct listnode *addrnode; - struct connected *ifc; - struct prefix *p; - struct vrf *vrf; - - if_data = ifp->info; - vrf = vrf_lookup_by_id (ifp->vrf_id); - - if (ifp->vrf_id == VRF_DEFAULT) - vty_out (vty, "interface %s\n", ifp->name); - else - vty_out (vty, "interface %s vrf %s\n", ifp->name,vrf->name); - - if (if_data) - { - if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) - vty_out (vty, " shutdown\n"); + int idx_ipv6_prefixlen = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + return ipv6_address_uninstall(vty, ifp, argv[idx_ipv6_prefixlen]->arg, + NULL, NULL, 0); +} + +static int link_params_config_write(struct vty *vty, struct interface *ifp) +{ + int i; + + if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp)) + return -1; - zebra_ptm_if_write(vty, if_data); + struct if_link_params *iflp = ifp->link_params; + + vty_out(vty, " link-params\n"); + vty_out(vty, " enable\n"); + if (IS_PARAM_SET(iflp, LP_TE_METRIC) && iflp->te_metric != ifp->metric) + vty_out(vty, " metric %u\n", iflp->te_metric); + if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw) + vty_out(vty, " max-bw %g\n", iflp->max_bw); + if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW) + && iflp->max_rsv_bw != iflp->default_bw) + vty_out(vty, " max-rsv-bw %g\n", iflp->max_rsv_bw); + if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) { + for (i = 0; i < 8; i++) + if (iflp->unrsv_bw[i] != iflp->default_bw) + vty_out(vty, " unrsv-bw %d %g\n", i, + iflp->unrsv_bw[i]); + } + if (IS_PARAM_SET(iflp, LP_ADM_GRP)) + vty_out(vty, " admin-grp 0x%x\n", iflp->admin_grp); + if (IS_PARAM_SET(iflp, LP_DELAY)) { + vty_out(vty, " delay %u", iflp->av_delay); + if (IS_PARAM_SET(iflp, LP_MM_DELAY)) { + vty_out(vty, " min %u", iflp->min_delay); + vty_out(vty, " max %u", iflp->max_delay); + } + vty_out(vty, "\n"); } + if (IS_PARAM_SET(iflp, LP_DELAY_VAR)) + vty_out(vty, " delay-variation %u\n", iflp->delay_var); + if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) + vty_out(vty, " packet-loss %g\n", iflp->pkt_loss); + if (IS_PARAM_SET(iflp, LP_AVA_BW)) + vty_out(vty, " ava-bw %g\n", iflp->ava_bw); + if (IS_PARAM_SET(iflp, LP_RES_BW)) + vty_out(vty, " res-bw %g\n", iflp->res_bw); + if (IS_PARAM_SET(iflp, LP_USE_BW)) + vty_out(vty, " use-bw %g\n", iflp->use_bw); + if (IS_PARAM_SET(iflp, LP_RMT_AS)) + vty_out(vty, " neighbor %s as %u\n", inet_ntoa(iflp->rmt_ip), + iflp->rmt_as); + vty_out(vty, " exit-link-params\n"); + return 0; +} + +static int if_config_write(struct vty *vty) +{ + struct vrf *vrf; + struct listnode *node; + struct interface *ifp; + + zebra_ptm_write(vty); + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, ifp)) { + struct zebra_if *if_data; + struct listnode *addrnode; + struct connected *ifc; + struct prefix *p; + struct vrf *vrf; + + if_data = ifp->info; + vrf = vrf_lookup_by_id(ifp->vrf_id); + + if (ifp->vrf_id == VRF_DEFAULT) + vty_out(vty, "interface %s\n", ifp->name); + else + vty_out(vty, "interface %s vrf %s\n", ifp->name, + vrf->name); + + if (if_data) { + if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) + vty_out(vty, " shutdown\n"); + + zebra_ptm_if_write(vty, if_data); + } - if (ifp->desc) - vty_out (vty, " description %s\n",ifp->desc); + if (ifp->desc) + vty_out(vty, " description %s\n", ifp->desc); - /* Assign bandwidth here to avoid unnecessary interface flap - while processing config script */ - if (ifp->bandwidth != 0) - vty_out (vty, " bandwidth %u\n", ifp->bandwidth); + /* Assign bandwidth here to avoid unnecessary interface flap + while processing config script */ + if (ifp->bandwidth != 0) + vty_out(vty, " bandwidth %u\n", ifp->bandwidth); - if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) - vty_out (vty, " no link-detect\n"); + if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) + vty_out(vty, " no link-detect\n"); - for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc)) - { - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - { - char buf[INET6_ADDRSTRLEN]; - p = ifc->address; - vty_out (vty, " ip%s address %s", - p->family == AF_INET ? "" : "v6", - prefix2str (p, buf, sizeof(buf))); + for (ALL_LIST_ELEMENTS_RO(ifp->connected, addrnode, ifc)) { + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) { + char buf[INET6_ADDRSTRLEN]; + p = ifc->address; + vty_out(vty, " ip%s address %s", + p->family == AF_INET ? "" : "v6", + prefix2str(p, buf, sizeof(buf))); - if (ifc->label) - vty_out (vty, " label %s", ifc->label); + if (ifc->label) + vty_out(vty, " label %s", ifc->label); - vty_out (vty, "\n"); - } - } + vty_out(vty, "\n"); + } + } - if (if_data) - { - if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC) - vty_out (vty, " %smulticast\n", - if_data->multicast == IF_ZEBRA_MULTICAST_ON ? "" : "no "); - } + if (if_data) { + if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC) + vty_out(vty, " %smulticast\n", + if_data->multicast + == IF_ZEBRA_MULTICAST_ON + ? "" + : "no "); + } -#if defined (HAVE_RTADV) - rtadv_config_write (vty, ifp); +#if defined(HAVE_RTADV) + rtadv_config_write(vty, ifp); #endif /* HAVE_RTADV */ #ifdef HAVE_IRDP - irdp_config_write (vty, ifp); + irdp_config_write(vty, ifp); #endif /* IRDP */ - link_params_config_write (vty, ifp); + link_params_config_write(vty, ifp); - vty_out (vty, "!\n"); - } - return 0; + vty_out(vty, "!\n"); + } + return 0; } /* Allocate and initialize interface vector. */ -void -zebra_if_init (void) -{ - /* Initialize interface and new hook. */ - if_add_hook (IF_NEW_HOOK, if_zebra_new_hook); - if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook); - - /* Install configuration write function. */ - install_node (&interface_node, if_config_write); - install_node (&link_params_node, NULL); - if_cmd_init (); - - install_element (VIEW_NODE, &show_interface_cmd); - install_element (VIEW_NODE, &show_interface_vrf_all_cmd); - install_element (VIEW_NODE, &show_interface_name_vrf_cmd); - install_element (VIEW_NODE, &show_interface_name_vrf_all_cmd); - - install_element (ENABLE_NODE, &show_interface_desc_cmd); - install_element (ENABLE_NODE, &show_interface_desc_vrf_all_cmd); - install_element (INTERFACE_NODE, &multicast_cmd); - install_element (INTERFACE_NODE, &no_multicast_cmd); - install_element (INTERFACE_NODE, &linkdetect_cmd); - install_element (INTERFACE_NODE, &no_linkdetect_cmd); - install_element (INTERFACE_NODE, &shutdown_if_cmd); - install_element (INTERFACE_NODE, &no_shutdown_if_cmd); - install_element (INTERFACE_NODE, &bandwidth_if_cmd); - install_element (INTERFACE_NODE, &no_bandwidth_if_cmd); - install_element (INTERFACE_NODE, &ip_address_cmd); - install_element (INTERFACE_NODE, &no_ip_address_cmd); - install_element (INTERFACE_NODE, &ipv6_address_cmd); - install_element (INTERFACE_NODE, &no_ipv6_address_cmd); +void zebra_if_init(void) +{ + /* Initialize interface and new hook. */ + if_add_hook(IF_NEW_HOOK, if_zebra_new_hook); + if_add_hook(IF_DELETE_HOOK, if_zebra_delete_hook); + + /* Install configuration write function. */ + install_node(&interface_node, if_config_write); + install_node(&link_params_node, NULL); + if_cmd_init(); + + install_element(VIEW_NODE, &show_interface_cmd); + install_element(VIEW_NODE, &show_interface_vrf_all_cmd); + install_element(VIEW_NODE, &show_interface_name_vrf_cmd); + install_element(VIEW_NODE, &show_interface_name_vrf_all_cmd); + + install_element(ENABLE_NODE, &show_interface_desc_cmd); + install_element(ENABLE_NODE, &show_interface_desc_vrf_all_cmd); + install_element(INTERFACE_NODE, &multicast_cmd); + install_element(INTERFACE_NODE, &no_multicast_cmd); + install_element(INTERFACE_NODE, &linkdetect_cmd); + install_element(INTERFACE_NODE, &no_linkdetect_cmd); + install_element(INTERFACE_NODE, &shutdown_if_cmd); + install_element(INTERFACE_NODE, &no_shutdown_if_cmd); + install_element(INTERFACE_NODE, &bandwidth_if_cmd); + install_element(INTERFACE_NODE, &no_bandwidth_if_cmd); + install_element(INTERFACE_NODE, &ip_address_cmd); + install_element(INTERFACE_NODE, &no_ip_address_cmd); + install_element(INTERFACE_NODE, &ipv6_address_cmd); + install_element(INTERFACE_NODE, &no_ipv6_address_cmd); #ifdef HAVE_NETLINK - install_element (INTERFACE_NODE, &ip_address_label_cmd); - install_element (INTERFACE_NODE, &no_ip_address_label_cmd); + install_element(INTERFACE_NODE, &ip_address_label_cmd); + install_element(INTERFACE_NODE, &no_ip_address_label_cmd); #endif /* HAVE_NETLINK */ - install_element(INTERFACE_NODE, &link_params_cmd); - install_default(LINK_PARAMS_NODE); - install_element(LINK_PARAMS_NODE, &link_params_enable_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd); - install_element(LINK_PARAMS_NODE, &link_params_metric_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_metric_cmd); - install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_admin_grp_cmd); - install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd); - install_element(LINK_PARAMS_NODE, &link_params_delay_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_delay_cmd); - install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_delay_var_cmd); - install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_pkt_loss_cmd); - install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_ava_bw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd); - install_element(LINK_PARAMS_NODE, &exit_link_params_cmd); + install_element(INTERFACE_NODE, &link_params_cmd); + install_default(LINK_PARAMS_NODE); + install_element(LINK_PARAMS_NODE, &link_params_enable_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd); + install_element(LINK_PARAMS_NODE, &link_params_metric_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_metric_cmd); + install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_admin_grp_cmd); + install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd); + install_element(LINK_PARAMS_NODE, &link_params_delay_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_delay_cmd); + install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_delay_var_cmd); + install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_pkt_loss_cmd); + install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_ava_bw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd); + install_element(LINK_PARAMS_NODE, &exit_link_params_cmd); } diff --git a/zebra/interface.h b/zebra/interface.h index f5ca00c4a..ea7226469 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -39,142 +39,144 @@ #define IF_ZEBRA_SHUTDOWN_OFF 0 #define IF_ZEBRA_SHUTDOWN_ON 1 -#if defined (HAVE_RTADV) +#if defined(HAVE_RTADV) /* Router advertisement parameter. From RFC4861, RFC6275 and RFC4191. */ -struct rtadvconf -{ - /* A flag indicating whether or not the router sends periodic Router - Advertisements and responds to Router Solicitations. - Default: FALSE */ - int AdvSendAdvertisements; - - /* The maximum time allowed between sending unsolicited multicast - Router Advertisements from the interface, in milliseconds. - MUST be no less than 70 ms [RFC6275 7.5] and no greater - than 1800000 ms [RFC4861 6.2.1]. - - Default: 600000 milliseconds */ - int MaxRtrAdvInterval; +struct rtadvconf { + /* A flag indicating whether or not the router sends periodic Router + Advertisements and responds to Router Solicitations. + Default: FALSE */ + int AdvSendAdvertisements; + + /* The maximum time allowed between sending unsolicited multicast + Router Advertisements from the interface, in milliseconds. + MUST be no less than 70 ms [RFC6275 7.5] and no greater + than 1800000 ms [RFC4861 6.2.1]. + + Default: 600000 milliseconds */ + int MaxRtrAdvInterval; #define RTADV_MAX_RTR_ADV_INTERVAL 600000 - /* The minimum time allowed between sending unsolicited multicast - Router Advertisements from the interface, in milliseconds. - MUST be no less than 30 ms [RFC6275 7.5]. - MUST be no greater than .75 * MaxRtrAdvInterval. + /* The minimum time allowed between sending unsolicited multicast + Router Advertisements from the interface, in milliseconds. + MUST be no less than 30 ms [RFC6275 7.5]. + MUST be no greater than .75 * MaxRtrAdvInterval. - Default: 0.33 * MaxRtrAdvInterval */ - int MinRtrAdvInterval; /* This field is currently unused. */ + Default: 0.33 * MaxRtrAdvInterval */ + int MinRtrAdvInterval; /* This field is currently unused. */ + /* $FRR indent$ */ + /* clang-format off */ #define RTADV_MIN_RTR_ADV_INTERVAL (0.33 * RTADV_MAX_RTR_ADV_INTERVAL) - /* Unsolicited Router Advertisements' interval timer. */ - int AdvIntervalTimer; + /* Unsolicited Router Advertisements' interval timer. */ + int AdvIntervalTimer; - /* The TRUE/FALSE value to be placed in the "Managed address - configuration" flag field in the Router Advertisement. See - [ADDRCONF]. - - Default: FALSE */ - int AdvManagedFlag; + /* The TRUE/FALSE value to be placed in the "Managed address + configuration" flag field in the Router Advertisement. See + [ADDRCONF]. + Default: FALSE */ + int AdvManagedFlag; - /* The TRUE/FALSE value to be placed in the "Other stateful - configuration" flag field in the Router Advertisement. See - [ADDRCONF]. - Default: FALSE */ - int AdvOtherConfigFlag; + /* The TRUE/FALSE value to be placed in the "Other stateful + configuration" flag field in the Router Advertisement. See + [ADDRCONF]. - /* The value to be placed in MTU options sent by the router. A - value of zero indicates that no MTU options are sent. + Default: FALSE */ + int AdvOtherConfigFlag; - Default: 0 */ - int AdvLinkMTU; + /* The value to be placed in MTU options sent by the router. A + value of zero indicates that no MTU options are sent. + Default: 0 */ + int AdvLinkMTU; - /* The value to be placed in the Reachable Time field in the Router - Advertisement messages sent by the router. The value zero means - unspecified (by this router). MUST be no greater than 3,600,000 - milliseconds (1 hour). - Default: 0 */ - u_int32_t AdvReachableTime; -#define RTADV_MAX_REACHABLE_TIME 3600000 + /* The value to be placed in the Reachable Time field in the Router + Advertisement messages sent by the router. The value zero means + unspecified (by this router). MUST be no greater than 3,600,000 + milliseconds (1 hour). + Default: 0 */ + u_int32_t AdvReachableTime; +#define RTADV_MAX_REACHABLE_TIME 3600000 - /* The value to be placed in the Retrans Timer field in the Router - Advertisement messages sent by the router. The value zero means - unspecified (by this router). + /* The value to be placed in the Retrans Timer field in the Router + Advertisement messages sent by the router. The value zero means + unspecified (by this router). - Default: 0 */ - int AdvRetransTimer; + Default: 0 */ + int AdvRetransTimer; - /* The default value to be placed in the Cur Hop Limit field in the - Router Advertisement messages sent by the router. The value - should be set to that current diameter of the Internet. The - value zero means unspecified (by this router). + /* The default value to be placed in the Cur Hop Limit field in the + Router Advertisement messages sent by the router. The value + should be set to that current diameter of the Internet. The + value zero means unspecified (by this router). - Default: The value specified in the "Assigned Numbers" RFC - [ASSIGNED] that was in effect at the time of implementation. */ - int AdvCurHopLimit; + Default: The value specified in the "Assigned Numbers" RFC + [ASSIGNED] that was in effect at the time of implementation. */ + int AdvCurHopLimit; - /* The value to be placed in the Router Lifetime field of Router - Advertisements sent from the interface, in seconds. MUST be - either zero or between MaxRtrAdvInterval and 9000 seconds. A - value of zero indicates that the router is not to be used as a - default router. + /* The value to be placed in the Router Lifetime field of Router + Advertisements sent from the interface, in seconds. MUST be + either zero or between MaxRtrAdvInterval and 9000 seconds. A + value of zero indicates that the router is not to be used as a + default router. - Default: 3 * MaxRtrAdvInterval */ - int AdvDefaultLifetime; + Default: 3 * MaxRtrAdvInterval */ + int AdvDefaultLifetime; #define RTADV_MAX_RTRLIFETIME 9000 /* 2.5 hours */ - /* A list of prefixes to be placed in Prefix Information options in - Router Advertisement messages sent from the interface. + /* A list of prefixes to be placed in Prefix Information options in + Router Advertisement messages sent from the interface. - Default: all prefixes that the router advertises via routing - protocols as being on-link for the interface from which the - advertisement is sent. The link-local prefix SHOULD NOT be - included in the list of advertised prefixes. */ - struct list *AdvPrefixList; + Default: all prefixes that the router advertises via routing + protocols as being on-link for the interface from which the + advertisement is sent. The link-local prefix SHOULD NOT be + included in the list of advertised prefixes. */ + struct list *AdvPrefixList; - /* The TRUE/FALSE value to be placed in the "Home agent" - flag field in the Router Advertisement. See [RFC6275 7.1]. + /* The TRUE/FALSE value to be placed in the "Home agent" + flag field in the Router Advertisement. See [RFC6275 7.1]. - Default: FALSE */ - int AdvHomeAgentFlag; + Default: FALSE */ + int AdvHomeAgentFlag; #ifndef ND_RA_FLAG_HOME_AGENT #define ND_RA_FLAG_HOME_AGENT 0x20 #endif - /* The value to be placed in Home Agent Information option if Home - Flag is set. - Default: 0 */ - int HomeAgentPreference; - - /* The value to be placed in Home Agent Information option if Home - Flag is set. Lifetime (seconds) MUST not be greater than 18.2 - hours. - The value 0 has special meaning: use of AdvDefaultLifetime value. - - Default: 0 */ - int HomeAgentLifetime; + /* The value to be placed in Home Agent Information option if Home + Flag is set. + Default: 0 */ + int HomeAgentPreference; + + /* The value to be placed in Home Agent Information option if Home + Flag is set. Lifetime (seconds) MUST not be greater than 18.2 + hours. + The value 0 has special meaning: use of AdvDefaultLifetime value. + + Default: 0 */ + int HomeAgentLifetime; #define RTADV_MAX_HALIFETIME 65520 /* 18.2 hours */ - /* The TRUE/FALSE value to insert or not an Advertisement Interval - option. See [RFC 6275 7.3] + /* The TRUE/FALSE value to insert or not an Advertisement Interval + option. See [RFC 6275 7.3] - Default: FALSE */ - int AdvIntervalOption; + Default: FALSE */ + int AdvIntervalOption; - /* The value to be placed in the Default Router Preference field of - a router advertisement. See [RFC 4191 2.1 & 2.2] + /* The value to be placed in the Default Router Preference field of + a router advertisement. See [RFC 4191 2.1 & 2.2] - Default: 0 (medium) */ - int DefaultPreference; + Default: 0 (medium) */ + int DefaultPreference; #define RTADV_PREF_MEDIUM 0x0 /* Per RFC4191. */ - u_char inFastRexmit; /* True if we're rexmits faster than usual */ - u_char configured; /* Has operator configured RA? */ - int NumFastReXmitsRemain; /* Loaded first with number of fast rexmits to do */ + u_char inFastRexmit; /* True if we're rexmits faster than usual */ + u_char configured; /* Has operator configured RA? */ + int + NumFastReXmitsRemain; /* Loaded first with number of fast + rexmits to do */ #define RTADV_FAST_REXMIT_PERIOD 1 /* 1 sec */ #define RTADV_NUM_FAST_REXMITS 4 /* Fast Rexmit RA 4 times on certain events */ @@ -183,158 +185,161 @@ struct rtadvconf #endif /* HAVE_RTADV */ /* Zebra interface type - ones of interest. */ -typedef enum -{ - ZEBRA_IF_VXLAN, /* VxLAN interface */ - ZEBRA_IF_VRF, /* VRF device */ - ZEBRA_IF_BRIDGE, /* bridge device */ - ZEBRA_IF_VLAN, /* VLAN sub-interface */ - ZEBRA_IF_OTHER, /* Anything else */ +typedef enum { + ZEBRA_IF_VXLAN, /* VxLAN interface */ + ZEBRA_IF_VRF, /* VRF device */ + ZEBRA_IF_BRIDGE, /* bridge device */ + ZEBRA_IF_VLAN, /* VLAN sub-interface */ + ZEBRA_IF_OTHER, /* Anything else */ } zebra_iftype_t; /* Zebra "slave" interface type */ -typedef enum -{ - ZEBRA_IF_SLAVE_NONE, /* Not a slave */ - ZEBRA_IF_SLAVE_VRF, /* Member of a VRF */ - ZEBRA_IF_SLAVE_BRIDGE, /* Member of a bridge */ - ZEBRA_IF_SLAVE_OTHER, /* Something else - e.g., bond slave */ +typedef enum { + ZEBRA_IF_SLAVE_NONE, /* Not a slave */ + ZEBRA_IF_SLAVE_VRF, /* Member of a VRF */ + ZEBRA_IF_SLAVE_BRIDGE, /* Member of a bridge */ + ZEBRA_IF_SLAVE_OTHER, /* Something else - e.g., bond slave */ } zebra_slave_iftype_t; /* `zebra' daemon local interface structure. */ -struct zebra_if -{ - /* Shutdown configuration. */ - u_char shutdown; +struct zebra_if { + /* Shutdown configuration. */ + u_char shutdown; - /* Multicast configuration. */ - u_char multicast; + /* Multicast configuration. */ + u_char multicast; - /* Router advertise configuration. */ - u_char rtadv_enable; + /* Router advertise configuration. */ + u_char rtadv_enable; - /* Installed addresses chains tree. */ - struct route_table *ipv4_subnets; + /* Installed addresses chains tree. */ + struct route_table *ipv4_subnets; - /* Information about up/down changes */ - unsigned int up_count; - char up_last[QUAGGA_TIMESTAMP_LEN]; - unsigned int down_count; - char down_last[QUAGGA_TIMESTAMP_LEN]; + /* Information about up/down changes */ + unsigned int up_count; + char up_last[QUAGGA_TIMESTAMP_LEN]; + unsigned int down_count; + char down_last[QUAGGA_TIMESTAMP_LEN]; #if defined(HAVE_RTADV) - struct rtadvconf rtadv; - unsigned int ra_sent, ra_rcvd; + struct rtadvconf rtadv; + unsigned int ra_sent, ra_rcvd; #endif /* HAVE_RTADV */ #ifdef HAVE_IRDP - struct irdp_interface irdp; + struct irdp_interface irdp; #endif #ifdef HAVE_STRUCT_SOCKADDR_DL - union { - /* note that sdl_storage is never accessed, it only exists to make space. - * all actual uses refer to sdl - but use sizeof(sdl_storage)! this fits - * best with C aliasing rules. */ - struct sockaddr_dl sdl; - struct sockaddr_storage sdl_storage; - }; + union { + /* note that sdl_storage is never accessed, it only exists to + * make space. + * all actual uses refer to sdl - but use sizeof(sdl_storage)! + * this fits + * best with C aliasing rules. */ + struct sockaddr_dl sdl; + struct sockaddr_storage sdl_storage; + }; #endif #ifdef SUNOS_5 - /* the real IFF_UP state of the primary interface. - * need this to differentiate between all interfaces being - * down (but primary still plumbed) and primary having gone - * ~IFF_UP, and all addresses gone. - */ - u_char primary_state; + /* the real IFF_UP state of the primary interface. + * need this to differentiate between all interfaces being + * down (but primary still plumbed) and primary having gone + * ~IFF_UP, and all addresses gone. + */ + u_char primary_state; #endif /* SUNOS_5 */ - /* ptm enable configuration */ - u_char ptm_enable; + /* ptm enable configuration */ + u_char ptm_enable; - /* Zebra interface and "slave" interface type */ - zebra_iftype_t zif_type; - zebra_slave_iftype_t zif_slave_type; + /* Zebra interface and "slave" interface type */ + zebra_iftype_t zif_type; + zebra_slave_iftype_t zif_slave_type; - /* Additional L2 info, depends on zif_type */ - union zebra_l2if_info l2info; + /* Additional L2 info, depends on zif_type */ + union zebra_l2if_info l2info; - /* For members of a bridge, link to bridge. */ - /* Note: If additional fields become necessary, this can be modified to - * be a pointer to a dynamically allocd struct. - */ - struct zebra_l2info_brslave brslave_info; + /* For members of a bridge, link to bridge. */ + /* Note: If additional fields become necessary, this can be modified to + * be a pointer to a dynamically allocd struct. + */ + struct zebra_l2info_brslave brslave_info; - /* Link fields - for sub-interfaces. */ - ifindex_t link_ifindex; - struct interface *link; + /* Link fields - for sub-interfaces. */ + ifindex_t link_ifindex; + struct interface *link; }; -static inline void -zebra_if_set_ziftype (struct interface *ifp, zebra_iftype_t zif_type, - zebra_slave_iftype_t zif_slave_type) +static inline void zebra_if_set_ziftype(struct interface *ifp, + zebra_iftype_t zif_type, + zebra_slave_iftype_t zif_slave_type) { - struct zebra_if *zif; + struct zebra_if *zif; - zif = (struct zebra_if *)ifp->info; - zif->zif_type = zif_type; - zif->zif_slave_type = zif_slave_type; + zif = (struct zebra_if *)ifp->info; + zif->zif_type = zif_type; + zif->zif_slave_type = zif_slave_type; } -#define IS_ZEBRA_IF_VRF(ifp) \ - (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VRF) - -#define IS_ZEBRA_IF_BRIDGE(ifp) \ - (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_BRIDGE) - -#define IS_ZEBRA_IF_VLAN(ifp) \ - (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VLAN) - -#define IS_ZEBRA_IF_VXLAN(ifp) \ - (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VXLAN) - -#define IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) \ - (((struct zebra_if *)(ifp->info))->zif_slave_type == ZEBRA_IF_SLAVE_BRIDGE) - -#define IS_ZEBRA_IF_VRF_SLAVE(ifp) \ - (((struct zebra_if *)(ifp->info))->zif_slave_type == ZEBRA_IF_SLAVE_VRF) - -extern struct interface *if_lookup_by_index_per_ns (struct zebra_ns *, u_int32_t); -extern struct interface *if_lookup_by_name_per_ns (struct zebra_ns *, const char *); -extern struct interface *if_link_per_ns (struct zebra_ns *, struct interface *); -extern const char *ifindex2ifname_per_ns (struct zebra_ns *, unsigned int); - -extern void if_unlink_per_ns (struct interface *); -extern void if_nbr_ipv6ll_to_ipv4ll_neigh_update (struct interface *ifp, - struct in6_addr *address, int add); -extern void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (struct interface *ifp); -extern void if_delete_update (struct interface *ifp); -extern void if_add_update (struct interface *ifp); -extern void if_up (struct interface *); -extern void if_down (struct interface *); -extern void if_refresh (struct interface *); -extern void if_flags_update (struct interface *, uint64_t); -extern int if_subnet_add (struct interface *, struct connected *); -extern int if_subnet_delete (struct interface *, struct connected *); -extern int ipv6_address_configured (struct interface *ifp); -extern void if_handle_vrf_change (struct interface *ifp, vrf_id_t vrf_id); -extern void zebra_if_update_link (struct interface *ifp, ifindex_t link_ifindex); - -extern void vrf_add_update (struct vrf *vrfp); +#define IS_ZEBRA_IF_VRF(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VRF) + +#define IS_ZEBRA_IF_BRIDGE(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_BRIDGE) + +#define IS_ZEBRA_IF_VLAN(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VLAN) + +#define IS_ZEBRA_IF_VXLAN(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VXLAN) + +#define IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_slave_type \ + == ZEBRA_IF_SLAVE_BRIDGE) + +#define IS_ZEBRA_IF_VRF_SLAVE(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_slave_type == ZEBRA_IF_SLAVE_VRF) + +extern struct interface *if_lookup_by_index_per_ns(struct zebra_ns *, + u_int32_t); +extern struct interface *if_lookup_by_name_per_ns(struct zebra_ns *, + const char *); +extern struct interface *if_link_per_ns(struct zebra_ns *, struct interface *); +extern const char *ifindex2ifname_per_ns(struct zebra_ns *, unsigned int); + +extern void if_unlink_per_ns(struct interface *); +extern void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp, + struct in6_addr *address, + int add); +extern void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(struct interface *ifp); +extern void if_delete_update(struct interface *ifp); +extern void if_add_update(struct interface *ifp); +extern void if_up(struct interface *); +extern void if_down(struct interface *); +extern void if_refresh(struct interface *); +extern void if_flags_update(struct interface *, uint64_t); +extern int if_subnet_add(struct interface *, struct connected *); +extern int if_subnet_delete(struct interface *, struct connected *); +extern int ipv6_address_configured(struct interface *ifp); +extern void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id); +extern void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex); + +extern void vrf_add_update(struct vrf *vrfp); #ifdef HAVE_PROC_NET_DEV -extern void ifstat_update_proc (void); +extern void ifstat_update_proc(void); #endif /* HAVE_PROC_NET_DEV */ #ifdef HAVE_NET_RT_IFLIST -extern void ifstat_update_sysctl (void); +extern void ifstat_update_sysctl(void); #endif /* HAVE_NET_RT_IFLIST */ #ifdef HAVE_PROC_NET_DEV -extern int interface_list_proc (void); +extern int interface_list_proc(void); #endif /* HAVE_PROC_NET_DEV */ #ifdef HAVE_PROC_NET_IF_INET6 -extern int ifaddr_proc_ipv6 (void); +extern int ifaddr_proc_ipv6(void); #endif /* HAVE_PROC_NET_IF_INET6 */ #endif /* _ZEBRA_INTERFACE_H */ diff --git a/zebra/ioctl.c b/zebra/ioctl.c index 25aeea18f..72d98943e 100644 --- a/zebra/ioctl.c +++ b/zebra/ioctl.c @@ -40,551 +40,525 @@ extern struct zebra_privs_t zserv_privs; /* clear and set interface name string */ -void -ifreq_set_name (struct ifreq *ifreq, struct interface *ifp) +void ifreq_set_name(struct ifreq *ifreq, struct interface *ifp) { - strncpy (ifreq->ifr_name, ifp->name, IFNAMSIZ); + strncpy(ifreq->ifr_name, ifp->name, IFNAMSIZ); } /* call ioctl system call */ -int -if_ioctl (u_long request, caddr_t buffer) +int if_ioctl(u_long request, caddr_t buffer) { - int sock; - int ret; - int err = 0; - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - sock = socket (AF_INET, SOCK_DGRAM, 0); - if (sock < 0) - { - int save_errno = errno; - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_err("Cannot create UDP socket: %s", safe_strerror(save_errno)); - exit (1); - } - if ((ret = ioctl (sock, request, buffer)) < 0) - err = errno; - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - close (sock); - - if (ret < 0) - { - errno = err; - return ret; - } - return 0; + int sock; + int ret; + int err = 0; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + int save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_err("Cannot create UDP socket: %s", + safe_strerror(save_errno)); + exit(1); + } + if ((ret = ioctl(sock, request, buffer)) < 0) + err = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + close(sock); + + if (ret < 0) { + errno = err; + return ret; + } + return 0; } -static int -if_ioctl_ipv6 (u_long request, caddr_t buffer) +static int if_ioctl_ipv6(u_long request, caddr_t buffer) { - int sock; - int ret; - int err = 0; - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - sock = socket (AF_INET6, SOCK_DGRAM, 0); - if (sock < 0) - { - int save_errno = errno; - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_err("Cannot create IPv6 datagram socket: %s", - safe_strerror(save_errno)); - exit (1); - } - - if ((ret = ioctl (sock, request, buffer)) < 0) - err = errno; - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - close (sock); - - if (ret < 0) - { - errno = err; - return ret; - } - return 0; + int sock; + int ret; + int err = 0; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) { + int save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_err("Cannot create IPv6 datagram socket: %s", + safe_strerror(save_errno)); + exit(1); + } + + if ((ret = ioctl(sock, request, buffer)) < 0) + err = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + close(sock); + + if (ret < 0) { + errno = err; + return ret; + } + return 0; } /* * get interface metric * -- if value is not avaliable set -1 */ -void -if_get_metric (struct interface *ifp) +void if_get_metric(struct interface *ifp) { #ifdef SIOCGIFMETRIC - struct ifreq ifreq; + struct ifreq ifreq; - ifreq_set_name (&ifreq, ifp); + ifreq_set_name(&ifreq, ifp); - if (if_ioctl (SIOCGIFMETRIC, (caddr_t) &ifreq) < 0) - return; - ifp->metric = ifreq.ifr_metric; - if (ifp->metric == 0) - ifp->metric = 1; -#else /* SIOCGIFMETRIC */ - ifp->metric = -1; + if (if_ioctl(SIOCGIFMETRIC, (caddr_t)&ifreq) < 0) + return; + ifp->metric = ifreq.ifr_metric; + if (ifp->metric == 0) + ifp->metric = 1; +#else /* SIOCGIFMETRIC */ + ifp->metric = -1; #endif /* SIOCGIFMETRIC */ } /* get interface MTU */ -void -if_get_mtu (struct interface *ifp) +void if_get_mtu(struct interface *ifp) { - struct ifreq ifreq; + struct ifreq ifreq; - ifreq_set_name (&ifreq, ifp); + ifreq_set_name(&ifreq, ifp); #if defined(SIOCGIFMTU) - if (if_ioctl (SIOCGIFMTU, (caddr_t) & ifreq) < 0) - { - zlog_info ("Can't lookup mtu by ioctl(SIOCGIFMTU)"); - ifp->mtu6 = ifp->mtu = -1; - return; - } + if (if_ioctl(SIOCGIFMTU, (caddr_t)&ifreq) < 0) { + zlog_info("Can't lookup mtu by ioctl(SIOCGIFMTU)"); + ifp->mtu6 = ifp->mtu = -1; + return; + } #ifdef SUNOS_5 - ifp->mtu6 = ifp->mtu = ifreq.ifr_metric; + ifp->mtu6 = ifp->mtu = ifreq.ifr_metric; #else - ifp->mtu6 = ifp->mtu = ifreq.ifr_mtu; + ifp->mtu6 = ifp->mtu = ifreq.ifr_mtu; #endif /* SUNOS_5 */ - /* propogate */ - zebra_interface_up_update(ifp); + /* propogate */ + zebra_interface_up_update(ifp); #else - zlog_info("Can't lookup mtu on this system"); - ifp->mtu6 = ifp->mtu = -1; + zlog_info("Can't lookup mtu on this system"); + ifp->mtu6 = ifp->mtu = -1; #endif } #ifdef HAVE_NETLINK /* Interface address setting via netlink interface. */ -int -if_set_prefix (struct interface *ifp, struct connected *ifc) +int if_set_prefix(struct interface *ifp, struct connected *ifc) { - return kernel_address_add_ipv4 (ifp, ifc); + return kernel_address_add_ipv4(ifp, ifc); } /* Interface address is removed using netlink interface. */ -int -if_unset_prefix (struct interface *ifp, struct connected *ifc) +int if_unset_prefix(struct interface *ifp, struct connected *ifc) { - return kernel_address_delete_ipv4 (ifp, ifc); + return kernel_address_delete_ipv4(ifp, ifc); } #else /* ! HAVE_NETLINK */ #ifdef HAVE_STRUCT_IFALIASREQ /* Set up interface's IP address, netmask (and broadcas? ). *BSD may has ifaliasreq structure. */ -int -if_set_prefix (struct interface *ifp, struct connected *ifc) +int if_set_prefix(struct interface *ifp, struct connected *ifc) { - int ret; - struct ifaliasreq addreq; - struct sockaddr_in addr; - struct sockaddr_in mask; - struct prefix_ipv4 *p; + int ret; + struct ifaliasreq addreq; + struct sockaddr_in addr; + struct sockaddr_in mask; + struct prefix_ipv4 *p; - p = (struct prefix_ipv4 *) ifc->address; - rib_lookup_and_pushup (p, ifp->vrf_id); + p = (struct prefix_ipv4 *)ifc->address; + rib_lookup_and_pushup(p, ifp->vrf_id); - memset (&addreq, 0, sizeof addreq); - strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); + memset(&addreq, 0, sizeof addreq); + strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); - memset (&addr, 0, sizeof (struct sockaddr_in)); - addr.sin_addr = p->prefix; - addr.sin_family = p->family; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_addr = p->prefix; + addr.sin_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - addr.sin_len = sizeof (struct sockaddr_in); + addr.sin_len = sizeof(struct sockaddr_in); #endif - memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in)); + memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in)); - memset (&mask, 0, sizeof (struct sockaddr_in)); - masklen2ip (p->prefixlen, &mask.sin_addr); - mask.sin_family = p->family; + memset(&mask, 0, sizeof(struct sockaddr_in)); + masklen2ip(p->prefixlen, &mask.sin_addr); + mask.sin_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - mask.sin_len = sizeof (struct sockaddr_in); + mask.sin_len = sizeof(struct sockaddr_in); #endif - memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in)); - - ret = if_ioctl (SIOCAIFADDR, (caddr_t) &addreq); - if (ret < 0) - return ret; - return 0; + memcpy(&addreq.ifra_mask, &mask, sizeof(struct sockaddr_in)); + + ret = if_ioctl(SIOCAIFADDR, (caddr_t)&addreq); + if (ret < 0) + return ret; + return 0; } /* Set up interface's IP address, netmask (and broadcas? ). *BSD may has ifaliasreq structure. */ -int -if_unset_prefix (struct interface *ifp, struct connected *ifc) +int if_unset_prefix(struct interface *ifp, struct connected *ifc) { - int ret; - struct ifaliasreq addreq; - struct sockaddr_in addr; - struct sockaddr_in mask; - struct prefix_ipv4 *p; + int ret; + struct ifaliasreq addreq; + struct sockaddr_in addr; + struct sockaddr_in mask; + struct prefix_ipv4 *p; - p = (struct prefix_ipv4 *)ifc->address; + p = (struct prefix_ipv4 *)ifc->address; - memset (&addreq, 0, sizeof addreq); - strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); + memset(&addreq, 0, sizeof addreq); + strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); - memset (&addr, 0, sizeof (struct sockaddr_in)); - addr.sin_addr = p->prefix; - addr.sin_family = p->family; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_addr = p->prefix; + addr.sin_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - addr.sin_len = sizeof (struct sockaddr_in); + addr.sin_len = sizeof(struct sockaddr_in); #endif - memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in)); + memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in)); - memset (&mask, 0, sizeof (struct sockaddr_in)); - masklen2ip (p->prefixlen, &mask.sin_addr); - mask.sin_family = p->family; + memset(&mask, 0, sizeof(struct sockaddr_in)); + masklen2ip(p->prefixlen, &mask.sin_addr); + mask.sin_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - mask.sin_len = sizeof (struct sockaddr_in); + mask.sin_len = sizeof(struct sockaddr_in); #endif - memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in)); - - ret = if_ioctl (SIOCDIFADDR, (caddr_t) &addreq); - if (ret < 0) - return ret; - return 0; + memcpy(&addreq.ifra_mask, &mask, sizeof(struct sockaddr_in)); + + ret = if_ioctl(SIOCDIFADDR, (caddr_t)&addreq); + if (ret < 0) + return ret; + return 0; } #else /* Set up interface's address, netmask (and broadcas? ). Linux or Solaris uses ifname:number semantics to set IP address aliases. */ -int -if_set_prefix (struct interface *ifp, struct connected *ifc) +int if_set_prefix(struct interface *ifp, struct connected *ifc) { - int ret; - struct ifreq ifreq; - struct sockaddr_in addr; - struct sockaddr_in broad; - struct sockaddr_in mask; - struct prefix_ipv4 ifaddr; - struct prefix_ipv4 *p; - - p = (struct prefix_ipv4 *) ifc->address; - - ifaddr = *p; - - ifreq_set_name (&ifreq, ifp); - - addr.sin_addr = p->prefix; - addr.sin_family = p->family; - memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in)); - ret = if_ioctl (SIOCSIFADDR, (caddr_t) &ifreq); - if (ret < 0) - return ret; - - /* We need mask for make broadcast addr. */ - masklen2ip (p->prefixlen, &mask.sin_addr); - - if (if_is_broadcast (ifp)) - { - apply_mask_ipv4 (&ifaddr); - addr.sin_addr = ifaddr.prefix; - - broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); - broad.sin_family = p->family; - - memcpy (&ifreq.ifr_broadaddr, &broad, sizeof (struct sockaddr_in)); - ret = if_ioctl (SIOCSIFBRDADDR, (caddr_t) &ifreq); - if (ret < 0) - return ret; - } - - mask.sin_family = p->family; + int ret; + struct ifreq ifreq; + struct sockaddr_in addr; + struct sockaddr_in broad; + struct sockaddr_in mask; + struct prefix_ipv4 ifaddr; + struct prefix_ipv4 *p; + + p = (struct prefix_ipv4 *)ifc->address; + + ifaddr = *p; + + ifreq_set_name(&ifreq, ifp); + + addr.sin_addr = p->prefix; + addr.sin_family = p->family; + memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); + ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); + if (ret < 0) + return ret; + + /* We need mask for make broadcast addr. */ + masklen2ip(p->prefixlen, &mask.sin_addr); + + if (if_is_broadcast(ifp)) { + apply_mask_ipv4(&ifaddr); + addr.sin_addr = ifaddr.prefix; + + broad.sin_addr.s_addr = + (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); + broad.sin_family = p->family; + + memcpy(&ifreq.ifr_broadaddr, &broad, + sizeof(struct sockaddr_in)); + ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq); + if (ret < 0) + return ret; + } + + mask.sin_family = p->family; #ifdef SUNOS_5 - memcpy (&mask, &ifreq.ifr_addr, sizeof (mask)); + memcpy(&mask, &ifreq.ifr_addr, sizeof(mask)); #else - memcpy (&ifreq.ifr_netmask, &mask, sizeof (struct sockaddr_in)); + memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in)); #endif /* SUNOS5 */ - ret = if_ioctl (SIOCSIFNETMASK, (caddr_t) &ifreq); - if (ret < 0) - return ret; + ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq); + if (ret < 0) + return ret; - return 0; + return 0; } /* Set up interface's address, netmask (and broadcas? ). Linux or Solaris uses ifname:number semantics to set IP address aliases. */ -int -if_unset_prefix (struct interface *ifp, struct connected *ifc) +int if_unset_prefix(struct interface *ifp, struct connected *ifc) { - int ret; - struct ifreq ifreq; - struct sockaddr_in addr; - struct prefix_ipv4 *p; + int ret; + struct ifreq ifreq; + struct sockaddr_in addr; + struct prefix_ipv4 *p; - p = (struct prefix_ipv4 *) ifc->address; + p = (struct prefix_ipv4 *)ifc->address; - ifreq_set_name (&ifreq, ifp); + ifreq_set_name(&ifreq, ifp); - memset (&addr, 0, sizeof (struct sockaddr_in)); - addr.sin_family = p->family; - memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in)); - ret = if_ioctl (SIOCSIFADDR, (caddr_t) &ifreq); - if (ret < 0) - return ret; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = p->family; + memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); + ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); + if (ret < 0) + return ret; - return 0; + return 0; } #endif /* HAVE_STRUCT_IFALIASREQ */ #endif /* HAVE_NETLINK */ /* get interface flags */ -void -if_get_flags (struct interface *ifp) +void if_get_flags(struct interface *ifp) { - int ret; - struct ifreq ifreq; + int ret; + struct ifreq ifreq; #ifdef HAVE_BSD_LINK_DETECT - struct ifmediareq ifmr; + struct ifmediareq ifmr; #endif /* HAVE_BSD_LINK_DETECT */ - ifreq_set_name (&ifreq, ifp); + ifreq_set_name(&ifreq, ifp); - ret = if_ioctl (SIOCGIFFLAGS, (caddr_t) &ifreq); - if (ret < 0) - { - zlog_err("if_ioctl(SIOCGIFFLAGS) failed: %s", safe_strerror(errno)); - return; - } + ret = if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreq); + if (ret < 0) { + zlog_err("if_ioctl(SIOCGIFFLAGS) failed: %s", + safe_strerror(errno)); + return; + } #ifdef HAVE_BSD_LINK_DETECT /* Detect BSD link-state at start-up */ - /* Per-default, IFF_RUNNING is held high, unless link-detect says - * otherwise - we abuse IFF_RUNNING inside zebra as a link-state flag, - * following practice on Linux and Solaris kernels - */ - SET_FLAG(ifreq.ifr_flags, IFF_RUNNING); - - if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) - { - (void) memset(&ifmr, 0, sizeof(ifmr)); - strncpy (ifmr.ifm_name, ifp->name, IFNAMSIZ); - - /* Seems not all interfaces implement this ioctl */ - if (if_ioctl(SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) - zlog_err("if_ioctl(SIOCGIFMEDIA) failed: %s", safe_strerror(errno)); - else if (ifmr.ifm_status & IFM_AVALID) /* Link state is valid */ - { - if (ifmr.ifm_status & IFM_ACTIVE) - SET_FLAG(ifreq.ifr_flags, IFF_RUNNING); - else - UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING); - } - } + /* Per-default, IFF_RUNNING is held high, unless link-detect says + * otherwise - we abuse IFF_RUNNING inside zebra as a link-state flag, + * following practice on Linux and Solaris kernels + */ + SET_FLAG(ifreq.ifr_flags, IFF_RUNNING); + + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) { + (void)memset(&ifmr, 0, sizeof(ifmr)); + strncpy(ifmr.ifm_name, ifp->name, IFNAMSIZ); + + /* Seems not all interfaces implement this ioctl */ + if (if_ioctl(SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) + zlog_err("if_ioctl(SIOCGIFMEDIA) failed: %s", + safe_strerror(errno)); + else if (ifmr.ifm_status & IFM_AVALID) /* Link state is valid */ + { + if (ifmr.ifm_status & IFM_ACTIVE) + SET_FLAG(ifreq.ifr_flags, IFF_RUNNING); + else + UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING); + } + } #endif /* HAVE_BSD_LINK_DETECT */ - if_flags_update (ifp, (ifreq.ifr_flags & 0x0000ffff)); + if_flags_update(ifp, (ifreq.ifr_flags & 0x0000ffff)); } /* Set interface flags */ -int -if_set_flags (struct interface *ifp, uint64_t flags) +int if_set_flags(struct interface *ifp, uint64_t flags) { - int ret; - struct ifreq ifreq; + int ret; + struct ifreq ifreq; - memset (&ifreq, 0, sizeof(struct ifreq)); - ifreq_set_name (&ifreq, ifp); + memset(&ifreq, 0, sizeof(struct ifreq)); + ifreq_set_name(&ifreq, ifp); - ifreq.ifr_flags = ifp->flags; - ifreq.ifr_flags |= flags; + ifreq.ifr_flags = ifp->flags; + ifreq.ifr_flags |= flags; - ret = if_ioctl (SIOCSIFFLAGS, (caddr_t) &ifreq); + ret = if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq); - if (ret < 0) - { - zlog_info ("can't set interface flags"); - return ret; - } - return 0; + if (ret < 0) { + zlog_info("can't set interface flags"); + return ret; + } + return 0; } /* Unset interface's flag. */ -int -if_unset_flags (struct interface *ifp, uint64_t flags) +int if_unset_flags(struct interface *ifp, uint64_t flags) { - int ret; - struct ifreq ifreq; + int ret; + struct ifreq ifreq; - memset (&ifreq, 0, sizeof(struct ifreq)); - ifreq_set_name (&ifreq, ifp); + memset(&ifreq, 0, sizeof(struct ifreq)); + ifreq_set_name(&ifreq, ifp); - ifreq.ifr_flags = ifp->flags; - ifreq.ifr_flags &= ~flags; + ifreq.ifr_flags = ifp->flags; + ifreq.ifr_flags &= ~flags; - ret = if_ioctl (SIOCSIFFLAGS, (caddr_t) &ifreq); + ret = if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq); - if (ret < 0) - { - zlog_info ("can't unset interface flags"); - return ret; - } - return 0; + if (ret < 0) { + zlog_info("can't unset interface flags"); + return ret; + } + return 0; } #ifdef LINUX_IPV6 #ifndef _LINUX_IN6_H /* linux/include/net/ipv6.h */ -struct in6_ifreq -{ - struct in6_addr ifr6_addr; - u_int32_t ifr6_prefixlen; - int ifr6_ifindex; +struct in6_ifreq { + struct in6_addr ifr6_addr; + u_int32_t ifr6_prefixlen; + int ifr6_ifindex; }; #endif /* _LINUX_IN6_H */ /* Interface's address add/delete functions. */ -int -if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc) { - int ret; - struct prefix_ipv6 *p; - struct in6_ifreq ifreq; + int ret; + struct prefix_ipv6 *p; + struct in6_ifreq ifreq; - p = (struct prefix_ipv6 *) ifc->address; + p = (struct prefix_ipv6 *)ifc->address; - memset (&ifreq, 0, sizeof (struct in6_ifreq)); + memset(&ifreq, 0, sizeof(struct in6_ifreq)); - memcpy (&ifreq.ifr6_addr, &p->prefix, sizeof (struct in6_addr)); - ifreq.ifr6_ifindex = ifp->ifindex; - ifreq.ifr6_prefixlen = p->prefixlen; + memcpy(&ifreq.ifr6_addr, &p->prefix, sizeof(struct in6_addr)); + ifreq.ifr6_ifindex = ifp->ifindex; + ifreq.ifr6_prefixlen = p->prefixlen; - ret = if_ioctl_ipv6 (SIOCSIFADDR, (caddr_t) &ifreq); + ret = if_ioctl_ipv6(SIOCSIFADDR, (caddr_t)&ifreq); - return ret; + return ret; } -int -if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc) { - int ret; - struct prefix_ipv6 *p; - struct in6_ifreq ifreq; + int ret; + struct prefix_ipv6 *p; + struct in6_ifreq ifreq; - p = (struct prefix_ipv6 *) ifc->address; + p = (struct prefix_ipv6 *)ifc->address; - memset (&ifreq, 0, sizeof (struct in6_ifreq)); + memset(&ifreq, 0, sizeof(struct in6_ifreq)); - memcpy (&ifreq.ifr6_addr, &p->prefix, sizeof (struct in6_addr)); - ifreq.ifr6_ifindex = ifp->ifindex; - ifreq.ifr6_prefixlen = p->prefixlen; + memcpy(&ifreq.ifr6_addr, &p->prefix, sizeof(struct in6_addr)); + ifreq.ifr6_ifindex = ifp->ifindex; + ifreq.ifr6_prefixlen = p->prefixlen; - ret = if_ioctl_ipv6 (SIOCDIFADDR, (caddr_t) &ifreq); + ret = if_ioctl_ipv6(SIOCDIFADDR, (caddr_t)&ifreq); - return ret; + return ret; } #else /* LINUX_IPV6 */ #ifdef HAVE_STRUCT_IN6_ALIASREQ #ifndef ND6_INFINITE_LIFETIME #define ND6_INFINITE_LIFETIME 0xffffffffL #endif /* ND6_INFINITE_LIFETIME */ -int -if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc) { - int ret; - struct in6_aliasreq addreq; - struct sockaddr_in6 addr; - struct sockaddr_in6 mask; - struct prefix_ipv6 *p; + int ret; + struct in6_aliasreq addreq; + struct sockaddr_in6 addr; + struct sockaddr_in6 mask; + struct prefix_ipv6 *p; - p = (struct prefix_ipv6 * ) ifc->address; + p = (struct prefix_ipv6 *)ifc->address; - memset (&addreq, 0, sizeof addreq); - strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); + memset(&addreq, 0, sizeof addreq); + strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); - memset (&addr, 0, sizeof (struct sockaddr_in6)); - addr.sin6_addr = p->prefix; - addr.sin6_family = p->family; + memset(&addr, 0, sizeof(struct sockaddr_in6)); + addr.sin6_addr = p->prefix; + addr.sin6_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - addr.sin6_len = sizeof (struct sockaddr_in6); + addr.sin6_len = sizeof(struct sockaddr_in6); #endif - memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in6)); + memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6)); - memset (&mask, 0, sizeof (struct sockaddr_in6)); - masklen2ip6 (p->prefixlen, &mask.sin6_addr); - mask.sin6_family = p->family; + memset(&mask, 0, sizeof(struct sockaddr_in6)); + masklen2ip6(p->prefixlen, &mask.sin6_addr); + mask.sin6_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - mask.sin6_len = sizeof (struct sockaddr_in6); + mask.sin6_len = sizeof(struct sockaddr_in6); #endif - memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6)); - - addreq.ifra_lifetime.ia6t_vltime = 0xffffffff; - addreq.ifra_lifetime.ia6t_pltime = 0xffffffff; - -#ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME - addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; - addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; + memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6)); + + addreq.ifra_lifetime.ia6t_vltime = 0xffffffff; + addreq.ifra_lifetime.ia6t_pltime = 0xffffffff; + +#ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME + addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; + addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; #endif - ret = if_ioctl_ipv6 (SIOCAIFADDR_IN6, (caddr_t) &addreq); - if (ret < 0) - return ret; - return 0; + ret = if_ioctl_ipv6(SIOCAIFADDR_IN6, (caddr_t)&addreq); + if (ret < 0) + return ret; + return 0; } -int -if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc) { - int ret; - struct in6_aliasreq addreq; - struct sockaddr_in6 addr; - struct sockaddr_in6 mask; - struct prefix_ipv6 *p; + int ret; + struct in6_aliasreq addreq; + struct sockaddr_in6 addr; + struct sockaddr_in6 mask; + struct prefix_ipv6 *p; - p = (struct prefix_ipv6 *) ifc->address; + p = (struct prefix_ipv6 *)ifc->address; - memset (&addreq, 0, sizeof addreq); - strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); + memset(&addreq, 0, sizeof addreq); + strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); - memset (&addr, 0, sizeof (struct sockaddr_in6)); - addr.sin6_addr = p->prefix; - addr.sin6_family = p->family; + memset(&addr, 0, sizeof(struct sockaddr_in6)); + addr.sin6_addr = p->prefix; + addr.sin6_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - addr.sin6_len = sizeof (struct sockaddr_in6); + addr.sin6_len = sizeof(struct sockaddr_in6); #endif - memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in6)); + memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6)); - memset (&mask, 0, sizeof (struct sockaddr_in6)); - masklen2ip6 (p->prefixlen, &mask.sin6_addr); - mask.sin6_family = p->family; + memset(&mask, 0, sizeof(struct sockaddr_in6)); + masklen2ip6(p->prefixlen, &mask.sin6_addr); + mask.sin6_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - mask.sin6_len = sizeof (struct sockaddr_in6); + mask.sin6_len = sizeof(struct sockaddr_in6); #endif - memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6)); + memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6)); #ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME - addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; - addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; + addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; + addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; #endif - ret = if_ioctl_ipv6 (SIOCDIFADDR_IN6, (caddr_t) &addreq); - if (ret < 0) - return ret; - return 0; + ret = if_ioctl_ipv6(SIOCDIFADDR_IN6, (caddr_t)&addreq); + if (ret < 0) + return ret; + return 0; } #else -int -if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc) { - return 0; + return 0; } -int -if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc) { - return 0; + return 0; } #endif /* HAVE_STRUCT_IN6_ALIASREQ */ diff --git a/zebra/ioctl.h b/zebra/ioctl.h index b11a90f19..02f8e6b88 100644 --- a/zebra/ioctl.h +++ b/zebra/ioctl.h @@ -23,30 +23,30 @@ #define _ZEBRA_IOCTL_H /* Prototypes. */ -extern void ifreq_set_name (struct ifreq *, struct interface *); -extern int if_ioctl (u_long, caddr_t); +extern void ifreq_set_name(struct ifreq *, struct interface *); +extern int if_ioctl(u_long, caddr_t); -extern int if_set_flags (struct interface *, uint64_t); -extern int if_unset_flags (struct interface *, uint64_t); -extern void if_get_flags (struct interface *); +extern int if_set_flags(struct interface *, uint64_t); +extern int if_unset_flags(struct interface *, uint64_t); +extern void if_get_flags(struct interface *); -extern int if_set_prefix (struct interface *, struct connected *); -extern int if_unset_prefix (struct interface *, struct connected *); +extern int if_set_prefix(struct interface *, struct connected *); +extern int if_unset_prefix(struct interface *, struct connected *); -extern void if_get_metric (struct interface *); -extern void if_get_mtu (struct interface *); +extern void if_get_metric(struct interface *); +extern void if_get_mtu(struct interface *); -extern int if_prefix_add_ipv6 (struct interface *, struct connected *); -extern int if_prefix_delete_ipv6 (struct interface *, struct connected *); +extern int if_prefix_add_ipv6(struct interface *, struct connected *); +extern int if_prefix_delete_ipv6(struct interface *, struct connected *); #ifdef SOLARIS_IPV6 extern int if_ioctl_ipv6(u_long, caddr_t); -extern struct connected *if_lookup_linklocal( struct interface *); +extern struct connected *if_lookup_linklocal(struct interface *); -#define AF_IOCTL(af, request, buffer) \ - ((af) == AF_INET? if_ioctl(request, buffer) : \ - if_ioctl_ipv6(request, buffer)) -#else /* SOLARIS_IPV6 */ +#define AF_IOCTL(af, request, buffer) \ + ((af) == AF_INET ? if_ioctl(request, buffer) \ + : if_ioctl_ipv6(request, buffer)) +#else /* SOLARIS_IPV6 */ #define AF_IOCTL(af, request, buffer) if_ioctl(request, buffer) diff --git a/zebra/ioctl_solaris.c b/zebra/ioctl_solaris.c index 4bdbdaa58..df1554ae6 100644 --- a/zebra/ioctl_solaris.c +++ b/zebra/ioctl_solaris.c @@ -37,245 +37,231 @@ extern struct zebra_privs_t zserv_privs; /* clear and set interface name string */ -void -lifreq_set_name (struct lifreq *lifreq, const char *ifname) +void lifreq_set_name(struct lifreq *lifreq, const char *ifname) { - strncpy (lifreq->lifr_name, ifname, IFNAMSIZ); + strncpy(lifreq->lifr_name, ifname, IFNAMSIZ); } /* call ioctl system call */ -int -if_ioctl (u_long request, caddr_t buffer) +int if_ioctl(u_long request, caddr_t buffer) { - int sock; - int ret; - int err; - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - - sock = socket (AF_INET, SOCK_DGRAM, 0); - if (sock < 0) - { - int save_errno = errno; - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_err("Cannot create UDP socket: %s", safe_strerror(save_errno)); - exit (1); - } - - if ((ret = ioctl (sock, request, buffer)) < 0) - err = errno; - - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - close (sock); - - if (ret < 0) - { - errno = err; - return ret; - } - return 0; + int sock; + int ret; + int err; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + int save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_err("Cannot create UDP socket: %s", + safe_strerror(save_errno)); + exit(1); + } + + if ((ret = ioctl(sock, request, buffer)) < 0) + err = errno; + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + close(sock); + + if (ret < 0) { + errno = err; + return ret; + } + return 0; } -int -if_ioctl_ipv6 (u_long request, caddr_t buffer) +int if_ioctl_ipv6(u_long request, caddr_t buffer) { - int sock; - int ret; - int err; - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - - sock = socket (AF_INET6, SOCK_DGRAM, 0); - if (sock < 0) - { - int save_errno = errno; - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_err("Cannot create IPv6 datagram socket: %s", - safe_strerror(save_errno)); - exit (1); - } - - if ((ret = ioctl (sock, request, buffer)) < 0) - err = errno; - - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - close (sock); - - if (ret < 0) - { - errno = err; - return ret; - } - - return 0; + int sock; + int ret; + int err; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) { + int save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_err("Cannot create IPv6 datagram socket: %s", + safe_strerror(save_errno)); + exit(1); + } + + if ((ret = ioctl(sock, request, buffer)) < 0) + err = errno; + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + close(sock); + + if (ret < 0) { + errno = err; + return ret; + } + + return 0; } /* * get interface metric * -- if value is not avaliable set -1 */ -void -if_get_metric (struct interface *ifp) +void if_get_metric(struct interface *ifp) { - struct lifreq lifreq; - int ret; + struct lifreq lifreq; + int ret; - lifreq_set_name (&lifreq, ifp->name); + lifreq_set_name(&lifreq, ifp->name); - if (ifp->flags & IFF_IPV4) - ret = AF_IOCTL (AF_INET, SIOCGLIFMETRIC, (caddr_t) & lifreq); + if (ifp->flags & IFF_IPV4) + ret = AF_IOCTL(AF_INET, SIOCGLIFMETRIC, (caddr_t)&lifreq); #ifdef SOLARIS_IPV6 - else if (ifp->flags & IFF_IPV6) - ret = AF_IOCTL (AF_INET6, SIOCGLIFMETRIC, (caddr_t) & lifreq); + else if (ifp->flags & IFF_IPV6) + ret = AF_IOCTL(AF_INET6, SIOCGLIFMETRIC, (caddr_t)&lifreq); #endif /* SOLARIS_IPV6 */ - else - ret = -1; - - if (ret < 0) - return; + else + ret = -1; - ifp->metric = lifreq.lifr_metric; + if (ret < 0) + return; - if (ifp->metric == 0) - ifp->metric = 1; + ifp->metric = lifreq.lifr_metric; + + if (ifp->metric == 0) + ifp->metric = 1; } /* get interface MTU */ -void -if_get_mtu (struct interface *ifp) +void if_get_mtu(struct interface *ifp) { - struct lifreq lifreq; - int ret; - u_char changed = 0; - - if (ifp->flags & IFF_IPV4) - { - lifreq_set_name (&lifreq, ifp->name); - ret = AF_IOCTL (AF_INET, SIOCGLIFMTU, (caddr_t) & lifreq); - if (ret < 0) - { - zlog_info ("Can't lookup mtu on %s by ioctl(SIOCGLIFMTU)", - ifp->name); - ifp->mtu = -1; - } - else - { - ifp->mtu = lifreq.lifr_metric; - changed = 1; - } - } - - if (ifp->flags & IFF_IPV6) - { - memset(&lifreq, 0, sizeof(lifreq)); - lifreq_set_name (&lifreq, ifp->name); - - ret = AF_IOCTL (AF_INET6, SIOCGLIFMTU, (caddr_t) & lifreq); - if (ret < 0) - { - zlog_info ("Can't lookup mtu6 on %s by ioctl(SIOCGIFMTU)", ifp->name); - ifp->mtu6 = -1; - } - else - { - ifp->mtu6 = lifreq.lifr_metric; - changed = 1; - } - } - - if (changed) - zebra_interface_up_update(ifp); + struct lifreq lifreq; + int ret; + u_char changed = 0; + + if (ifp->flags & IFF_IPV4) { + lifreq_set_name(&lifreq, ifp->name); + ret = AF_IOCTL(AF_INET, SIOCGLIFMTU, (caddr_t)&lifreq); + if (ret < 0) { + zlog_info( + "Can't lookup mtu on %s by ioctl(SIOCGLIFMTU)", + ifp->name); + ifp->mtu = -1; + } else { + ifp->mtu = lifreq.lifr_metric; + changed = 1; + } + } + + if (ifp->flags & IFF_IPV6) { + memset(&lifreq, 0, sizeof(lifreq)); + lifreq_set_name(&lifreq, ifp->name); + + ret = AF_IOCTL(AF_INET6, SIOCGLIFMTU, (caddr_t)&lifreq); + if (ret < 0) { + zlog_info( + "Can't lookup mtu6 on %s by ioctl(SIOCGIFMTU)", + ifp->name); + ifp->mtu6 = -1; + } else { + ifp->mtu6 = lifreq.lifr_metric; + changed = 1; + } + } + + if (changed) + zebra_interface_up_update(ifp); } /* Set up interface's address, netmask (and broadcast? ). Solaris uses ifname:number semantics to set IP address aliases. */ -int -if_set_prefix (struct interface *ifp, struct connected *ifc) +int if_set_prefix(struct interface *ifp, struct connected *ifc) { - int ret; - struct ifreq ifreq; - struct sockaddr_in addr; - struct sockaddr_in broad; - struct sockaddr_in mask; - struct prefix_ipv4 ifaddr; - struct prefix_ipv4 *p; + int ret; + struct ifreq ifreq; + struct sockaddr_in addr; + struct sockaddr_in broad; + struct sockaddr_in mask; + struct prefix_ipv4 ifaddr; + struct prefix_ipv4 *p; - p = (struct prefix_ipv4 *) ifc->address; + p = (struct prefix_ipv4 *)ifc->address; - ifaddr = *p; + ifaddr = *p; - strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ); + strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ); - addr.sin_addr = p->prefix; - addr.sin_family = p->family; - memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in)); + addr.sin_addr = p->prefix; + addr.sin_family = p->family; + memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); - ret = if_ioctl (SIOCSIFADDR, (caddr_t) & ifreq); + ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); - if (ret < 0) - return ret; + if (ret < 0) + return ret; - /* We need mask for make broadcast addr. */ - masklen2ip (p->prefixlen, &mask.sin_addr); + /* We need mask for make broadcast addr. */ + masklen2ip(p->prefixlen, &mask.sin_addr); - if (if_is_broadcast (ifp)) - { - apply_mask_ipv4 (&ifaddr); - addr.sin_addr = ifaddr.prefix; + if (if_is_broadcast(ifp)) { + apply_mask_ipv4(&ifaddr); + addr.sin_addr = ifaddr.prefix; - broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); - broad.sin_family = p->family; + broad.sin_addr.s_addr = + (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); + broad.sin_family = p->family; - memcpy (&ifreq.ifr_broadaddr, &broad, sizeof (struct sockaddr_in)); - ret = if_ioctl (SIOCSIFBRDADDR, (caddr_t) & ifreq); - if (ret < 0) - return ret; - } + memcpy(&ifreq.ifr_broadaddr, &broad, + sizeof(struct sockaddr_in)); + ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq); + if (ret < 0) + return ret; + } - mask.sin_family = p->family; + mask.sin_family = p->family; #ifdef SUNOS_5 - memcpy (&mask, &ifreq.ifr_addr, sizeof (mask)); + memcpy(&mask, &ifreq.ifr_addr, sizeof(mask)); #else - memcpy (&ifreq.ifr_netmask, &mask, sizeof (struct sockaddr_in)); + memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in)); #endif /* SUNOS_5 */ - ret = if_ioctl (SIOCSIFNETMASK, (caddr_t) & ifreq); + ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq); - return ((ret < 0) ? ret : 0); + return ((ret < 0) ? ret : 0); } /* Set up interface's address, netmask (and broadcast). Solaris uses ifname:number semantics to set IP address aliases. */ -int -if_unset_prefix (struct interface *ifp, struct connected *ifc) +int if_unset_prefix(struct interface *ifp, struct connected *ifc) { - int ret; - struct ifreq ifreq; - struct sockaddr_in addr; - struct prefix_ipv4 *p; + int ret; + struct ifreq ifreq; + struct sockaddr_in addr; + struct prefix_ipv4 *p; + + p = (struct prefix_ipv4 *)ifc->address; - p = (struct prefix_ipv4 *) ifc->address; + strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ); - strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ); + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = p->family; + memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); - memset (&addr, 0, sizeof (struct sockaddr_in)); - addr.sin_family = p->family; - memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in)); + ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); - ret = if_ioctl (SIOCSIFADDR, (caddr_t) & ifreq); - - if (ret < 0) - return ret; + if (ret < 0) + return ret; - return 0; + return 0; } /* Get just the flags for the given name. @@ -283,144 +269,132 @@ if_unset_prefix (struct interface *ifp, struct connected *ifc) * as the bootup interface-list code, which has to peek at per-address * flags in order to figure out which ones should be ignored.. */ -int -if_get_flags_direct (const char *ifname, uint64_t *flags, unsigned int af) +int if_get_flags_direct(const char *ifname, uint64_t *flags, unsigned int af) { - struct lifreq lifreq; - int ret; - - lifreq_set_name (&lifreq, ifname); - - ret = AF_IOCTL (af, SIOCGLIFFLAGS, (caddr_t) &lifreq); - - if (ret) - zlog_debug ("%s: ifname %s, error %s (%d)", - __func__, ifname, safe_strerror (errno), errno); - - *flags = lifreq.lifr_flags; - - return ret; + struct lifreq lifreq; + int ret; + + lifreq_set_name(&lifreq, ifname); + + ret = AF_IOCTL(af, SIOCGLIFFLAGS, (caddr_t)&lifreq); + + if (ret) + zlog_debug("%s: ifname %s, error %s (%d)", __func__, ifname, + safe_strerror(errno), errno); + + *flags = lifreq.lifr_flags; + + return ret; } /* get interface flags */ -void -if_get_flags (struct interface *ifp) +void if_get_flags(struct interface *ifp) { - int ret4 = 0, ret6 = 0; - uint64_t newflags = 0; - uint64_t tmpflags; - - if (ifp->flags & IFF_IPV4) - { - ret4 = if_get_flags_direct (ifp->name, &tmpflags, AF_INET); - - if (!ret4) - newflags |= tmpflags; - else if (errno == ENXIO) - { - /* it's gone */ - UNSET_FLAG (ifp->flags, IFF_UP); - if_flags_update (ifp, ifp->flags); - } - } - - if (ifp->flags & IFF_IPV6) - { - ret6 = if_get_flags_direct (ifp->name, &tmpflags, AF_INET6); - - if (!ret6) - newflags |= tmpflags; - else if (errno == ENXIO) - { - /* it's gone */ - UNSET_FLAG (ifp->flags, IFF_UP); - if_flags_update (ifp, ifp->flags); - } - } - - /* only update flags if one of above succeeded */ - if ( !(ret4 && ret6) ) - if_flags_update (ifp, newflags); + int ret4 = 0, ret6 = 0; + uint64_t newflags = 0; + uint64_t tmpflags; + + if (ifp->flags & IFF_IPV4) { + ret4 = if_get_flags_direct(ifp->name, &tmpflags, AF_INET); + + if (!ret4) + newflags |= tmpflags; + else if (errno == ENXIO) { + /* it's gone */ + UNSET_FLAG(ifp->flags, IFF_UP); + if_flags_update(ifp, ifp->flags); + } + } + + if (ifp->flags & IFF_IPV6) { + ret6 = if_get_flags_direct(ifp->name, &tmpflags, AF_INET6); + + if (!ret6) + newflags |= tmpflags; + else if (errno == ENXIO) { + /* it's gone */ + UNSET_FLAG(ifp->flags, IFF_UP); + if_flags_update(ifp, ifp->flags); + } + } + + /* only update flags if one of above succeeded */ + if (!(ret4 && ret6)) + if_flags_update(ifp, newflags); } /* Set interface flags */ -int -if_set_flags (struct interface *ifp, uint64_t flags) +int if_set_flags(struct interface *ifp, uint64_t flags) { - int ret; - struct lifreq lifreq; - - lifreq_set_name (&lifreq, ifp->name); - - lifreq.lifr_flags = ifp->flags; - lifreq.lifr_flags |= flags; - - if (ifp->flags & IFF_IPV4) - ret = AF_IOCTL (AF_INET, SIOCSLIFFLAGS, (caddr_t) & lifreq); - else if (ifp->flags & IFF_IPV6) - ret = AF_IOCTL (AF_INET6, SIOCSLIFFLAGS, (caddr_t) & lifreq); - else - ret = -1; - - if (ret < 0) - zlog_info ("can't set interface flags on %s: %s", ifp->name, - safe_strerror (errno)); - else - ret = 0; - - return ret; + int ret; + struct lifreq lifreq; + + lifreq_set_name(&lifreq, ifp->name); + + lifreq.lifr_flags = ifp->flags; + lifreq.lifr_flags |= flags; + + if (ifp->flags & IFF_IPV4) + ret = AF_IOCTL(AF_INET, SIOCSLIFFLAGS, (caddr_t)&lifreq); + else if (ifp->flags & IFF_IPV6) + ret = AF_IOCTL(AF_INET6, SIOCSLIFFLAGS, (caddr_t)&lifreq); + else + ret = -1; + + if (ret < 0) + zlog_info("can't set interface flags on %s: %s", ifp->name, + safe_strerror(errno)); + else + ret = 0; + + return ret; } /* Unset interface's flag. */ -int -if_unset_flags (struct interface *ifp, uint64_t flags) +int if_unset_flags(struct interface *ifp, uint64_t flags) { - int ret; - struct lifreq lifreq; - - lifreq_set_name (&lifreq, ifp->name); - - lifreq.lifr_flags = ifp->flags; - lifreq.lifr_flags &= ~flags; - - if (ifp->flags & IFF_IPV4) - ret = AF_IOCTL (AF_INET, SIOCSLIFFLAGS, (caddr_t) & lifreq); - else if (ifp->flags & IFF_IPV6) - ret = AF_IOCTL (AF_INET6, SIOCSLIFFLAGS, (caddr_t) & lifreq); - else - ret = -1; - - if (ret < 0) - zlog_info ("can't unset interface flags"); - else - ret = 0; - - return ret; + int ret; + struct lifreq lifreq; + + lifreq_set_name(&lifreq, ifp->name); + + lifreq.lifr_flags = ifp->flags; + lifreq.lifr_flags &= ~flags; + + if (ifp->flags & IFF_IPV4) + ret = AF_IOCTL(AF_INET, SIOCSLIFFLAGS, (caddr_t)&lifreq); + else if (ifp->flags & IFF_IPV6) + ret = AF_IOCTL(AF_INET6, SIOCSLIFFLAGS, (caddr_t)&lifreq); + else + ret = -1; + + if (ret < 0) + zlog_info("can't unset interface flags"); + else + ret = 0; + + return ret; } /* Interface's address add/delete functions. */ -int -if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc) { - char addrbuf[PREFIX_STRLEN]; - - zlog_warn ("Can't set %s on interface %s", - prefix2str(ifc->address, addrbuf, sizeof(addrbuf)), - ifp->name); + char addrbuf[PREFIX_STRLEN]; - return 0; + zlog_warn("Can't set %s on interface %s", + prefix2str(ifc->address, addrbuf, sizeof(addrbuf)), + ifp->name); + return 0; } -int -if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc) { - char addrbuf[PREFIX_STRLEN]; - - zlog_warn ("Can't delete %s on interface %s", - prefix2str(ifc->address, addrbuf, sizeof(addrbuf)), - ifp->name); + char addrbuf[PREFIX_STRLEN]; - return 0; + zlog_warn("Can't delete %s on interface %s", + prefix2str(ifc->address, addrbuf, sizeof(addrbuf)), + ifp->name); + return 0; } diff --git a/zebra/ioctl_solaris.h b/zebra/ioctl_solaris.h index dbf93bdca..3507e563c 100644 --- a/zebra/ioctl_solaris.h +++ b/zebra/ioctl_solaris.h @@ -22,7 +22,7 @@ #ifndef _ZEBRA_IF_IOCTL_SOLARIS_H #define _ZEBRA_IF_IOCTL_SOLARIS_H -void lifreq_set_name (struct lifreq *, const char *); -int if_get_flags_direct (const char *, uint64_t *, unsigned int af); +void lifreq_set_name(struct lifreq *, const char *); +int if_get_flags_direct(const char *, uint64_t *, unsigned int af); #endif /* _ZEBRA_IF_IOCTL_SOLARIS_H */ diff --git a/zebra/ipforward.h b/zebra/ipforward.h index 5401ed08a..fe9f2db91 100644 --- a/zebra/ipforward.h +++ b/zebra/ipforward.h @@ -21,12 +21,12 @@ #ifndef _ZEBRA_IPFORWARD_H #define _ZEBRA_IPFORWARD_H -extern int ipforward (void); -extern int ipforward_on (void); -extern int ipforward_off (void); +extern int ipforward(void); +extern int ipforward_on(void); +extern int ipforward_off(void); -extern int ipforward_ipv6 (void); -extern int ipforward_ipv6_on (void); -extern int ipforward_ipv6_off (void); +extern int ipforward_ipv6(void); +extern int ipforward_ipv6_on(void); +extern int ipforward_ipv6_off(void); #endif /* _ZEBRA_IPFORWARD_H */ diff --git a/zebra/ipforward_proc.c b/zebra/ipforward_proc.c index 200c50c0a..c3dcdda55 100644 --- a/zebra/ipforward_proc.c +++ b/zebra/ipforward_proc.c @@ -30,169 +30,166 @@ extern struct zebra_privs_t zserv_privs; char proc_net_snmp[] = "/proc/net/snmp"; -static void -dropline (FILE *fp) +static void dropline(FILE *fp) { - int c; + int c; - while ((c = getc (fp)) != '\n') - ; + while ((c = getc(fp)) != '\n') + ; } -int -ipforward (void) +int ipforward(void) { - FILE *fp; - int ipforwarding = 0; - char buf[10]; - - fp = fopen (proc_net_snmp, "r"); - - if (fp == NULL) - return -1; - - /* We don't care about the first line. */ - dropline (fp); - - /* Get ip_statistics.IpForwarding : - 1 => ip forwarding enabled - 2 => ip forwarding off. */ - if (fgets (buf, 6, fp)) - sscanf (buf, "Ip: %d", &ipforwarding); - - fclose(fp); - - if (ipforwarding == 1) - return 1; - - return 0; + FILE *fp; + int ipforwarding = 0; + char buf[10]; + + fp = fopen(proc_net_snmp, "r"); + + if (fp == NULL) + return -1; + + /* We don't care about the first line. */ + dropline(fp); + + /* Get ip_statistics.IpForwarding : + 1 => ip forwarding enabled + 2 => ip forwarding off. */ + if (fgets(buf, 6, fp)) + sscanf(buf, "Ip: %d", &ipforwarding); + + fclose(fp); + + if (ipforwarding == 1) + return 1; + + return 0; } /* char proc_ipv4_forwarding[] = "/proc/sys/net/ipv4/conf/all/forwarding"; */ char proc_ipv4_forwarding[] = "/proc/sys/net/ipv4/ip_forward"; -int -ipforward_on (void) +int ipforward_on(void) { - FILE *fp; - - if ( zserv_privs.change(ZPRIVS_RAISE) ) - zlog_err ("Can't raise privileges, %s", safe_strerror (errno) ); + FILE *fp; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges, %s", safe_strerror(errno)); - fp = fopen (proc_ipv4_forwarding, "w"); + fp = fopen(proc_ipv4_forwarding, "w"); - if (fp == NULL) { - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); - return -1; - } + if (fp == NULL) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", + safe_strerror(errno)); + return -1; + } - fprintf (fp, "1\n"); + fprintf(fp, "1\n"); - fclose (fp); + fclose(fp); - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", safe_strerror(errno)); - return ipforward (); + return ipforward(); } -int -ipforward_off (void) +int ipforward_off(void) { - FILE *fp; + FILE *fp; - if ( zserv_privs.change(ZPRIVS_RAISE) ) - zlog_err ("Can't raise privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges, %s", safe_strerror(errno)); - fp = fopen (proc_ipv4_forwarding, "w"); + fp = fopen(proc_ipv4_forwarding, "w"); - if (fp == NULL) { - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); - return -1; - } + if (fp == NULL) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", + safe_strerror(errno)); + return -1; + } - fprintf (fp, "0\n"); + fprintf(fp, "0\n"); - fclose (fp); + fclose(fp); - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", safe_strerror(errno)); - return ipforward (); + return ipforward(); } char proc_ipv6_forwarding[] = "/proc/sys/net/ipv6/conf/all/forwarding"; -int -ipforward_ipv6 (void) +int ipforward_ipv6(void) { - FILE *fp; - char buf[5]; - int ipforwarding = 0; + FILE *fp; + char buf[5]; + int ipforwarding = 0; - fp = fopen (proc_ipv6_forwarding, "r"); + fp = fopen(proc_ipv6_forwarding, "r"); - if (fp == NULL) - return -1; + if (fp == NULL) + return -1; - if (fgets (buf, 2, fp)) - sscanf (buf, "%d", &ipforwarding); + if (fgets(buf, 2, fp)) + sscanf(buf, "%d", &ipforwarding); - fclose (fp); - return ipforwarding; + fclose(fp); + return ipforwarding; } -int -ipforward_ipv6_on (void) +int ipforward_ipv6_on(void) { - FILE *fp; + FILE *fp; - if ( zserv_privs.change(ZPRIVS_RAISE) ) - zlog_err ("Can't raise privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges, %s", safe_strerror(errno)); - fp = fopen (proc_ipv6_forwarding, "w"); + fp = fopen(proc_ipv6_forwarding, "w"); - if (fp == NULL) { - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); - return -1; - } + if (fp == NULL) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", + safe_strerror(errno)); + return -1; + } - fprintf (fp, "1\n"); + fprintf(fp, "1\n"); - fclose (fp); + fclose(fp); - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", safe_strerror(errno)); - return ipforward_ipv6 (); + return ipforward_ipv6(); } -int -ipforward_ipv6_off (void) +int ipforward_ipv6_off(void) { - FILE *fp; + FILE *fp; - if ( zserv_privs.change(ZPRIVS_RAISE) ) - zlog_err ("Can't raise privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges, %s", safe_strerror(errno)); - fp = fopen (proc_ipv6_forwarding, "w"); + fp = fopen(proc_ipv6_forwarding, "w"); - if (fp == NULL) { - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); - return -1; - } + if (fp == NULL) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", + safe_strerror(errno)); + return -1; + } - fprintf (fp, "0\n"); + fprintf(fp, "0\n"); - fclose (fp); + fclose(fp); - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", safe_strerror(errno)); - return ipforward_ipv6 (); + return ipforward_ipv6(); } diff --git a/zebra/ipforward_solaris.c b/zebra/ipforward_solaris.c index 09f145e81..0d6b7dac0 100644 --- a/zebra/ipforward_solaris.c +++ b/zebra/ipforward_solaris.c @@ -46,117 +46,110 @@ extern struct zebra_privs_t zserv_privs; ** name of the parameter being referenced. */ -static int -solaris_nd(const int cmd, const char* parameter, const int value) +static int solaris_nd(const int cmd, const char *parameter, const int value) { #define ND_BUFFER_SIZE 1024 - int fd; - char nd_buf[ND_BUFFER_SIZE]; - struct strioctl strioctl; - const char* device = IP_DEV_NAME; - int retval; - memset(nd_buf, '\0', ND_BUFFER_SIZE); - /* - ** ND_SET takes a NULL delimited list of strings further terminated - ** buy a NULL. ND_GET returns a list in a similar layout, although - ** here we only use the first result. - */ - if (cmd == ND_SET) - snprintf(nd_buf, ND_BUFFER_SIZE, "%s%c%d%c", parameter, '\0', value,'\0'); - else if (cmd == ND_GET) - snprintf(nd_buf, ND_BUFFER_SIZE, "%s", parameter); - else { - zlog_err("internal error - inappropriate command given to " - "solaris_nd()%s:%d", __FILE__, __LINE__); - return -1; - } + int fd; + char nd_buf[ND_BUFFER_SIZE]; + struct strioctl strioctl; + const char *device = IP_DEV_NAME; + int retval; + memset(nd_buf, '\0', ND_BUFFER_SIZE); + /* + ** ND_SET takes a NULL delimited list of strings further terminated + ** buy a NULL. ND_GET returns a list in a similar layout, although + ** here we only use the first result. + */ + if (cmd == ND_SET) + snprintf(nd_buf, ND_BUFFER_SIZE, "%s%c%d%c", parameter, '\0', + value, '\0'); + else if (cmd == ND_GET) + snprintf(nd_buf, ND_BUFFER_SIZE, "%s", parameter); + else { + zlog_err( + "internal error - inappropriate command given to " + "solaris_nd()%s:%d", + __FILE__, __LINE__); + return -1; + } - strioctl.ic_cmd = cmd; - strioctl.ic_timout = 0; - strioctl.ic_len = ND_BUFFER_SIZE; - strioctl.ic_dp = nd_buf; - - if ( zserv_privs.change (ZPRIVS_RAISE) ) - zlog_err ("solaris_nd: Can't raise privileges"); - if ((fd = open (device, O_RDWR)) < 0) - { - zlog_warn("failed to open device %s - %s", device, safe_strerror(errno)); - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("solaris_nd: Can't lower privileges"); - return -1; - } - if (ioctl (fd, I_STR, &strioctl) < 0) - { - int save_errno = errno; - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("solaris_nd: Can't lower privileges"); - close (fd); - zlog_warn("ioctl I_STR failed on device %s - %s", - device, safe_strerror(save_errno)); - return -1; - } - close(fd); - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("solaris_nd: Can't lower privileges"); - - if (cmd == ND_GET) - { - errno = 0; - retval = atoi(nd_buf); - if (errno) - { - zlog_warn("failed to convert returned value to integer - %s", - safe_strerror(errno)); - retval = -1; - } - } - else - { - retval = 0; - } - return retval; + strioctl.ic_cmd = cmd; + strioctl.ic_timout = 0; + strioctl.ic_len = ND_BUFFER_SIZE; + strioctl.ic_dp = nd_buf; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("solaris_nd: Can't raise privileges"); + if ((fd = open(device, O_RDWR)) < 0) { + zlog_warn("failed to open device %s - %s", device, + safe_strerror(errno)); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("solaris_nd: Can't lower privileges"); + return -1; + } + if (ioctl(fd, I_STR, &strioctl) < 0) { + int save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("solaris_nd: Can't lower privileges"); + close(fd); + zlog_warn("ioctl I_STR failed on device %s - %s", device, + safe_strerror(save_errno)); + return -1; + } + close(fd); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("solaris_nd: Can't lower privileges"); + + if (cmd == ND_GET) { + errno = 0; + retval = atoi(nd_buf); + if (errno) { + zlog_warn( + "failed to convert returned value to integer - %s", + safe_strerror(errno)); + retval = -1; + } + } else { + retval = 0; + } + return retval; } -static int -solaris_nd_set(const char* parameter, const int value) { - return solaris_nd(ND_SET, parameter, value); +static int solaris_nd_set(const char *parameter, const int value) +{ + return solaris_nd(ND_SET, parameter, value); } -static int -solaris_nd_get(const char* parameter) { - return solaris_nd(ND_GET, parameter, 0); +static int solaris_nd_get(const char *parameter) +{ + return solaris_nd(ND_GET, parameter, 0); } -int -ipforward(void) +int ipforward(void) { - return solaris_nd_get("ip_forwarding"); + return solaris_nd_get("ip_forwarding"); } -int -ipforward_on (void) +int ipforward_on(void) { - (void) solaris_nd_set("ip_forwarding", 1); - return ipforward(); + (void)solaris_nd_set("ip_forwarding", 1); + return ipforward(); } -int -ipforward_off (void) +int ipforward_off(void) { - (void) solaris_nd_set("ip_forwarding", 0); - return ipforward(); + (void)solaris_nd_set("ip_forwarding", 0); + return ipforward(); } int ipforward_ipv6(void) { - return solaris_nd_get("ip6_forwarding"); + return solaris_nd_get("ip6_forwarding"); } -int -ipforward_ipv6_on (void) +int ipforward_ipv6_on(void) { - (void) solaris_nd_set("ip6_forwarding", 1); - return ipforward_ipv6(); + (void)solaris_nd_set("ip6_forwarding", 1); + return ipforward_ipv6(); } -int -ipforward_ipv6_off (void) +int ipforward_ipv6_off(void) { - (void) solaris_nd_set("ip6_forwarding", 0); - return ipforward_ipv6(); + (void)solaris_nd_set("ip6_forwarding", 0); + return ipforward_ipv6(); } diff --git a/zebra/ipforward_sysctl.c b/zebra/ipforward_sysctl.c index a381eb2d7..00be92bb6 100644 --- a/zebra/ipforward_sysctl.c +++ b/zebra/ipforward_sysctl.c @@ -29,144 +29,121 @@ extern struct zebra_privs_t zserv_privs; /* IPv4 forwarding control MIB. */ -int mib[MIB_SIZ] = -{ - CTL_NET, - PF_INET, - IPPROTO_IP, - IPCTL_FORWARDING -}; +int mib[MIB_SIZ] = {CTL_NET, PF_INET, IPPROTO_IP, IPCTL_FORWARDING}; -int -ipforward (void) +int ipforward(void) { - size_t len; - int ipforwarding = 0; - - len = sizeof ipforwarding; - if (sysctl (mib, MIB_SIZ, &ipforwarding, &len, 0, 0) < 0) - { - zlog_warn ("Can't get ipforwarding value"); - return -1; - } - return ipforwarding; + size_t len; + int ipforwarding = 0; + + len = sizeof ipforwarding; + if (sysctl(mib, MIB_SIZ, &ipforwarding, &len, 0, 0) < 0) { + zlog_warn("Can't get ipforwarding value"); + return -1; + } + return ipforwarding; } -int -ipforward_on (void) +int ipforward_on(void) { - size_t len; - int ipforwarding = 1; - - len = sizeof ipforwarding; - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - if (sysctl (mib, MIB_SIZ, NULL, NULL, &ipforwarding, len) < 0) - { - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_warn ("Can't set ipforwarding on"); - return -1; - } - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - return ipforwarding; + size_t len; + int ipforwarding = 1; + + len = sizeof ipforwarding; + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + if (sysctl(mib, MIB_SIZ, NULL, NULL, &ipforwarding, len) < 0) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_warn("Can't set ipforwarding on"); + return -1; + } + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + return ipforwarding; } -int -ipforward_off (void) +int ipforward_off(void) { - size_t len; - int ipforwarding = 0; - - len = sizeof ipforwarding; - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - if (sysctl (mib, MIB_SIZ, NULL, NULL, &ipforwarding, len) < 0) - { - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_warn ("Can't set ipforwarding on"); - return -1; - } - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - return ipforwarding; + size_t len; + int ipforwarding = 0; + + len = sizeof ipforwarding; + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + if (sysctl(mib, MIB_SIZ, NULL, NULL, &ipforwarding, len) < 0) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_warn("Can't set ipforwarding on"); + return -1; + } + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + return ipforwarding; } /* IPv6 forwarding control MIB. */ -int mib_ipv6[MIB_SIZ] = -{ - CTL_NET, - PF_INET6, +int mib_ipv6[MIB_SIZ] = {CTL_NET, PF_INET6, #if defined(KAME) - IPPROTO_IPV6, - IPV6CTL_FORWARDING -#else /* NOT KAME */ - IPPROTO_IP, - IP6CTL_FORWARDING + IPPROTO_IPV6, IPV6CTL_FORWARDING +#else /* NOT KAME */ + IPPROTO_IP, IP6CTL_FORWARDING #endif /* KAME */ -}; +}; -int -ipforward_ipv6 (void) +int ipforward_ipv6(void) { - size_t len; - int ip6forwarding = 0; - - len = sizeof ip6forwarding; - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - if (sysctl (mib_ipv6, MIB_SIZ, &ip6forwarding, &len, 0, 0) < 0) - { - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_warn ("can't get ip6forwarding value"); - return -1; - } - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - return ip6forwarding; + size_t len; + int ip6forwarding = 0; + + len = sizeof ip6forwarding; + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + if (sysctl(mib_ipv6, MIB_SIZ, &ip6forwarding, &len, 0, 0) < 0) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_warn("can't get ip6forwarding value"); + return -1; + } + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + return ip6forwarding; } -int -ipforward_ipv6_on (void) +int ipforward_ipv6_on(void) { - size_t len; - int ip6forwarding = 1; - - len = sizeof ip6forwarding; - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - if (sysctl (mib_ipv6, MIB_SIZ, NULL, NULL, &ip6forwarding, len) < 0) - { - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_warn ("can't get ip6forwarding value"); - return -1; - } - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - return ip6forwarding; + size_t len; + int ip6forwarding = 1; + + len = sizeof ip6forwarding; + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + if (sysctl(mib_ipv6, MIB_SIZ, NULL, NULL, &ip6forwarding, len) < 0) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_warn("can't get ip6forwarding value"); + return -1; + } + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + return ip6forwarding; } -int -ipforward_ipv6_off (void) +int ipforward_ipv6_off(void) { - size_t len; - int ip6forwarding = 0; - - len = sizeof ip6forwarding; - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - if (sysctl (mib_ipv6, MIB_SIZ, NULL, NULL, &ip6forwarding, len) < 0) - { - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_warn ("can't get ip6forwarding value"); - return -1; - } - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - return ip6forwarding; + size_t len; + int ip6forwarding = 0; + + len = sizeof ip6forwarding; + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + if (sysctl(mib_ipv6, MIB_SIZ, NULL, NULL, &ip6forwarding, len) < 0) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_warn("can't get ip6forwarding value"); + return -1; + } + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + return ip6forwarding; } diff --git a/zebra/irdp.h b/zebra/irdp.h index 975e378b7..01308b915 100644 --- a/zebra/irdp.h +++ b/zebra/irdp.h @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* +/* * This file is modified and completed for the Zebra IRDP implementation * by Robert Olsson, Swedish University of Agricultural Sciences */ @@ -68,8 +68,8 @@ #define IRDP_RX_BUF 1500 -/* - Comments comes from RFC1256 ICMP Router Discovery Messages. +/* + Comments comes from RFC1256 ICMP Router Discovery Messages. The IP destination address to be used for multicast Router Advertisements sent from the interface. The only permissible @@ -79,26 +79,26 @@ all listening hosts support IP multicast.) Default: 224.0.0.1 if the router supports IP multicast on the - interface, else 255.255.255.255 + interface, else 255.255.255.255 The maximum time allowed between sending multicast Router Advertisements from the interface, in seconds. Must be no less than 4 seconds and no greater than 1800 seconds. - Default: 600 seconds + Default: 600 seconds The minimum time allowed between sending unsolicited multicast Router Advertisements from the interface, in seconds. Must be no less than 3 seconds and no greater than MaxAdvertisementInterval. - Default: 0.75 * MaxAdvertisementInterval + Default: 0.75 * MaxAdvertisementInterval The value to be placed in the Lifetime field of Router Advertisements sent from the interface, in seconds. Must be no less than MaxAdvertisementInterval and no greater than 9000 seconds. - Default: 3 * MaxAdvertisementInterval + Default: 3 * MaxAdvertisementInterval The preferability of the address as a default router address, relative to other router addresses on the same subnet. A 32-bit, @@ -107,16 +107,15 @@ that the address, even though it may be advertised, is not to be used by neighboring hosts as a default router address. - Default: 0 + Default: 0 */ -struct irdp_interface -{ - unsigned long MaxAdvertInterval; - unsigned long MinAdvertInterval; - unsigned long Preference; +struct irdp_interface { + unsigned long MaxAdvertInterval; + unsigned long MinAdvertInterval; + unsigned long Preference; - u_int32_t flags; + u_int32_t flags; #define IF_ACTIVE (1<<0) /* ICMP Active */ #define IF_BROADCAST (1<<1) /* 255.255.255.255 */ @@ -126,31 +125,29 @@ struct irdp_interface #define IF_DEBUG_MISC (1<<5) #define IF_SHUTDOWN (1<<6) - struct interface *ifp; - struct thread *t_advertise; - unsigned long irdp_sent; - u_int16_t Lifetime; - - struct list *AdvPrefList; + struct interface *ifp; + struct thread *t_advertise; + unsigned long irdp_sent; + u_int16_t Lifetime; + struct list *AdvPrefList; }; -struct Adv -{ - struct in_addr ip; - int pref; +struct Adv { + struct in_addr ip; + int pref; }; extern void irdp_init(void); extern int irdp_sock_init(void); extern void irdp_finish(void); -extern void irdp_config_write (struct vty *, struct interface *); +extern void irdp_config_write(struct vty *, struct interface *); extern int irdp_send_thread(struct thread *t_advert); extern void irdp_advert_off(struct interface *ifp); -extern void process_solicit (struct interface *ifp); +extern void process_solicit(struct interface *ifp); extern int irdp_read_raw(struct thread *r); -extern void send_packet(struct interface *ifp, struct stream *s, - u_int32_t dst, struct prefix *p, u_int32_t ttl); +extern void send_packet(struct interface *ifp, struct stream *s, u_int32_t dst, + struct prefix *p, u_int32_t ttl); #endif /* _IRDP_H */ diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c index 323e94818..5682e12e6 100644 --- a/zebra/irdp_interface.c +++ b/zebra/irdp_interface.c @@ -63,311 +63,291 @@ extern int irdp_sock; -static const char * -inet_2a(u_int32_t a, char *b) +static const char *inet_2a(u_int32_t a, char *b) { - sprintf(b, "%u.%u.%u.%u", - (a ) & 0xFF, - (a>> 8) & 0xFF, - (a>>16) & 0xFF, - (a>>24) & 0xFF); - return b; + sprintf(b, "%u.%u.%u.%u", (a)&0xFF, (a >> 8) & 0xFF, (a >> 16) & 0xFF, + (a >> 24) & 0xFF); + return b; } -static struct prefix * -irdp_get_prefix(struct interface *ifp) +static struct prefix *irdp_get_prefix(struct interface *ifp) { - struct listnode *node; - struct connected *ifc; + struct listnode *node; + struct connected *ifc; - if (ifp->connected) - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) - return ifc->address; + if (ifp->connected) + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) + return ifc->address; - return NULL; + return NULL; } /* Join to the add/leave multicast group. */ -static int -if_group (struct interface *ifp, - int sock, - u_int32_t group, - int add_leave) +static int if_group(struct interface *ifp, int sock, u_int32_t group, + int add_leave) { - struct ip_mreq m; - struct prefix *p; - int ret; - char b1[INET_ADDRSTRLEN]; - - memset (&m, 0, sizeof (m)); - m.imr_multiaddr.s_addr = htonl (group); - p = irdp_get_prefix(ifp); - - if(!p) { - zlog_warn ("IRDP: can't get address for %s", ifp->name); - return 1; - } - - m.imr_interface = p->u.prefix4; - - ret = setsockopt (sock, IPPROTO_IP, add_leave, - (char *) &m, sizeof (struct ip_mreq)); - if (ret < 0) - zlog_warn ("IRDP: %s can't setsockopt %s: %s", - add_leave == IP_ADD_MEMBERSHIP? "join group":"leave group", - inet_2a(group, b1), - safe_strerror (errno)); - - return ret; + struct ip_mreq m; + struct prefix *p; + int ret; + char b1[INET_ADDRSTRLEN]; + + memset(&m, 0, sizeof(m)); + m.imr_multiaddr.s_addr = htonl(group); + p = irdp_get_prefix(ifp); + + if (!p) { + zlog_warn("IRDP: can't get address for %s", ifp->name); + return 1; + } + + m.imr_interface = p->u.prefix4; + + ret = setsockopt(sock, IPPROTO_IP, add_leave, (char *)&m, + sizeof(struct ip_mreq)); + if (ret < 0) + zlog_warn("IRDP: %s can't setsockopt %s: %s", + add_leave == IP_ADD_MEMBERSHIP ? "join group" + : "leave group", + inet_2a(group, b1), safe_strerror(errno)); + + return ret; } -static int -if_add_group (struct interface *ifp) +static int if_add_group(struct interface *ifp) { - struct zebra_if *zi= ifp->info; - struct irdp_interface *irdp = &zi->irdp; - int ret; - char b1[INET_ADDRSTRLEN]; - - ret = if_group (ifp, irdp_sock, INADDR_ALLRTRS_GROUP, IP_ADD_MEMBERSHIP); - if (ret < 0) { - return ret; - } - - if(irdp->flags & IF_DEBUG_MISC ) - zlog_debug("IRDP: Adding group %s for %s", - inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), - ifp->name); - return 0; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + int ret; + char b1[INET_ADDRSTRLEN]; + + ret = if_group(ifp, irdp_sock, INADDR_ALLRTRS_GROUP, IP_ADD_MEMBERSHIP); + if (ret < 0) { + return ret; + } + + if (irdp->flags & IF_DEBUG_MISC) + zlog_debug("IRDP: Adding group %s for %s", + inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), ifp->name); + return 0; } -static int -if_drop_group (struct interface *ifp) +static int if_drop_group(struct interface *ifp) { - struct zebra_if *zi= ifp->info; - struct irdp_interface *irdp = &zi->irdp; - int ret; - char b1[INET_ADDRSTRLEN]; - - ret = if_group (ifp, irdp_sock, INADDR_ALLRTRS_GROUP, IP_DROP_MEMBERSHIP); - if (ret < 0) - return ret; - - if(irdp->flags & IF_DEBUG_MISC) - zlog_debug("IRDP: Leaving group %s for %s", - inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), - ifp->name); - return 0; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + int ret; + char b1[INET_ADDRSTRLEN]; + + ret = if_group(ifp, irdp_sock, INADDR_ALLRTRS_GROUP, + IP_DROP_MEMBERSHIP); + if (ret < 0) + return ret; + + if (irdp->flags & IF_DEBUG_MISC) + zlog_debug("IRDP: Leaving group %s for %s", + inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), ifp->name); + return 0; } -static void -if_set_defaults(struct interface *ifp) +static void if_set_defaults(struct interface *ifp) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; - irdp->MaxAdvertInterval = IRDP_MAXADVERTINTERVAL; - irdp->MinAdvertInterval = IRDP_MINADVERTINTERVAL; - irdp->Preference = IRDP_PREFERENCE; - irdp->Lifetime = IRDP_LIFETIME; + irdp->MaxAdvertInterval = IRDP_MAXADVERTINTERVAL; + irdp->MinAdvertInterval = IRDP_MINADVERTINTERVAL; + irdp->Preference = IRDP_PREFERENCE; + irdp->Lifetime = IRDP_LIFETIME; } -static struct Adv *Adv_new (void) +static struct Adv *Adv_new(void) { - return XCALLOC (MTYPE_TMP, sizeof (struct Adv)); + return XCALLOC(MTYPE_TMP, sizeof(struct Adv)); } -static void -Adv_free (struct Adv *adv) +static void Adv_free(struct Adv *adv) { - XFREE (MTYPE_TMP, adv); + XFREE(MTYPE_TMP, adv); } -static void -irdp_if_start(struct interface *ifp, int multicast, int set_defaults) +static void irdp_if_start(struct interface *ifp, int multicast, + int set_defaults) { - struct zebra_if *zi= ifp->info; - struct irdp_interface *irdp = &zi->irdp; - struct listnode *node; - struct connected *ifc; - u_int32_t timer, seed; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + struct listnode *node; + struct connected *ifc; + u_int32_t timer, seed; - if (irdp->flags & IF_ACTIVE ) { - zlog_warn("IRDP: Interface is already active %s", ifp->name); - return; - } - if ((irdp_sock < 0) && ((irdp_sock = irdp_sock_init()) < 0)) { - zlog_warn("IRDP: Cannot activate interface %s (cannot create " - "IRDP socket)", ifp->name); - return; - } - irdp->flags |= IF_ACTIVE; + if (irdp->flags & IF_ACTIVE) { + zlog_warn("IRDP: Interface is already active %s", ifp->name); + return; + } + if ((irdp_sock < 0) && ((irdp_sock = irdp_sock_init()) < 0)) { + zlog_warn( + "IRDP: Cannot activate interface %s (cannot create " + "IRDP socket)", + ifp->name); + return; + } + irdp->flags |= IF_ACTIVE; - if(!multicast) - irdp->flags |= IF_BROADCAST; + if (!multicast) + irdp->flags |= IF_BROADCAST; - if_add_update(ifp); + if_add_update(ifp); - if (! (ifp->flags & IFF_UP)) { - zlog_warn("IRDP: Interface is down %s", ifp->name); - } + if (!(ifp->flags & IFF_UP)) { + zlog_warn("IRDP: Interface is down %s", ifp->name); + } - /* Shall we cancel if_start if if_add_group fails? */ + /* Shall we cancel if_start if if_add_group fails? */ - if( multicast) { - if_add_group(ifp); + if (multicast) { + if_add_group(ifp); - if (! (ifp->flags & (IFF_MULTICAST|IFF_ALLMULTI))) { - zlog_warn("IRDP: Interface not multicast enabled %s", ifp->name); - } - } + if (!(ifp->flags & (IFF_MULTICAST | IFF_ALLMULTI))) { + zlog_warn("IRDP: Interface not multicast enabled %s", + ifp->name); + } + } - if(set_defaults) - if_set_defaults(ifp); + if (set_defaults) + if_set_defaults(ifp); - irdp->irdp_sent = 0; + irdp->irdp_sent = 0; - /* The spec suggests this for randomness */ + /* The spec suggests this for randomness */ - seed = 0; - if( ifp->connected) - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) - { - seed = ifc->address->u.prefix4.s_addr; - break; - } + seed = 0; + if (ifp->connected) + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + seed = ifc->address->u.prefix4.s_addr; + break; + } - srandom(seed); - timer = (random () % IRDP_DEFAULT_INTERVAL) + 1; + srandom(seed); + timer = (random() % IRDP_DEFAULT_INTERVAL) + 1; - irdp->AdvPrefList = list_new(); - irdp->AdvPrefList->del = (void (*)(void *)) Adv_free; /* Destructor */ + irdp->AdvPrefList = list_new(); + irdp->AdvPrefList->del = (void (*)(void *))Adv_free; /* Destructor */ - /* And this for startup. Speed limit from 1991 :-). But it's OK*/ + /* And this for startup. Speed limit from 1991 :-). But it's OK*/ - if(irdp->irdp_sent < MAX_INITIAL_ADVERTISEMENTS && - timer > MAX_INITIAL_ADVERT_INTERVAL ) - timer= MAX_INITIAL_ADVERT_INTERVAL; + if (irdp->irdp_sent < MAX_INITIAL_ADVERTISEMENTS + && timer > MAX_INITIAL_ADVERT_INTERVAL) + timer = MAX_INITIAL_ADVERT_INTERVAL; - if(irdp->flags & IF_DEBUG_MISC) - zlog_debug("IRDP: Init timer for %s set to %u", - ifp->name, - timer); + if (irdp->flags & IF_DEBUG_MISC) + zlog_debug("IRDP: Init timer for %s set to %u", ifp->name, + timer); - irdp->t_advertise = NULL; - thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer, - &irdp->t_advertise); + irdp->t_advertise = NULL; + thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer, + &irdp->t_advertise); } -static void -irdp_if_stop(struct interface *ifp) +static void irdp_if_stop(struct interface *ifp) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; - if (irdp == NULL) { - zlog_warn ("Interface %s structure is NULL", ifp->name); - return; - } + if (irdp == NULL) { + zlog_warn("Interface %s structure is NULL", ifp->name); + return; + } - if (! (irdp->flags & IF_ACTIVE )) { - zlog_warn("Interface is not active %s", ifp->name); - return; - } + if (!(irdp->flags & IF_ACTIVE)) { + zlog_warn("Interface is not active %s", ifp->name); + return; + } - if(! (irdp->flags & IF_BROADCAST)) - if_drop_group(ifp); + if (!(irdp->flags & IF_BROADCAST)) + if_drop_group(ifp); - irdp_advert_off(ifp); + irdp_advert_off(ifp); - list_delete(irdp->AdvPrefList); - irdp->AdvPrefList=NULL; + list_delete(irdp->AdvPrefList); + irdp->AdvPrefList = NULL; - irdp->flags = 0; + irdp->flags = 0; } -static void -irdp_if_shutdown(struct interface *ifp) +static void irdp_if_shutdown(struct interface *ifp) { - struct zebra_if *zi= ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; - if (irdp->flags & IF_SHUTDOWN ) { - zlog_warn("IRDP: Interface is already shutdown %s", ifp->name); - return; - } + if (irdp->flags & IF_SHUTDOWN) { + zlog_warn("IRDP: Interface is already shutdown %s", ifp->name); + return; + } - irdp->flags |= IF_SHUTDOWN; - irdp->flags &= ~IF_ACTIVE; + irdp->flags |= IF_SHUTDOWN; + irdp->flags &= ~IF_ACTIVE; - if(! (irdp->flags & IF_BROADCAST)) - if_drop_group(ifp); + if (!(irdp->flags & IF_BROADCAST)) + if_drop_group(ifp); - /* Tell the hosts we are out of service */ - irdp_advert_off(ifp); + /* Tell the hosts we are out of service */ + irdp_advert_off(ifp); } -static void -irdp_if_no_shutdown(struct interface *ifp) +static void irdp_if_no_shutdown(struct interface *ifp) { - struct zebra_if *zi= ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; - if (! (irdp->flags & IF_SHUTDOWN )) { - zlog_warn("IRDP: Interface is not shutdown %s", ifp->name); - return; - } + if (!(irdp->flags & IF_SHUTDOWN)) { + zlog_warn("IRDP: Interface is not shutdown %s", ifp->name); + return; + } - irdp->flags &= ~IF_SHUTDOWN; - - irdp_if_start(ifp, irdp->flags & IF_BROADCAST? FALSE : TRUE, FALSE); + irdp->flags &= ~IF_SHUTDOWN; + irdp_if_start(ifp, irdp->flags & IF_BROADCAST ? FALSE : TRUE, FALSE); } /* Write configuration to user */ -void irdp_config_write (struct vty *vty, struct interface *ifp) +void irdp_config_write(struct vty *vty, struct interface *ifp) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; - struct Adv *adv; - struct listnode *node; - char b1[INET_ADDRSTRLEN]; - - if(irdp->flags & IF_ACTIVE || irdp->flags & IF_SHUTDOWN) { + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + struct Adv *adv; + struct listnode *node; + char b1[INET_ADDRSTRLEN]; - if( irdp->flags & IF_SHUTDOWN) - vty_out (vty, " ip irdp shutdown \n"); + if (irdp->flags & IF_ACTIVE || irdp->flags & IF_SHUTDOWN) { - if( irdp->flags & IF_BROADCAST) - vty_out (vty, " ip irdp broadcast\n"); - else - vty_out (vty, " ip irdp multicast\n"); + if (irdp->flags & IF_SHUTDOWN) + vty_out(vty, " ip irdp shutdown \n"); - vty_out (vty, " ip irdp preference %ld\n", - irdp->Preference); + if (irdp->flags & IF_BROADCAST) + vty_out(vty, " ip irdp broadcast\n"); + else + vty_out(vty, " ip irdp multicast\n"); - for (ALL_LIST_ELEMENTS_RO (irdp->AdvPrefList, node, adv)) - vty_out (vty, " ip irdp address %s preference %d\n", - inet_2a(adv->ip.s_addr, b1), - adv->pref); + vty_out(vty, " ip irdp preference %ld\n", irdp->Preference); - vty_out (vty, " ip irdp holdtime %d\n", - irdp->Lifetime); + for (ALL_LIST_ELEMENTS_RO(irdp->AdvPrefList, node, adv)) + vty_out(vty, " ip irdp address %s preference %d\n", + inet_2a(adv->ip.s_addr, b1), adv->pref); - vty_out (vty, " ip irdp minadvertinterval %ld\n", - irdp->MinAdvertInterval); + vty_out(vty, " ip irdp holdtime %d\n", irdp->Lifetime); - vty_out (vty, " ip irdp maxadvertinterval %ld\n", - irdp->MaxAdvertInterval); + vty_out(vty, " ip irdp minadvertinterval %ld\n", + irdp->MinAdvertInterval); - } + vty_out(vty, " ip irdp maxadvertinterval %ld\n", + irdp->MaxAdvertInterval); + } } @@ -378,10 +358,10 @@ DEFUN (ip_irdp_multicast, "ICMP Router discovery on this interface\n" "Use multicast mode\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - irdp_if_start(ifp, TRUE, TRUE); - return CMD_SUCCESS; + irdp_if_start(ifp, TRUE, TRUE); + return CMD_SUCCESS; } DEFUN (ip_irdp_broadcast, @@ -391,10 +371,10 @@ DEFUN (ip_irdp_broadcast, "ICMP Router discovery on this interface\n" "Use broadcast mode\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - irdp_if_start(ifp, FALSE, TRUE); - return CMD_SUCCESS; + irdp_if_start(ifp, FALSE, TRUE); + return CMD_SUCCESS; } DEFUN (no_ip_irdp, @@ -404,10 +384,10 @@ DEFUN (no_ip_irdp, IP_STR "Disable ICMP Router discovery on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - irdp_if_stop(ifp); - return CMD_SUCCESS; + irdp_if_stop(ifp); + return CMD_SUCCESS; } DEFUN (ip_irdp_shutdown, @@ -417,10 +397,10 @@ DEFUN (ip_irdp_shutdown, "ICMP Router discovery on this interface\n" "ICMP Router discovery shutdown on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - irdp_if_shutdown(ifp); - return CMD_SUCCESS; + irdp_if_shutdown(ifp); + return CMD_SUCCESS; } DEFUN (no_ip_irdp_shutdown, @@ -431,10 +411,10 @@ DEFUN (no_ip_irdp_shutdown, "ICMP Router discovery on this interface\n" "ICMP Router discovery no shutdown on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - irdp_if_no_shutdown(ifp); - return CMD_SUCCESS; + irdp_if_no_shutdown(ifp); + return CMD_SUCCESS; } DEFUN (ip_irdp_holdtime, @@ -445,16 +425,16 @@ DEFUN (ip_irdp_holdtime, "Set holdtime value\n" "Holdtime value in seconds. Default is 1800 seconds\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; - zi=ifp->info; - irdp=&zi->irdp; + zi = ifp->info; + irdp = &zi->irdp; - irdp->Lifetime = atoi(argv[idx_number]->arg); - return CMD_SUCCESS; + irdp->Lifetime = atoi(argv[idx_number]->arg); + return CMD_SUCCESS; } DEFUN (ip_irdp_minadvertinterval, @@ -465,23 +445,23 @@ DEFUN (ip_irdp_minadvertinterval, "Set minimum time between advertisement\n" "Minimum advertisement interval in seconds\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi=ifp->info; - irdp=&zi->irdp; - - if((unsigned) atoi(argv[idx_number]->arg) <= irdp->MaxAdvertInterval) { - irdp->MinAdvertInterval = atoi(argv[idx_number]->arg); - return CMD_SUCCESS; - } - else { - vty_out (vty, "%% MinAdvertInterval must be less than or equal to " - "MaxAdvertInterval\n"); - return CMD_WARNING_CONFIG_FAILED; - } + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; + + zi = ifp->info; + irdp = &zi->irdp; + + if ((unsigned)atoi(argv[idx_number]->arg) <= irdp->MaxAdvertInterval) { + irdp->MinAdvertInterval = atoi(argv[idx_number]->arg); + return CMD_SUCCESS; + } else { + vty_out(vty, + "%% MinAdvertInterval must be less than or equal to " + "MaxAdvertInterval\n"); + return CMD_WARNING_CONFIG_FAILED; + } } DEFUN (ip_irdp_maxadvertinterval, @@ -492,23 +472,23 @@ DEFUN (ip_irdp_maxadvertinterval, "Set maximum time between advertisement\n" "Maximum advertisement interval in seconds\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi=ifp->info; - irdp=&zi->irdp; - - if(irdp->MinAdvertInterval <= (unsigned) atoi(argv[idx_number]->arg)) { - irdp->MaxAdvertInterval = atoi(argv[idx_number]->arg); - return CMD_SUCCESS; - } - else { - vty_out (vty, "%% MaxAdvertInterval must be greater than or equal to " - "MinAdvertInterval\n"); - return CMD_WARNING_CONFIG_FAILED; - } + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; + + zi = ifp->info; + irdp = &zi->irdp; + + if (irdp->MinAdvertInterval <= (unsigned)atoi(argv[idx_number]->arg)) { + irdp->MaxAdvertInterval = atoi(argv[idx_number]->arg); + return CMD_SUCCESS; + } else { + vty_out(vty, + "%% MaxAdvertInterval must be greater than or equal to " + "MinAdvertInterval\n"); + return CMD_WARNING_CONFIG_FAILED; + } } /* DEFUN needs to be fixed for negative ranages... @@ -524,16 +504,16 @@ DEFUN (ip_irdp_preference, "Set default preference level for this interface\n" "Preference level\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; - zi=ifp->info; - irdp=&zi->irdp; + zi = ifp->info; + irdp = &zi->irdp; - irdp->Preference = atoi(argv[idx_number]->arg); - return CMD_SUCCESS; + irdp->Preference = atoi(argv[idx_number]->arg); + return CMD_SUCCESS; } DEFUN (ip_irdp_address_preference, @@ -546,36 +526,36 @@ DEFUN (ip_irdp_address_preference, "Specify IRDP non-default preference to advertise\n" "Preference level\n") { - int idx_ipv4 = 3; - int idx_number = 5; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct listnode *node; - struct in_addr ip; - int pref; - int ret; - struct zebra_if *zi; - struct irdp_interface *irdp; - struct Adv *adv; - - zi=ifp->info; - irdp=&zi->irdp; - - ret = inet_aton(argv[idx_ipv4]->arg, &ip); - if(!ret) return CMD_WARNING_CONFIG_FAILED; - - pref = atoi(argv[idx_number]->arg); - - for (ALL_LIST_ELEMENTS_RO (irdp->AdvPrefList, node, adv)) - if(adv->ip.s_addr == ip.s_addr) - return CMD_SUCCESS; - - adv = Adv_new(); - adv->ip = ip; - adv->pref = pref; - listnode_add(irdp->AdvPrefList, adv); - - return CMD_SUCCESS; - + int idx_ipv4 = 3; + int idx_number = 5; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct listnode *node; + struct in_addr ip; + int pref; + int ret; + struct zebra_if *zi; + struct irdp_interface *irdp; + struct Adv *adv; + + zi = ifp->info; + irdp = &zi->irdp; + + ret = inet_aton(argv[idx_ipv4]->arg, &ip); + if (!ret) + return CMD_WARNING_CONFIG_FAILED; + + pref = atoi(argv[idx_number]->arg); + + for (ALL_LIST_ELEMENTS_RO(irdp->AdvPrefList, node, adv)) + if (adv->ip.s_addr == ip.s_addr) + return CMD_SUCCESS; + + adv = Adv_new(); + adv->ip = ip; + adv->pref = pref; + listnode_add(irdp->AdvPrefList, adv); + + return CMD_SUCCESS; } DEFUN (no_ip_irdp_address_preference, @@ -589,32 +569,30 @@ DEFUN (no_ip_irdp_address_preference, "Reset ICMP Router discovery preference on this interface\n" "Old preference level\n") { - int idx_ipv4 = 4; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct listnode *node, *nnode; - struct in_addr ip; - int ret; - struct zebra_if *zi; - struct irdp_interface *irdp; - struct Adv *adv; - - zi=ifp->info; - irdp=&zi->irdp; - - ret = inet_aton(argv[idx_ipv4]->arg, &ip); - if (!ret) - return CMD_WARNING_CONFIG_FAILED; - - for (ALL_LIST_ELEMENTS (irdp->AdvPrefList, node, nnode, adv)) - { - if(adv->ip.s_addr == ip.s_addr ) - { - listnode_delete(irdp->AdvPrefList, adv); - break; - } - } - - return CMD_SUCCESS; + int idx_ipv4 = 4; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct listnode *node, *nnode; + struct in_addr ip; + int ret; + struct zebra_if *zi; + struct irdp_interface *irdp; + struct Adv *adv; + + zi = ifp->info; + irdp = &zi->irdp; + + ret = inet_aton(argv[idx_ipv4]->arg, &ip); + if (!ret) + return CMD_WARNING_CONFIG_FAILED; + + for (ALL_LIST_ELEMENTS(irdp->AdvPrefList, node, nnode, adv)) { + if (adv->ip.s_addr == ip.s_addr) { + listnode_delete(irdp->AdvPrefList, adv); + break; + } + } + + return CMD_SUCCESS; } DEFUN (ip_irdp_debug_messages, @@ -625,16 +603,16 @@ DEFUN (ip_irdp_debug_messages, "IRDP debugging options\n" "Enable debugging for IRDP messages\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; - zi=ifp->info; - irdp=&zi->irdp; + zi = ifp->info; + irdp = &zi->irdp; - irdp->flags |= IF_DEBUG_MESSAGES; + irdp->flags |= IF_DEBUG_MESSAGES; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_irdp_debug_misc, @@ -645,16 +623,16 @@ DEFUN (ip_irdp_debug_misc, "IRDP debugging options\n" "Enable debugging for miscellaneous IRDP events\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; - zi=ifp->info; - irdp=&zi->irdp; + zi = ifp->info; + irdp = &zi->irdp; - irdp->flags |= IF_DEBUG_MISC; + irdp->flags |= IF_DEBUG_MISC; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_irdp_debug_packet, @@ -665,16 +643,16 @@ DEFUN (ip_irdp_debug_packet, "IRDP debugging options\n" "Enable debugging for IRDP packets\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; - zi=ifp->info; - irdp=&zi->irdp; + zi = ifp->info; + irdp = &zi->irdp; - irdp->flags |= IF_DEBUG_PACKET; + irdp->flags |= IF_DEBUG_PACKET; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -686,39 +664,38 @@ DEFUN (ip_irdp_debug_disable, "IRDP debugging options\n" "Disable debugging for all IRDP events\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; - zi=ifp->info; - irdp=&zi->irdp; + zi = ifp->info; + irdp = &zi->irdp; - irdp->flags &= ~IF_DEBUG_PACKET; - irdp->flags &= ~IF_DEBUG_MESSAGES; - irdp->flags &= ~IF_DEBUG_MISC; + irdp->flags &= ~IF_DEBUG_PACKET; + irdp->flags &= ~IF_DEBUG_MESSAGES; + irdp->flags &= ~IF_DEBUG_MISC; - return CMD_SUCCESS; + return CMD_SUCCESS; } -void -irdp_init () +void irdp_init() { - install_element (INTERFACE_NODE, &ip_irdp_broadcast_cmd); - install_element (INTERFACE_NODE, &ip_irdp_multicast_cmd); - install_element (INTERFACE_NODE, &no_ip_irdp_cmd); - install_element (INTERFACE_NODE, &ip_irdp_shutdown_cmd); - install_element (INTERFACE_NODE, &no_ip_irdp_shutdown_cmd); - install_element (INTERFACE_NODE, &ip_irdp_holdtime_cmd); - install_element (INTERFACE_NODE, &ip_irdp_maxadvertinterval_cmd); - install_element (INTERFACE_NODE, &ip_irdp_minadvertinterval_cmd); - install_element (INTERFACE_NODE, &ip_irdp_preference_cmd); - install_element (INTERFACE_NODE, &ip_irdp_address_preference_cmd); - install_element (INTERFACE_NODE, &no_ip_irdp_address_preference_cmd); - - install_element (INTERFACE_NODE, &ip_irdp_debug_messages_cmd); - install_element (INTERFACE_NODE, &ip_irdp_debug_misc_cmd); - install_element (INTERFACE_NODE, &ip_irdp_debug_packet_cmd); - install_element (INTERFACE_NODE, &ip_irdp_debug_disable_cmd); + install_element(INTERFACE_NODE, &ip_irdp_broadcast_cmd); + install_element(INTERFACE_NODE, &ip_irdp_multicast_cmd); + install_element(INTERFACE_NODE, &no_ip_irdp_cmd); + install_element(INTERFACE_NODE, &ip_irdp_shutdown_cmd); + install_element(INTERFACE_NODE, &no_ip_irdp_shutdown_cmd); + install_element(INTERFACE_NODE, &ip_irdp_holdtime_cmd); + install_element(INTERFACE_NODE, &ip_irdp_maxadvertinterval_cmd); + install_element(INTERFACE_NODE, &ip_irdp_minadvertinterval_cmd); + install_element(INTERFACE_NODE, &ip_irdp_preference_cmd); + install_element(INTERFACE_NODE, &ip_irdp_address_preference_cmd); + install_element(INTERFACE_NODE, &no_ip_irdp_address_preference_cmd); + + install_element(INTERFACE_NODE, &ip_irdp_debug_messages_cmd); + install_element(INTERFACE_NODE, &ip_irdp_debug_misc_cmd); + install_element(INTERFACE_NODE, &ip_irdp_debug_packet_cmd); + install_element(INTERFACE_NODE, &ip_irdp_debug_disable_cmd); } #endif /* HAVE_IRDP */ diff --git a/zebra/irdp_main.c b/zebra/irdp_main.c index a155331c9..6220c9d81 100644 --- a/zebra/irdp_main.c +++ b/zebra/irdp_main.c @@ -20,14 +20,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* +/* * This work includes work with the following copywrite: * * Copyright (C) 1997, 2000 Kunihiro Ishiguro * */ -/* +/* * Thanks to Jens Låås at Swedish University of Agricultural Sciences * for reviewing and tests. */ @@ -74,262 +74,258 @@ struct thread *t_irdp_raw; /* Timer interval of irdp. */ int irdp_timer_interval = IRDP_DEFAULT_INTERVAL; -int -irdp_sock_init (void) +int irdp_sock_init(void) { - int ret, i; - int save_errno; - int sock; - - if ( zserv_privs.change (ZPRIVS_RAISE) ) - zlog_err ("irdp_sock_init: could not raise privs, %s", - safe_strerror (errno) ); - - sock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); - save_errno = errno; - - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("irdp_sock_init: could not lower privs, %s", - safe_strerror (errno) ); - - if (sock < 0) { - zlog_warn ("IRDP: can't create irdp socket %s", safe_strerror(save_errno)); - return sock; - }; - - i = 1; - ret = setsockopt (sock, IPPROTO_IP, IP_TTL, - (void *) &i, sizeof (i)); - if (ret < 0) { - zlog_warn ("IRDP: can't do irdp sockopt %s", safe_strerror(errno)); - close(sock); - return ret; - }; - - ret = setsockopt_ifindex (AF_INET, sock, 1); - if (ret < 0) { - zlog_warn ("IRDP: can't do irdp sockopt %s", safe_strerror(errno)); - close(sock); - return ret; - }; - - t_irdp_raw = NULL; - thread_add_read(zebrad.master, irdp_read_raw, NULL, sock, &t_irdp_raw); - - return sock; + int ret, i; + int save_errno; + int sock; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("irdp_sock_init: could not raise privs, %s", + safe_strerror(errno)); + + sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + save_errno = errno; + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("irdp_sock_init: could not lower privs, %s", + safe_strerror(errno)); + + if (sock < 0) { + zlog_warn("IRDP: can't create irdp socket %s", + safe_strerror(save_errno)); + return sock; + }; + + i = 1; + ret = setsockopt(sock, IPPROTO_IP, IP_TTL, (void *)&i, sizeof(i)); + if (ret < 0) { + zlog_warn("IRDP: can't do irdp sockopt %s", + safe_strerror(errno)); + close(sock); + return ret; + }; + + ret = setsockopt_ifindex(AF_INET, sock, 1); + if (ret < 0) { + zlog_warn("IRDP: can't do irdp sockopt %s", + safe_strerror(errno)); + close(sock); + return ret; + }; + + t_irdp_raw = NULL; + thread_add_read(zebrad.master, irdp_read_raw, NULL, sock, &t_irdp_raw); + + return sock; } -static int -get_pref(struct irdp_interface *irdp, struct prefix *p) +static int get_pref(struct irdp_interface *irdp, struct prefix *p) { - struct listnode *node; - struct Adv *adv; - - /* Use default preference or use the override pref */ - - if( irdp->AdvPrefList == NULL ) - return irdp->Preference; - - for (ALL_LIST_ELEMENTS_RO (irdp->AdvPrefList, node, adv)) - if( p->u.prefix4.s_addr == adv->ip.s_addr ) - return adv->pref; - - return irdp->Preference; + struct listnode *node; + struct Adv *adv; + + /* Use default preference or use the override pref */ + + if (irdp->AdvPrefList == NULL) + return irdp->Preference; + + for (ALL_LIST_ELEMENTS_RO(irdp->AdvPrefList, node, adv)) + if (p->u.prefix4.s_addr == adv->ip.s_addr) + return adv->pref; + + return irdp->Preference; } /* Make ICMP Router Advertisement Message. */ -static int -make_advertisement_packet (struct interface *ifp, - struct prefix *p, - struct stream *s) +static int make_advertisement_packet(struct interface *ifp, struct prefix *p, + struct stream *s) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; - int size; - int pref; - u_int16_t checksum; - - pref = get_pref(irdp, p); - - stream_putc (s, ICMP_ROUTERADVERT); /* Type. */ - stream_putc (s, 0); /* Code. */ - stream_putw (s, 0); /* Checksum. */ - stream_putc (s, 1); /* Num address. */ - stream_putc (s, 2); /* Address Entry Size. */ - - if(irdp->flags & IF_SHUTDOWN) - stream_putw (s, 0); - else - stream_putw (s, irdp->Lifetime); - - stream_putl (s, htonl(p->u.prefix4.s_addr)); /* Router address. */ - stream_putl (s, pref); - - /* in_cksum return network byte order value */ - size = 16; - checksum = in_cksum (s->data, size); - stream_putw_at (s, 2, htons(checksum)); - - return size; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + int size; + int pref; + u_int16_t checksum; + + pref = get_pref(irdp, p); + + stream_putc(s, ICMP_ROUTERADVERT); /* Type. */ + stream_putc(s, 0); /* Code. */ + stream_putw(s, 0); /* Checksum. */ + stream_putc(s, 1); /* Num address. */ + stream_putc(s, 2); /* Address Entry Size. */ + + if (irdp->flags & IF_SHUTDOWN) + stream_putw(s, 0); + else + stream_putw(s, irdp->Lifetime); + + stream_putl(s, htonl(p->u.prefix4.s_addr)); /* Router address. */ + stream_putl(s, pref); + + /* in_cksum return network byte order value */ + size = 16; + checksum = in_cksum(s->data, size); + stream_putw_at(s, 2, htons(checksum)); + + return size; } -static void -irdp_send(struct interface *ifp, struct prefix *p, struct stream *s) +static void irdp_send(struct interface *ifp, struct prefix *p, struct stream *s) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; - char buf[PREFIX_STRLEN]; - u_int32_t dst; - u_int32_t ttl=1; - - if (! (ifp->flags & IFF_UP)) return; - - if (irdp->flags & IF_BROADCAST) - dst =INADDR_BROADCAST ; - else - dst = htonl(INADDR_ALLHOSTS_GROUP); - - if(irdp->flags & IF_DEBUG_MESSAGES) - zlog_debug("IRDP: TX Advert on %s %s Holdtime=%d Preference=%d", - ifp->name, - prefix2str(p, buf, sizeof buf), - irdp->flags & IF_SHUTDOWN? 0 : irdp->Lifetime, - get_pref(irdp, p)); - - send_packet (ifp, s, dst, p, ttl); + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + char buf[PREFIX_STRLEN]; + u_int32_t dst; + u_int32_t ttl = 1; + + if (!(ifp->flags & IFF_UP)) + return; + + if (irdp->flags & IF_BROADCAST) + dst = INADDR_BROADCAST; + else + dst = htonl(INADDR_ALLHOSTS_GROUP); + + if (irdp->flags & IF_DEBUG_MESSAGES) + zlog_debug("IRDP: TX Advert on %s %s Holdtime=%d Preference=%d", + ifp->name, prefix2str(p, buf, sizeof buf), + irdp->flags & IF_SHUTDOWN ? 0 : irdp->Lifetime, + get_pref(irdp, p)); + + send_packet(ifp, s, dst, p, ttl); } -static void irdp_advertisement (struct interface *ifp, struct prefix *p) +static void irdp_advertisement(struct interface *ifp, struct prefix *p) { - struct stream *s; - s = stream_new (128); - make_advertisement_packet (ifp, p, s); - irdp_send(ifp, p, s); - stream_free (s); + struct stream *s; + s = stream_new(128); + make_advertisement_packet(ifp, p, s); + irdp_send(ifp, p, s); + stream_free(s); } int irdp_send_thread(struct thread *t_advert) { - u_int32_t timer, tmp; - struct interface *ifp = THREAD_ARG (t_advert); - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; - struct prefix *p; - struct listnode *node, *nnode; - struct connected *ifc; - - irdp->flags &= ~IF_SOLICIT; - - if(ifp->connected) - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc)) - { - p = ifc->address; - - if (p->family != AF_INET) - continue; - - irdp_advertisement(ifp, p); - irdp->irdp_sent++; - } - - tmp = irdp->MaxAdvertInterval-irdp->MinAdvertInterval; - timer = random () % (tmp + 1); - timer = irdp->MinAdvertInterval + timer; - - if(irdp->irdp_sent < MAX_INITIAL_ADVERTISEMENTS && - timer > MAX_INITIAL_ADVERT_INTERVAL ) - timer= MAX_INITIAL_ADVERT_INTERVAL; - - if(irdp->flags & IF_DEBUG_MISC) - zlog_debug("IRDP: New timer for %s set to %u\n", ifp->name, timer); - - irdp->t_advertise = NULL; - thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer, - &irdp->t_advertise); - return 0; + u_int32_t timer, tmp; + struct interface *ifp = THREAD_ARG(t_advert); + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + struct prefix *p; + struct listnode *node, *nnode; + struct connected *ifc; + + irdp->flags &= ~IF_SOLICIT; + + if (ifp->connected) + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, ifc)) { + p = ifc->address; + + if (p->family != AF_INET) + continue; + + irdp_advertisement(ifp, p); + irdp->irdp_sent++; + } + + tmp = irdp->MaxAdvertInterval - irdp->MinAdvertInterval; + timer = random() % (tmp + 1); + timer = irdp->MinAdvertInterval + timer; + + if (irdp->irdp_sent < MAX_INITIAL_ADVERTISEMENTS + && timer > MAX_INITIAL_ADVERT_INTERVAL) + timer = MAX_INITIAL_ADVERT_INTERVAL; + + if (irdp->flags & IF_DEBUG_MISC) + zlog_debug("IRDP: New timer for %s set to %u\n", ifp->name, + timer); + + irdp->t_advertise = NULL; + thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer, + &irdp->t_advertise); + return 0; } void irdp_advert_off(struct interface *ifp) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; - struct listnode *node, *nnode; - int i; - struct connected *ifc; - struct prefix *p; - - if(irdp->t_advertise) thread_cancel(irdp->t_advertise); - irdp->t_advertise = NULL; - - if(ifp->connected) - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc)) - { - p = ifc->address; - - /* Output some packets with Lifetime 0 - we should add a wait... - */ - - for(i=0; i< IRDP_LAST_ADVERT_MESSAGES; i++) - { - irdp->irdp_sent++; - irdp_advertisement(ifp, p); - } - } + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + struct listnode *node, *nnode; + int i; + struct connected *ifc; + struct prefix *p; + + if (irdp->t_advertise) + thread_cancel(irdp->t_advertise); + irdp->t_advertise = NULL; + + if (ifp->connected) + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, ifc)) { + p = ifc->address; + + /* Output some packets with Lifetime 0 + we should add a wait... + */ + + for (i = 0; i < IRDP_LAST_ADVERT_MESSAGES; i++) { + irdp->irdp_sent++; + irdp_advertisement(ifp, p); + } + } } -void process_solicit (struct interface *ifp) +void process_solicit(struct interface *ifp) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; - u_int32_t timer; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + u_int32_t timer; - /* When SOLICIT is active we reject further incoming solicits - this keeps down the answering rate so we don't have think - about DoS attacks here. */ + /* When SOLICIT is active we reject further incoming solicits + this keeps down the answering rate so we don't have think + about DoS attacks here. */ - if( irdp->flags & IF_SOLICIT) return; + if (irdp->flags & IF_SOLICIT) + return; - irdp->flags |= IF_SOLICIT; - if(irdp->t_advertise) thread_cancel(irdp->t_advertise); - irdp->t_advertise = NULL; + irdp->flags |= IF_SOLICIT; + if (irdp->t_advertise) + thread_cancel(irdp->t_advertise); + irdp->t_advertise = NULL; - timer = (random () % MAX_RESPONSE_DELAY) + 1; + timer = (random() % MAX_RESPONSE_DELAY) + 1; - irdp->t_advertise = NULL; - thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer, - &irdp->t_advertise); + irdp->t_advertise = NULL; + thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer, + &irdp->t_advertise); } void irdp_finish() { - struct vrf *vrf; - struct listnode *node, *nnode; - struct interface *ifp; - struct zebra_if *zi; - struct irdp_interface *irdp; - - zlog_info("IRDP: Received shutdown notification."); - - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - for (ALL_LIST_ELEMENTS (vrf->iflist, node, nnode, ifp)) - { - zi = ifp->info; - - if (!zi) - continue; - irdp = &zi->irdp; - if (!irdp) - continue; - - if (irdp->flags & IF_ACTIVE ) - { - irdp->flags |= IF_SHUTDOWN; - irdp_advert_off(ifp); - } - } + struct vrf *vrf; + struct listnode *node, *nnode; + struct interface *ifp; + struct zebra_if *zi; + struct irdp_interface *irdp; + + zlog_info("IRDP: Received shutdown notification."); + + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + for (ALL_LIST_ELEMENTS(vrf->iflist, node, nnode, ifp)) { + zi = ifp->info; + + if (!zi) + continue; + irdp = &zi->irdp; + if (!irdp) + continue; + + if (irdp->flags & IF_ACTIVE) { + irdp->flags |= IF_SHUTDOWN; + irdp_advert_off(ifp); + } + } } #endif /* HAVE_IRDP */ diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c index 20982b31a..3bd093d97 100644 --- a/zebra/irdp_packet.c +++ b/zebra/irdp_packet.c @@ -20,14 +20,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* +/* * This work includes work with the following copywrite: * * Copyright (C) 1997, 2000 Kunihiro Ishiguro * */ -/* +/* * Thanks to Jens Låås at Swedish University of Agricultural Sciences * for reviewing and tests. */ @@ -71,294 +71,288 @@ int irdp_sock = -1; extern struct thread *t_irdp_raw; -static void -parse_irdp_packet(char *p, - int len, - struct interface *ifp) +static void parse_irdp_packet(char *p, int len, struct interface *ifp) { - struct ip *ip = (struct ip *)p ; - struct icmphdr *icmp; - struct in_addr src; - int ip_hlen, iplen, datalen; - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi = ifp->info; - if (!zi) - return; - - irdp = &zi->irdp; - if (!irdp) - return; - - ip_hlen = ip->ip_hl << 2; - - sockopt_iphdrincl_swab_systoh (ip); - - iplen = ip->ip_len; - datalen = len - ip_hlen; - src = ip->ip_src; - - if (len != iplen) - { - zlog_err ("IRDP: RX length doesnt match IP length"); - return; - } - - if (iplen < ICMP_MINLEN) - { - zlog_err ("IRDP: RX ICMP packet too short from %s\n", - inet_ntoa (src)); - return; - } - - /* XXX: RAW doesnt receive link-layer, surely? ??? */ - /* Check so we don't checksum packets longer than oure RX_BUF - (ethlen + - len of IP-header) 14+20 */ - if (iplen > IRDP_RX_BUF-34) - { - zlog_err ("IRDP: RX ICMP packet too long from %s\n", - inet_ntoa (src)); - return; - } - - icmp = (struct icmphdr *) (p+ip_hlen); - - /* check icmp checksum */ - if (in_cksum (icmp, datalen) != icmp->checksum) - { - zlog_warn ("IRDP: RX ICMP packet from %s. Bad checksum, silently ignored", - inet_ntoa (src)); - return; - } - - /* Handle just only IRDP */ - if (!(icmp->type == ICMP_ROUTERADVERT - || icmp->type == ICMP_ROUTERSOLICIT)) - return; - - if (icmp->code != 0) - { - zlog_warn ("IRDP: RX packet type %d from %s. Bad ICMP type code," - " silently ignored", - icmp->type, inet_ntoa (src)); - return; - } - - if (! ((ntohl (ip->ip_dst.s_addr) == INADDR_BROADCAST) - && (irdp->flags & IF_BROADCAST)) - || - (ntohl (ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP - && !(irdp->flags & IF_BROADCAST))) - { - zlog_warn ("IRDP: RX illegal from %s to %s while %s operates in %s\n", - inet_ntoa (src), - ntohl (ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP ? - "multicast" : inet_ntoa (ip->ip_dst), - ifp->name, - irdp->flags & IF_BROADCAST ? "broadcast" : "multicast"); - - zlog_warn ("IRDP: Please correct settings\n"); - return; - } - - switch (icmp->type) - { - case ICMP_ROUTERADVERT: - break; - - case ICMP_ROUTERSOLICIT: - - if(irdp->flags & IF_DEBUG_MESSAGES) - zlog_debug ("IRDP: RX Solicit on %s from %s\n", - ifp->name, - inet_ntoa (src)); - - process_solicit(ifp); - break; - - default: - zlog_warn ("IRDP: RX type %d from %s. Bad ICMP type, silently ignored", - icmp->type, - inet_ntoa (src)); - } + struct ip *ip = (struct ip *)p; + struct icmphdr *icmp; + struct in_addr src; + int ip_hlen, iplen, datalen; + struct zebra_if *zi; + struct irdp_interface *irdp; + + zi = ifp->info; + if (!zi) + return; + + irdp = &zi->irdp; + if (!irdp) + return; + + ip_hlen = ip->ip_hl << 2; + + sockopt_iphdrincl_swab_systoh(ip); + + iplen = ip->ip_len; + datalen = len - ip_hlen; + src = ip->ip_src; + + if (len != iplen) { + zlog_err("IRDP: RX length doesnt match IP length"); + return; + } + + if (iplen < ICMP_MINLEN) { + zlog_err("IRDP: RX ICMP packet too short from %s\n", + inet_ntoa(src)); + return; + } + + /* XXX: RAW doesnt receive link-layer, surely? ??? */ + /* Check so we don't checksum packets longer than oure RX_BUF - (ethlen + + + len of IP-header) 14+20 */ + if (iplen > IRDP_RX_BUF - 34) { + zlog_err("IRDP: RX ICMP packet too long from %s\n", + inet_ntoa(src)); + return; + } + + icmp = (struct icmphdr *)(p + ip_hlen); + + /* check icmp checksum */ + if (in_cksum(icmp, datalen) != icmp->checksum) { + zlog_warn( + "IRDP: RX ICMP packet from %s. Bad checksum, silently ignored", + inet_ntoa(src)); + return; + } + + /* Handle just only IRDP */ + if (!(icmp->type == ICMP_ROUTERADVERT + || icmp->type == ICMP_ROUTERSOLICIT)) + return; + + if (icmp->code != 0) { + zlog_warn( + "IRDP: RX packet type %d from %s. Bad ICMP type code," + " silently ignored", + icmp->type, inet_ntoa(src)); + return; + } + + if (!((ntohl(ip->ip_dst.s_addr) == INADDR_BROADCAST) + && (irdp->flags & IF_BROADCAST)) + || (ntohl(ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP + && !(irdp->flags & IF_BROADCAST))) { + zlog_warn( + "IRDP: RX illegal from %s to %s while %s operates in %s\n", + inet_ntoa(src), + ntohl(ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP + ? "multicast" + : inet_ntoa(ip->ip_dst), + ifp->name, + irdp->flags & IF_BROADCAST ? "broadcast" : "multicast"); + + zlog_warn("IRDP: Please correct settings\n"); + return; + } + + switch (icmp->type) { + case ICMP_ROUTERADVERT: + break; + + case ICMP_ROUTERSOLICIT: + + if (irdp->flags & IF_DEBUG_MESSAGES) + zlog_debug("IRDP: RX Solicit on %s from %s\n", + ifp->name, inet_ntoa(src)); + + process_solicit(ifp); + break; + + default: + zlog_warn( + "IRDP: RX type %d from %s. Bad ICMP type, silently ignored", + icmp->type, inet_ntoa(src)); + } } -static int -irdp_recvmsg (int sock, u_char *buf, int size, int *ifindex) +static int irdp_recvmsg(int sock, u_char *buf, int size, int *ifindex) { - struct msghdr msg; - struct iovec iov; - char adata[CMSG_SPACE( SOPT_SIZE_CMSG_PKTINFO_IPV4() )]; - int ret; - - msg.msg_name = (void *)0; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = (void *) adata; - msg.msg_controllen = sizeof adata; - - iov.iov_base = buf; - iov.iov_len = size; - - ret = recvmsg (sock, &msg, 0); - if (ret < 0) { - zlog_warn("IRDP: recvmsg: read error %s", safe_strerror(errno)); - return ret; - } - - if (msg.msg_flags & MSG_TRUNC) { - zlog_warn("IRDP: recvmsg: truncated message"); - return ret; - } - if (msg.msg_flags & MSG_CTRUNC) { - zlog_warn("IRDP: recvmsg: truncated control message"); - return ret; - } - - *ifindex = getsockopt_ifindex (AF_INET, &msg); - - return ret; + struct msghdr msg; + struct iovec iov; + char adata[CMSG_SPACE(SOPT_SIZE_CMSG_PKTINFO_IPV4())]; + int ret; + + msg.msg_name = (void *)0; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (void *)adata; + msg.msg_controllen = sizeof adata; + + iov.iov_base = buf; + iov.iov_len = size; + + ret = recvmsg(sock, &msg, 0); + if (ret < 0) { + zlog_warn("IRDP: recvmsg: read error %s", safe_strerror(errno)); + return ret; + } + + if (msg.msg_flags & MSG_TRUNC) { + zlog_warn("IRDP: recvmsg: truncated message"); + return ret; + } + if (msg.msg_flags & MSG_CTRUNC) { + zlog_warn("IRDP: recvmsg: truncated control message"); + return ret; + } + + *ifindex = getsockopt_ifindex(AF_INET, &msg); + + return ret; } int irdp_read_raw(struct thread *r) { - struct interface *ifp; - struct zebra_if *zi; - struct irdp_interface *irdp; - char buf[IRDP_RX_BUF]; - int ret, ifindex = 0; - - int irdp_sock = THREAD_FD (r); - t_irdp_raw = NULL; - thread_add_read(zebrad.master, irdp_read_raw, NULL, irdp_sock, &t_irdp_raw); - - ret = irdp_recvmsg (irdp_sock, (u_char *) buf, IRDP_RX_BUF, &ifindex); - - if (ret < 0) zlog_warn ("IRDP: RX Error length = %d", ret); - - ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - if(! ifp ) return ret; - - zi= ifp->info; - if(! zi ) return ret; - - irdp = &zi->irdp; - if(! irdp ) return ret; - - if(! (irdp->flags & IF_ACTIVE)) { - - if(irdp->flags & IF_DEBUG_MISC) - zlog_debug("IRDP: RX ICMP for disabled interface %s\n", ifp->name); - return 0; - } - - if(irdp->flags & IF_DEBUG_PACKET) { - int i; - zlog_debug("IRDP: RX (idx %d) ", ifindex); - for(i=0; i < ret; i++) zlog_debug( "IRDP: RX %x ", buf[i]&0xFF); - } - - parse_irdp_packet(buf, ret, ifp); - - return ret; + struct interface *ifp; + struct zebra_if *zi; + struct irdp_interface *irdp; + char buf[IRDP_RX_BUF]; + int ret, ifindex = 0; + + int irdp_sock = THREAD_FD(r); + t_irdp_raw = NULL; + thread_add_read(zebrad.master, irdp_read_raw, NULL, irdp_sock, + &t_irdp_raw); + + ret = irdp_recvmsg(irdp_sock, (u_char *)buf, IRDP_RX_BUF, &ifindex); + + if (ret < 0) + zlog_warn("IRDP: RX Error length = %d", ret); + + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + if (!ifp) + return ret; + + zi = ifp->info; + if (!zi) + return ret; + + irdp = &zi->irdp; + if (!irdp) + return ret; + + if (!(irdp->flags & IF_ACTIVE)) { + + if (irdp->flags & IF_DEBUG_MISC) + zlog_debug("IRDP: RX ICMP for disabled interface %s\n", + ifp->name); + return 0; + } + + if (irdp->flags & IF_DEBUG_PACKET) { + int i; + zlog_debug("IRDP: RX (idx %d) ", ifindex); + for (i = 0; i < ret; i++) + zlog_debug("IRDP: RX %x ", buf[i] & 0xFF); + } + + parse_irdp_packet(buf, ret, ifp); + + return ret; } -void -send_packet(struct interface *ifp, - struct stream *s, - u_int32_t dst, - struct prefix *p, - u_int32_t ttl) +void send_packet(struct interface *ifp, struct stream *s, u_int32_t dst, + struct prefix *p, u_int32_t ttl) { - static struct sockaddr_in sockdst = {AF_INET}; - struct ip *ip; - struct icmphdr *icmp; - struct msghdr *msg; - struct cmsghdr *cmsg; - struct iovec iovector; - char msgbuf[256]; - char buf[256]; - struct in_pktinfo *pktinfo; - u_long src; - u_char on; - - if (!(ifp->flags & IFF_UP)) - return; - - if (p) - src = ntohl(p->u.prefix4.s_addr); - else - src = 0; /* Is filled in */ - - ip = (struct ip *) buf; - ip->ip_hl = sizeof(struct ip) >> 2; - ip->ip_v = IPVERSION; - ip->ip_tos = 0xC0; - ip->ip_off = 0L; - ip->ip_p = 1; /* IP_ICMP */ - ip->ip_ttl = ttl; - ip->ip_src.s_addr = src; - ip->ip_dst.s_addr = dst; - icmp = (struct icmphdr *) (buf + sizeof (struct ip)); - - /* Merge IP header with icmp packet */ - assert (stream_get_endp(s) < (sizeof (buf) - sizeof (struct ip))); - stream_get(icmp, s, stream_get_endp(s)); - - /* icmp->checksum is already calculated */ - ip->ip_len = sizeof(struct ip) + stream_get_endp(s); - - on = 1; - if (setsockopt(irdp_sock, IPPROTO_IP, IP_HDRINCL, - (char *) &on, sizeof(on)) < 0) - zlog_warn("sendto %s", safe_strerror (errno)); - - - if(dst == INADDR_BROADCAST ) { - on = 1; - if (setsockopt(irdp_sock, SOL_SOCKET, SO_BROADCAST, - (char *) &on, sizeof(on)) < 0) - zlog_warn("sendto %s", safe_strerror (errno)); - } - - if(dst != INADDR_BROADCAST) - setsockopt_ipv4_multicast_loop (irdp_sock, 0); - - memset(&sockdst,0,sizeof(sockdst)); - sockdst.sin_family=AF_INET; - sockdst.sin_addr.s_addr = dst; - - cmsg = (struct cmsghdr *) (msgbuf + sizeof(struct msghdr)); - cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo); - cmsg->cmsg_level = SOL_IP; - cmsg->cmsg_type = IP_PKTINFO; - pktinfo = (struct in_pktinfo *) CMSG_DATA(cmsg); - pktinfo->ipi_ifindex = ifp->ifindex; - pktinfo->ipi_spec_dst.s_addr = src; - pktinfo->ipi_addr.s_addr = src; - - iovector.iov_base = (void *) buf; - iovector.iov_len = ip->ip_len; - msg = (struct msghdr *) msgbuf; - msg->msg_name = &sockdst; - msg->msg_namelen = sizeof(sockdst); - msg->msg_iov = &iovector; - msg->msg_iovlen = 1; - msg->msg_control = cmsg; - msg->msg_controllen = cmsg->cmsg_len; - - sockopt_iphdrincl_swab_htosys (ip); - - if (sendmsg(irdp_sock, msg, 0) < 0) { - zlog_warn("sendto %s", safe_strerror (errno)); - } - /* printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */ + static struct sockaddr_in sockdst = {AF_INET}; + struct ip *ip; + struct icmphdr *icmp; + struct msghdr *msg; + struct cmsghdr *cmsg; + struct iovec iovector; + char msgbuf[256]; + char buf[256]; + struct in_pktinfo *pktinfo; + u_long src; + u_char on; + + if (!(ifp->flags & IFF_UP)) + return; + + if (p) + src = ntohl(p->u.prefix4.s_addr); + else + src = 0; /* Is filled in */ + + ip = (struct ip *)buf; + ip->ip_hl = sizeof(struct ip) >> 2; + ip->ip_v = IPVERSION; + ip->ip_tos = 0xC0; + ip->ip_off = 0L; + ip->ip_p = 1; /* IP_ICMP */ + ip->ip_ttl = ttl; + ip->ip_src.s_addr = src; + ip->ip_dst.s_addr = dst; + icmp = (struct icmphdr *)(buf + sizeof(struct ip)); + + /* Merge IP header with icmp packet */ + assert(stream_get_endp(s) < (sizeof(buf) - sizeof(struct ip))); + stream_get(icmp, s, stream_get_endp(s)); + + /* icmp->checksum is already calculated */ + ip->ip_len = sizeof(struct ip) + stream_get_endp(s); + + on = 1; + if (setsockopt(irdp_sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, + sizeof(on)) + < 0) + zlog_warn("sendto %s", safe_strerror(errno)); + + + if (dst == INADDR_BROADCAST) { + on = 1; + if (setsockopt(irdp_sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, + sizeof(on)) + < 0) + zlog_warn("sendto %s", safe_strerror(errno)); + } + + if (dst != INADDR_BROADCAST) + setsockopt_ipv4_multicast_loop(irdp_sock, 0); + + memset(&sockdst, 0, sizeof(sockdst)); + sockdst.sin_family = AF_INET; + sockdst.sin_addr.s_addr = dst; + + cmsg = (struct cmsghdr *)(msgbuf + sizeof(struct msghdr)); + cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo); + cmsg->cmsg_level = SOL_IP; + cmsg->cmsg_type = IP_PKTINFO; + pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg); + pktinfo->ipi_ifindex = ifp->ifindex; + pktinfo->ipi_spec_dst.s_addr = src; + pktinfo->ipi_addr.s_addr = src; + + iovector.iov_base = (void *)buf; + iovector.iov_len = ip->ip_len; + msg = (struct msghdr *)msgbuf; + msg->msg_name = &sockdst; + msg->msg_namelen = sizeof(sockdst); + msg->msg_iov = &iovector; + msg->msg_iovlen = 1; + msg->msg_control = cmsg; + msg->msg_controllen = cmsg->cmsg_len; + + sockopt_iphdrincl_swab_htosys(ip); + + if (sendmsg(irdp_sock, msg, 0) < 0) { + zlog_warn("sendto %s", safe_strerror(errno)); + } + /* printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */ } #endif /* HAVE_IRDP */ - - - diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 91d4946b5..7fc2d6133 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -53,13 +53,13 @@ #endif /* MSG_TRUNC */ #ifndef NLMSG_TAIL -#define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((u_char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) +#define NLMSG_TAIL(nmsg) \ + ((struct rtattr *)(((u_char *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) #endif #ifndef RTA_TAIL -#define RTA_TAIL(rta) \ - ((struct rtattr *) (((u_char *) (rta)) + RTA_ALIGN((rta)->rta_len))) +#define RTA_TAIL(rta) \ + ((struct rtattr *)(((u_char *)(rta)) + RTA_ALIGN((rta)->rta_len))) #endif #ifndef RTNL_FAMILY_IP6MR @@ -70,396 +70,368 @@ #define RTPROT_MROUTED 17 #endif -static const struct message nlmsg_str[] = { - {RTM_NEWROUTE, "RTM_NEWROUTE"}, - {RTM_DELROUTE, "RTM_DELROUTE"}, - {RTM_GETROUTE, "RTM_GETROUTE"}, - {RTM_NEWLINK, "RTM_NEWLINK"}, - {RTM_DELLINK, "RTM_DELLINK"}, - {RTM_GETLINK, "RTM_GETLINK"}, - {RTM_NEWADDR, "RTM_NEWADDR"}, - {RTM_DELADDR, "RTM_DELADDR"}, - {RTM_GETADDR, "RTM_GETADDR"}, - {RTM_NEWNEIGH, "RTM_NEWNEIGH"}, - {RTM_DELNEIGH, "RTM_DELNEIGH"}, - {RTM_GETNEIGH, "RTM_GETNEIGH"}, - { 0 } -}; +static const struct message nlmsg_str[] = {{RTM_NEWROUTE, "RTM_NEWROUTE"}, + {RTM_DELROUTE, "RTM_DELROUTE"}, + {RTM_GETROUTE, "RTM_GETROUTE"}, + {RTM_NEWLINK, "RTM_NEWLINK"}, + {RTM_DELLINK, "RTM_DELLINK"}, + {RTM_GETLINK, "RTM_GETLINK"}, + {RTM_NEWADDR, "RTM_NEWADDR"}, + {RTM_DELADDR, "RTM_DELADDR"}, + {RTM_GETADDR, "RTM_GETADDR"}, + {RTM_NEWNEIGH, "RTM_NEWNEIGH"}, + {RTM_DELNEIGH, "RTM_DELNEIGH"}, + {RTM_GETNEIGH, "RTM_GETNEIGH"}, + {0}}; static const struct message rtproto_str[] = { - {RTPROT_REDIRECT, "redirect"}, - {RTPROT_KERNEL, "kernel"}, - {RTPROT_BOOT, "boot"}, - {RTPROT_STATIC, "static"}, - {RTPROT_GATED, "GateD"}, - {RTPROT_RA, "router advertisement"}, - {RTPROT_MRT, "MRT"}, - {RTPROT_ZEBRA, "Zebra"}, + {RTPROT_REDIRECT, "redirect"}, + {RTPROT_KERNEL, "kernel"}, + {RTPROT_BOOT, "boot"}, + {RTPROT_STATIC, "static"}, + {RTPROT_GATED, "GateD"}, + {RTPROT_RA, "router advertisement"}, + {RTPROT_MRT, "MRT"}, + {RTPROT_ZEBRA, "Zebra"}, #ifdef RTPROT_BIRD - {RTPROT_BIRD, "BIRD"}, + {RTPROT_BIRD, "BIRD"}, #endif /* RTPROT_BIRD */ - {RTPROT_MROUTED, "mroute"}, - {RTPROT_BGP, "BGP"}, - {RTPROT_OSPF, "OSPF"}, - {RTPROT_ISIS, "IS-IS"}, - {RTPROT_RIP, "RIP"}, - {RTPROT_RIPNG, "RIPNG"}, - { 0 } -}; - -static const struct message family_str[] = { - {AF_INET, "ipv4"}, - {AF_INET6, "ipv6"}, - {AF_BRIDGE, "bridge"}, - {RTNL_FAMILY_IPMR, "ipv4MR"}, - {RTNL_FAMILY_IP6MR, "ipv6MR"}, - { 0 } -}; - -static const struct message rttype_str[] = { - {RTN_UNICAST, "unicast"}, - {RTN_MULTICAST, "multicast"}, - { 0 } -}; + {RTPROT_MROUTED, "mroute"}, + {RTPROT_BGP, "BGP"}, + {RTPROT_OSPF, "OSPF"}, + {RTPROT_ISIS, "IS-IS"}, + {RTPROT_RIP, "RIP"}, + {RTPROT_RIPNG, "RIPNG"}, + {0}}; + +static const struct message family_str[] = {{AF_INET, "ipv4"}, + {AF_INET6, "ipv6"}, + {AF_BRIDGE, "bridge"}, + {RTNL_FAMILY_IPMR, "ipv4MR"}, + {RTNL_FAMILY_IP6MR, "ipv6MR"}, + {0}}; + +static const struct message rttype_str[] = {{RTN_UNICAST, "unicast"}, + {RTN_MULTICAST, "multicast"}, + {0}}; extern struct thread_master *master; extern u_int32_t nl_rcvbufsize; extern struct zebra_privs_t zserv_privs; -int -netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +int netlink_talk_filter(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - zlog_warn ("netlink_talk: ignoring message type 0x%04x NS %u", h->nlmsg_type, - ns_id); - return 0; + zlog_warn("netlink_talk: ignoring message type 0x%04x NS %u", + h->nlmsg_type, ns_id); + return 0; } -static int -netlink_recvbuf (struct nlsock *nl, uint32_t newsize) +static int netlink_recvbuf(struct nlsock *nl, uint32_t newsize) { - u_int32_t oldsize; - socklen_t newlen = sizeof(newsize); - socklen_t oldlen = sizeof(oldsize); - int ret; - - ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen); - if (ret < 0) - { - zlog_err("Can't get %s receive buffer size: %s", nl->name, - safe_strerror(errno)); - return -1; - } - - /* Try force option (linux >= 2.6.14) and fall back to normal set */ - if ( zserv_privs.change (ZPRIVS_RAISE) ) - zlog_err ("routing_socket: Can't raise privileges"); - ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUFFORCE, &nl_rcvbufsize, - sizeof(nl_rcvbufsize)); - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("routing_socket: Can't lower privileges"); - if (ret < 0) - ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize, - sizeof(nl_rcvbufsize)); - if (ret < 0) - { - zlog_err("Can't set %s receive buffer size: %s", nl->name, - safe_strerror(errno)); - return -1; - } - - ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen); - if (ret < 0) - { - zlog_err("Can't get %s receive buffer size: %s", nl->name, - safe_strerror(errno)); - return -1; - } - - zlog_info("Setting netlink socket receive buffer size: %u -> %u", oldsize, - newsize); - return 0; + u_int32_t oldsize; + socklen_t newlen = sizeof(newsize); + socklen_t oldlen = sizeof(oldsize); + int ret; + + ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen); + if (ret < 0) { + zlog_err("Can't get %s receive buffer size: %s", nl->name, + safe_strerror(errno)); + return -1; + } + + /* Try force option (linux >= 2.6.14) and fall back to normal set */ + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("routing_socket: Can't raise privileges"); + ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUFFORCE, &nl_rcvbufsize, + sizeof(nl_rcvbufsize)); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("routing_socket: Can't lower privileges"); + if (ret < 0) + ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, + &nl_rcvbufsize, sizeof(nl_rcvbufsize)); + if (ret < 0) { + zlog_err("Can't set %s receive buffer size: %s", nl->name, + safe_strerror(errno)); + return -1; + } + + ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen); + if (ret < 0) { + zlog_err("Can't get %s receive buffer size: %s", nl->name, + safe_strerror(errno)); + return -1; + } + + zlog_info("Setting netlink socket receive buffer size: %u -> %u", + oldsize, newsize); + return 0; } /* Make socket for Linux netlink interface. */ -static int -netlink_socket (struct nlsock *nl, unsigned long groups, ns_id_t ns_id) +static int netlink_socket(struct nlsock *nl, unsigned long groups, + ns_id_t ns_id) { - int ret; - struct sockaddr_nl snl; - int sock; - int namelen; - int save_errno; - - if (zserv_privs.change (ZPRIVS_RAISE)) - { - zlog_err("Can't raise privileges"); - return -1; - } - - sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (sock < 0) - { - zlog_err("Can't open %s socket: %s", nl->name, safe_strerror(errno)); - return -1; - } - - memset (&snl, 0, sizeof snl); - snl.nl_family = AF_NETLINK; - snl.nl_groups = groups; - - /* Bind the socket to the netlink structure for anything. */ - ret = bind (sock, (struct sockaddr *) &snl, sizeof snl); - save_errno = errno; - if (zserv_privs.change (ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - if (ret < 0) - { - zlog_err("Can't bind %s socket to group 0x%x: %s", nl->name, - snl.nl_groups, safe_strerror(save_errno)); - close (sock); - return -1; - } - - /* multiple netlink sockets will have different nl_pid */ - namelen = sizeof snl; - ret = getsockname (sock, (struct sockaddr *) &snl, (socklen_t *) &namelen); - if (ret < 0 || namelen != sizeof snl) - { - zlog_err("Can't get %s socket name: %s", nl->name, safe_strerror(errno)); - close (sock); - return -1; - } - - nl->snl = snl; - nl->sock = sock; - return ret; + int ret; + struct sockaddr_nl snl; + int sock; + int namelen; + int save_errno; + + if (zserv_privs.change(ZPRIVS_RAISE)) { + zlog_err("Can't raise privileges"); + return -1; + } + + sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (sock < 0) { + zlog_err("Can't open %s socket: %s", nl->name, + safe_strerror(errno)); + return -1; + } + + memset(&snl, 0, sizeof snl); + snl.nl_family = AF_NETLINK; + snl.nl_groups = groups; + + /* Bind the socket to the netlink structure for anything. */ + ret = bind(sock, (struct sockaddr *)&snl, sizeof snl); + save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + if (ret < 0) { + zlog_err("Can't bind %s socket to group 0x%x: %s", nl->name, + snl.nl_groups, safe_strerror(save_errno)); + close(sock); + return -1; + } + + /* multiple netlink sockets will have different nl_pid */ + namelen = sizeof snl; + ret = getsockname(sock, (struct sockaddr *)&snl, (socklen_t *)&namelen); + if (ret < 0 || namelen != sizeof snl) { + zlog_err("Can't get %s socket name: %s", nl->name, + safe_strerror(errno)); + close(sock); + return -1; + } + + nl->snl = snl; + nl->sock = sock; + return ret; } -static int -netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +static int netlink_information_fetch(struct sockaddr_nl *snl, + struct nlmsghdr *h, ns_id_t ns_id, + int startup) { - /* JF: Ignore messages that aren't from the kernel */ - if ( snl->nl_pid != 0 ) - { - zlog_err("Ignoring message from pid %u", snl->nl_pid); - return 0; - } - - switch (h->nlmsg_type) - { - case RTM_NEWROUTE: - return netlink_route_change (snl, h, ns_id, startup); - break; - case RTM_DELROUTE: - return netlink_route_change (snl, h, ns_id, startup); - break; - case RTM_NEWLINK: - return netlink_link_change (snl, h, ns_id, startup); - break; - case RTM_DELLINK: - return netlink_link_change (snl, h, ns_id, startup); - break; - case RTM_NEWADDR: - return netlink_interface_addr (snl, h, ns_id, startup); - break; - case RTM_DELADDR: - return netlink_interface_addr (snl, h, ns_id, startup); - break; - case RTM_NEWNEIGH: - return netlink_neigh_change (snl, h, ns_id); - break; - case RTM_DELNEIGH: - return netlink_neigh_change (snl, h, ns_id); - break; - default: - zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type, - ns_id); - break; - } - return 0; + /* JF: Ignore messages that aren't from the kernel */ + if (snl->nl_pid != 0) { + zlog_err("Ignoring message from pid %u", snl->nl_pid); + return 0; + } + + switch (h->nlmsg_type) { + case RTM_NEWROUTE: + return netlink_route_change(snl, h, ns_id, startup); + break; + case RTM_DELROUTE: + return netlink_route_change(snl, h, ns_id, startup); + break; + case RTM_NEWLINK: + return netlink_link_change(snl, h, ns_id, startup); + break; + case RTM_DELLINK: + return netlink_link_change(snl, h, ns_id, startup); + break; + case RTM_NEWADDR: + return netlink_interface_addr(snl, h, ns_id, startup); + break; + case RTM_DELADDR: + return netlink_interface_addr(snl, h, ns_id, startup); + break; + case RTM_NEWNEIGH: + return netlink_neigh_change(snl, h, ns_id); + break; + case RTM_DELNEIGH: + return netlink_neigh_change(snl, h, ns_id); + break; + default: + zlog_warn("Unknown netlink nlmsg_type %d vrf %u\n", + h->nlmsg_type, ns_id); + break; + } + return 0; } -static int -kernel_read (struct thread *thread) +static int kernel_read(struct thread *thread) { - struct zebra_ns *zns = (struct zebra_ns *)THREAD_ARG (thread); - netlink_parse_info (netlink_information_fetch, &zns->netlink, zns, 5, 0); - zns->t_netlink = NULL; - thread_add_read(zebrad.master, kernel_read, zns, zns->netlink.sock, - &zns->t_netlink); + struct zebra_ns *zns = (struct zebra_ns *)THREAD_ARG(thread); + netlink_parse_info(netlink_information_fetch, &zns->netlink, zns, 5, 0); + zns->t_netlink = NULL; + thread_add_read(zebrad.master, kernel_read, zns, zns->netlink.sock, + &zns->t_netlink); - return 0; + return 0; } /* Filter out messages from self that occur on listener socket, * caused by our actions on the command socket */ -static void netlink_install_filter (int sock, __u32 pid) +static void netlink_install_filter(int sock, __u32 pid) { - struct sock_filter filter[] = { - /* 0: ldh [4] */ - BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), - /* 1: jeq 0x18 jt 5 jf next */ - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 3, 0), - /* 2: jeq 0x19 jt 5 jf next */ - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 2, 0), - /* 3: jeq 0x19 jt 5 jf next */ - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWNEIGH), 1, 0), - /* 4: jeq 0x19 jt 5 jf 8 */ - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELNEIGH), 0, 3), - /* 5: ldw [12] */ - BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)), - /* 6: jeq XX jt 7 jf 8 */ - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1), - /* 7: ret 0 (skip) */ - BPF_STMT(BPF_RET|BPF_K, 0), - /* 8: ret 0xffff (keep) */ - BPF_STMT(BPF_RET|BPF_K, 0xffff), - }; - - struct sock_fprog prog = { - .len = array_size(filter), - .filter = filter, - }; - - if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0) - zlog_warn ("Can't install socket filter: %s\n", safe_strerror(errno)); + struct sock_filter filter[] = { + /* 0: ldh [4] */ + BPF_STMT(BPF_LD | BPF_ABS | BPF_H, + offsetof(struct nlmsghdr, nlmsg_type)), + /* 1: jeq 0x18 jt 5 jf next */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htons(RTM_NEWROUTE), 3, 0), + /* 2: jeq 0x19 jt 5 jf next */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htons(RTM_DELROUTE), 2, 0), + /* 3: jeq 0x19 jt 5 jf next */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htons(RTM_NEWNEIGH), 1, 0), + /* 4: jeq 0x19 jt 5 jf 8 */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htons(RTM_DELNEIGH), 0, 3), + /* 5: ldw [12] */ + BPF_STMT(BPF_LD | BPF_ABS | BPF_W, + offsetof(struct nlmsghdr, nlmsg_pid)), + /* 6: jeq XX jt 7 jf 8 */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htonl(pid), 0, 1), + /* 7: ret 0 (skip) */ + BPF_STMT(BPF_RET | BPF_K, 0), + /* 8: ret 0xffff (keep) */ + BPF_STMT(BPF_RET | BPF_K, 0xffff), + }; + + struct sock_fprog prog = { + .len = array_size(filter), .filter = filter, + }; + + if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) + < 0) + zlog_warn("Can't install socket filter: %s\n", + safe_strerror(errno)); } -void -netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta, - int len) +void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, + int len) { - while (RTA_OK (rta, len)) - { - if (rta->rta_type <= max) - tb[rta->rta_type] = rta; - rta = RTA_NEXT (rta, len); - } + while (RTA_OK(rta, len)) { + if (rta->rta_type <= max) + tb[rta->rta_type] = rta; + rta = RTA_NEXT(rta, len); + } } -int -addattr_l (struct nlmsghdr *n, unsigned int maxlen, int type, - void *data, unsigned int alen) +int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, void *data, + unsigned int alen) { - int len; - struct rtattr *rta; + int len; + struct rtattr *rta; - len = RTA_LENGTH (alen); + len = RTA_LENGTH(alen); - if (NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len) > maxlen) - return -1; + if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) + return -1; - rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len)); - rta->rta_type = type; - rta->rta_len = len; + rta = (struct rtattr *)(((char *)n) + NLMSG_ALIGN(n->nlmsg_len)); + rta->rta_type = type; + rta->rta_len = len; - if (data) - memcpy (RTA_DATA (rta), data, alen); - else - assert (alen == 0); + if (data) + memcpy(RTA_DATA(rta), data, alen); + else + assert(alen == 0); - n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len); + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); - return 0; + return 0; } -int -rta_addattr_l (struct rtattr *rta, unsigned int maxlen, int type, - void *data, unsigned int alen) +int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type, void *data, + unsigned int alen) { - unsigned int len; - struct rtattr *subrta; + unsigned int len; + struct rtattr *subrta; - len = RTA_LENGTH (alen); + len = RTA_LENGTH(alen); - if (RTA_ALIGN (rta->rta_len) + RTA_ALIGN (len) > maxlen) - return -1; + if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) + return -1; - subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len)); - subrta->rta_type = type; - subrta->rta_len = len; + subrta = (struct rtattr *)(((char *)rta) + RTA_ALIGN(rta->rta_len)); + subrta->rta_type = type; + subrta->rta_len = len; - if (data) - memcpy (RTA_DATA (subrta), data, alen); - else - assert (alen == 0); + if (data) + memcpy(RTA_DATA(subrta), data, alen); + else + assert(alen == 0); - rta->rta_len = NLMSG_ALIGN (rta->rta_len) + RTA_ALIGN (len); + rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len); - return 0; + return 0; } -int -addattr16 (struct nlmsghdr *n, unsigned int maxlen, int type, u_int16_t data) +int addattr16(struct nlmsghdr *n, unsigned int maxlen, int type, u_int16_t data) { - return addattr_l(n, maxlen, type, &data, sizeof(u_int16_t)); + return addattr_l(n, maxlen, type, &data, sizeof(u_int16_t)); } -int -addattr32 (struct nlmsghdr *n, unsigned int maxlen, int type, int data) +int addattr32(struct nlmsghdr *n, unsigned int maxlen, int type, int data) { - return addattr_l(n, maxlen, type, &data, sizeof(u_int32_t)); + return addattr_l(n, maxlen, type, &data, sizeof(u_int32_t)); } -struct rtattr * -addattr_nest(struct nlmsghdr *n, int maxlen, int type) +struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type) { - struct rtattr *nest = NLMSG_TAIL(n); + struct rtattr *nest = NLMSG_TAIL(n); - addattr_l(n, maxlen, type, NULL, 0); - return nest; + addattr_l(n, maxlen, type, NULL, 0); + return nest; } -int -addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest) +int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest) { - nest->rta_len = (u_char *)NLMSG_TAIL(n) - (u_char *)nest; - return n->nlmsg_len; + nest->rta_len = (u_char *)NLMSG_TAIL(n) - (u_char *)nest; + return n->nlmsg_len; } -struct rtattr * -rta_nest(struct rtattr *rta, int maxlen, int type) +struct rtattr *rta_nest(struct rtattr *rta, int maxlen, int type) { - struct rtattr *nest = RTA_TAIL(rta); + struct rtattr *nest = RTA_TAIL(rta); - rta_addattr_l(rta, maxlen, type, NULL, 0); - return nest; + rta_addattr_l(rta, maxlen, type, NULL, 0); + return nest; } -int -rta_nest_end(struct rtattr *rta, struct rtattr *nest) +int rta_nest_end(struct rtattr *rta, struct rtattr *nest) { - nest->rta_len = (u_char *)RTA_TAIL(rta) - (u_char *)nest; - return rta->rta_len; + nest->rta_len = (u_char *)RTA_TAIL(rta) - (u_char *)nest; + return rta->rta_len; } -const char * -nl_msg_type_to_str (uint16_t msg_type) +const char *nl_msg_type_to_str(uint16_t msg_type) { - return lookup_msg (nlmsg_str, msg_type, ""); + return lookup_msg(nlmsg_str, msg_type, ""); } -const char * -nl_rtproto_to_str (u_char rtproto) +const char *nl_rtproto_to_str(u_char rtproto) { - return lookup_msg (rtproto_str, rtproto, ""); + return lookup_msg(rtproto_str, rtproto, ""); } -const char * -nl_family_to_str (u_char family) +const char *nl_family_to_str(u_char family) { - return lookup_msg (family_str, family, ""); + return lookup_msg(family_str, family, ""); } -const char * -nl_rttype_to_str (u_char rttype) +const char *nl_rttype_to_str(u_char rttype) { - return lookup_msg (rttype_str, rttype, ""); + return lookup_msg(rttype_str, rttype, ""); } /* @@ -475,192 +447,210 @@ nl_rttype_to_str (u_char rttype) * startup -> Are we reading in under startup conditions? passed to * the filter. */ -int -netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, - ns_id_t, int), - struct nlsock *nl, struct zebra_ns *zns, int count, int startup) +int netlink_parse_info(int (*filter)(struct sockaddr_nl *, struct nlmsghdr *, + ns_id_t, int), + struct nlsock *nl, struct zebra_ns *zns, int count, + int startup) { - int status; - int ret = 0; - int error; - int read_in = 0; - - while (1) - { - char buf[NL_PKT_BUF_SIZE]; - struct iovec iov = { - .iov_base = buf, - .iov_len = sizeof buf - }; - struct sockaddr_nl snl; - struct msghdr msg = { - .msg_name = (void *) &snl, - .msg_namelen = sizeof snl, - .msg_iov = &iov, - .msg_iovlen = 1 - }; - struct nlmsghdr *h; - - if (count && read_in >= count) - return 0; - - status = recvmsg (nl->sock, &msg, 0); - if (status < 0) - { - if (errno == EINTR) - continue; - if (errno == EWOULDBLOCK || errno == EAGAIN) - break; - zlog_err("%s recvmsg overrun: %s", nl->name, safe_strerror(errno)); - /* - * In this case we are screwed. - * There is no good way to - * recover zebra at this point. - */ - exit (-1); - continue; - } - - if (status == 0) - { - zlog_err("%s EOF", nl->name); - return -1; - } - - if (msg.msg_namelen != sizeof snl) - { - zlog_err("%s sender address length error: length %d", nl->name, - msg.msg_namelen); - return -1; - } - - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) - { - zlog_debug("%s: << netlink message dump [recv]", __func__); - zlog_hexdump(buf, status); - } - - read_in++; - for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status); - h = NLMSG_NEXT (h, status)) - { - /* Finish of reading. */ - if (h->nlmsg_type == NLMSG_DONE) - return ret; - - /* Error handling. */ - if (h->nlmsg_type == NLMSG_ERROR) - { - struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h); - int errnum = err->error; - int msg_type = err->msg.nlmsg_type; - - /* If the error field is zero, then this is an ACK */ - if (err->error == 0) - { - if (IS_ZEBRA_DEBUG_KERNEL) - { - zlog_debug ("%s: %s ACK: type=%s(%u), seq=%u, pid=%u", - __FUNCTION__, nl->name, - nl_msg_type_to_str (err->msg.nlmsg_type), - err->msg.nlmsg_type, err->msg.nlmsg_seq, - err->msg.nlmsg_pid); - } - - /* return if not a multipart message, otherwise continue */ - if (!(h->nlmsg_flags & NLM_F_MULTI)) - return 0; - continue; - } - - if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr))) - { - zlog_err("%s error: message truncated", nl->name); - return -1; - } - - /* Deal with errors that occur because of races in link handling */ - if (nl == &zns->netlink_cmd - && ((msg_type == RTM_DELROUTE && - (-errnum == ENODEV || -errnum == ESRCH)) - || (msg_type == RTM_NEWROUTE && - (-errnum == ENETDOWN || -errnum == EEXIST)))) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: error: %s type=%s(%u), seq=%u, pid=%u", - nl->name, safe_strerror (-errnum), - nl_msg_type_to_str (msg_type), - msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid); - return 0; + int status; + int ret = 0; + int error; + int read_in = 0; + + while (1) { + char buf[NL_PKT_BUF_SIZE]; + struct iovec iov = {.iov_base = buf, .iov_len = sizeof buf}; + struct sockaddr_nl snl; + struct msghdr msg = {.msg_name = (void *)&snl, + .msg_namelen = sizeof snl, + .msg_iov = &iov, + .msg_iovlen = 1}; + struct nlmsghdr *h; + + if (count && read_in >= count) + return 0; + + status = recvmsg(nl->sock, &msg, 0); + if (status < 0) { + if (errno == EINTR) + continue; + if (errno == EWOULDBLOCK || errno == EAGAIN) + break; + zlog_err("%s recvmsg overrun: %s", nl->name, + safe_strerror(errno)); + /* + * In this case we are screwed. + * There is no good way to + * recover zebra at this point. + */ + exit(-1); + continue; } - /* We see RTM_DELNEIGH when shutting down an interface with an IPv4 - * link-local. The kernel should have already deleted the neighbor - * so do not log these as an error. - */ - if (msg_type == RTM_DELNEIGH || - (nl == &zns->netlink_cmd && msg_type == RTM_NEWROUTE && - (-errnum == ESRCH || -errnum == ENETUNREACH))) - { - /* This is known to happen in some situations, don't log - * as error. - */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s error: %s, type=%s(%u), seq=%u, pid=%u", - nl->name, safe_strerror (-errnum), - nl_msg_type_to_str (msg_type), - msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid); - } - else - zlog_err ("%s error: %s, type=%s(%u), seq=%u, pid=%u", - nl->name, safe_strerror (-errnum), - nl_msg_type_to_str (msg_type), - msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid); - - return -1; - } - - /* OK we got netlink message. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("netlink_parse_info: %s type %s(%u), len=%d, seq=%u, pid=%u", - nl->name, - nl_msg_type_to_str (h->nlmsg_type), h->nlmsg_type, - h->nlmsg_len, h->nlmsg_seq, h->nlmsg_pid); - - /* skip unsolicited messages originating from command socket - * linux sets the originators port-id for {NEW|DEL}ADDR messages, - * so this has to be checked here. */ - if (nl != &zns->netlink_cmd - && h->nlmsg_pid == zns->netlink_cmd.snl.nl_pid - && (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("netlink_parse_info: %s packet comes from %s", - zns->netlink_cmd.name, nl->name); - continue; - } - - error = (*filter) (&snl, h, zns->ns_id, startup); - if (error < 0) - { - zlog_err("%s filter function error", nl->name); - ret = error; - } - } - - /* After error care. */ - if (msg.msg_flags & MSG_TRUNC) - { - zlog_err("%s error: message truncated", nl->name); - continue; - } - if (status) - { - zlog_err("%s error: data remnant size %d", nl->name, status); - return -1; - } - } - return ret; + if (status == 0) { + zlog_err("%s EOF", nl->name); + return -1; + } + + if (msg.msg_namelen != sizeof snl) { + zlog_err("%s sender address length error: length %d", + nl->name, msg.msg_namelen); + return -1; + } + + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) { + zlog_debug("%s: << netlink message dump [recv]", + __func__); + zlog_hexdump(buf, status); + } + + read_in++; + for (h = (struct nlmsghdr *)buf; + NLMSG_OK(h, (unsigned int)status); + h = NLMSG_NEXT(h, status)) { + /* Finish of reading. */ + if (h->nlmsg_type == NLMSG_DONE) + return ret; + + /* Error handling. */ + if (h->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = + (struct nlmsgerr *)NLMSG_DATA(h); + int errnum = err->error; + int msg_type = err->msg.nlmsg_type; + + /* If the error field is zero, then this is an + * ACK */ + if (err->error == 0) { + if (IS_ZEBRA_DEBUG_KERNEL) { + zlog_debug( + "%s: %s ACK: type=%s(%u), seq=%u, pid=%u", + __FUNCTION__, nl->name, + nl_msg_type_to_str( + err->msg.nlmsg_type), + err->msg.nlmsg_type, + err->msg.nlmsg_seq, + err->msg.nlmsg_pid); + } + + /* return if not a multipart message, + * otherwise continue */ + if (!(h->nlmsg_flags & NLM_F_MULTI)) + return 0; + continue; + } + + if (h->nlmsg_len + < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { + zlog_err("%s error: message truncated", + nl->name); + return -1; + } + + /* Deal with errors that occur because of races + * in link handling */ + if (nl == &zns->netlink_cmd + && ((msg_type == RTM_DELROUTE + && (-errnum == ENODEV + || -errnum == ESRCH)) + || (msg_type == RTM_NEWROUTE + && (-errnum == ENETDOWN + || -errnum == EEXIST)))) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: error: %s type=%s(%u), seq=%u, pid=%u", + nl->name, + safe_strerror(-errnum), + nl_msg_type_to_str( + msg_type), + msg_type, + err->msg.nlmsg_seq, + err->msg.nlmsg_pid); + return 0; + } + + /* We see RTM_DELNEIGH when shutting down an + * interface with an IPv4 + * link-local. The kernel should have already + * deleted the neighbor + * so do not log these as an error. + */ + if (msg_type == RTM_DELNEIGH + || (nl == &zns->netlink_cmd + && msg_type == RTM_NEWROUTE + && (-errnum == ESRCH + || -errnum == ENETUNREACH))) { + /* This is known to happen in some + * situations, don't log + * as error. + */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s error: %s, type=%s(%u), seq=%u, pid=%u", + nl->name, + safe_strerror(-errnum), + nl_msg_type_to_str( + msg_type), + msg_type, + err->msg.nlmsg_seq, + err->msg.nlmsg_pid); + } else + zlog_err( + "%s error: %s, type=%s(%u), seq=%u, pid=%u", + nl->name, + safe_strerror(-errnum), + nl_msg_type_to_str(msg_type), + msg_type, err->msg.nlmsg_seq, + err->msg.nlmsg_pid); + + return -1; + } + + /* OK we got netlink message. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_parse_info: %s type %s(%u), len=%d, seq=%u, pid=%u", + nl->name, + nl_msg_type_to_str(h->nlmsg_type), + h->nlmsg_type, h->nlmsg_len, + h->nlmsg_seq, h->nlmsg_pid); + + /* skip unsolicited messages originating from command + * socket + * linux sets the originators port-id for {NEW|DEL}ADDR + * messages, + * so this has to be checked here. */ + if (nl != &zns->netlink_cmd + && h->nlmsg_pid == zns->netlink_cmd.snl.nl_pid + && (h->nlmsg_type != RTM_NEWADDR + && h->nlmsg_type != RTM_DELADDR)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_parse_info: %s packet comes from %s", + zns->netlink_cmd.name, + nl->name); + continue; + } + + error = (*filter)(&snl, h, zns->ns_id, startup); + if (error < 0) { + zlog_err("%s filter function error", nl->name); + ret = error; + } + } + + /* After error care. */ + if (msg.msg_flags & MSG_TRUNC) { + zlog_err("%s error: message truncated", nl->name); + continue; + } + if (status) { + zlog_err("%s error: data remnant size %d", nl->name, + status); + return -1; + } + } + return ret; } /* @@ -676,173 +666,163 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, * startup -> Are we reading in under startup conditions * This is passed through eventually to filter. */ -int -netlink_talk (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, - ns_id_t, int startup), - struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns, int startup) +int netlink_talk(int (*filter)(struct sockaddr_nl *, struct nlmsghdr *, ns_id_t, + int startup), + struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns, + int startup) { - int status; - struct sockaddr_nl snl; - struct iovec iov = { - .iov_base = (void *) n, - .iov_len = n->nlmsg_len - }; - struct msghdr msg = { - .msg_name = (void *) &snl, - .msg_namelen = sizeof snl, - .msg_iov = &iov, - .msg_iovlen = 1, - }; - int save_errno; - - memset (&snl, 0, sizeof snl); - snl.nl_family = AF_NETLINK; - - n->nlmsg_seq = ++nl->seq; - n->nlmsg_pid = nl->snl.nl_pid; - - /* Request an acknowledgement by setting NLM_F_ACK */ - n->nlmsg_flags |= NLM_F_ACK; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("netlink_talk: %s type %s(%u), len=%d seq=%u flags 0x%x", - nl->name, - nl_msg_type_to_str (n->nlmsg_type), n->nlmsg_type, - n->nlmsg_len, n->nlmsg_seq, n->nlmsg_flags); - - /* Send message to netlink interface. */ - if (zserv_privs.change (ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - status = sendmsg (nl->sock, &msg, 0); - save_errno = errno; - if (zserv_privs.change (ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) - { - zlog_debug("%s: >> netlink message dump [sent]", __func__); - zlog_hexdump(n, n->nlmsg_len); - } - - if (status < 0) - { - zlog_err("netlink_talk sendmsg() error: %s", safe_strerror(save_errno)); - return -1; - } - - - /* - * Get reply from netlink socket. - * The reply should either be an acknowlegement or an error. - */ - return netlink_parse_info (filter, nl, zns, 0, startup); + int status; + struct sockaddr_nl snl; + struct iovec iov = {.iov_base = (void *)n, .iov_len = n->nlmsg_len}; + struct msghdr msg = { + .msg_name = (void *)&snl, + .msg_namelen = sizeof snl, + .msg_iov = &iov, + .msg_iovlen = 1, + }; + int save_errno; + + memset(&snl, 0, sizeof snl); + snl.nl_family = AF_NETLINK; + + n->nlmsg_seq = ++nl->seq; + n->nlmsg_pid = nl->snl.nl_pid; + + /* Request an acknowledgement by setting NLM_F_ACK */ + n->nlmsg_flags |= NLM_F_ACK; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_talk: %s type %s(%u), len=%d seq=%u flags 0x%x", + nl->name, nl_msg_type_to_str(n->nlmsg_type), + n->nlmsg_type, n->nlmsg_len, n->nlmsg_seq, + n->nlmsg_flags); + + /* Send message to netlink interface. */ + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + status = sendmsg(nl->sock, &msg, 0); + save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) { + zlog_debug("%s: >> netlink message dump [sent]", __func__); + zlog_hexdump(n, n->nlmsg_len); + } + + if (status < 0) { + zlog_err("netlink_talk sendmsg() error: %s", + safe_strerror(save_errno)); + return -1; + } + + + /* + * Get reply from netlink socket. + * The reply should either be an acknowlegement or an error. + */ + return netlink_parse_info(filter, nl, zns, 0, startup); } /* Issue request message to kernel via netlink socket. GET messages * are issued through this interface. */ -int -netlink_request (struct nlsock *nl, struct nlmsghdr *n) +int netlink_request(struct nlsock *nl, struct nlmsghdr *n) { - int ret; - struct sockaddr_nl snl; - int save_errno; - - /* Check netlink socket. */ - if (nl->sock < 0) - { - zlog_err("%s socket isn't active.", nl->name); - return -1; - } - - /* Fill common fields for all requests. */ - n->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; - n->nlmsg_pid = nl->snl.nl_pid; - n->nlmsg_seq = ++nl->seq; - - memset (&snl, 0, sizeof snl); - snl.nl_family = AF_NETLINK; - - /* Raise capabilities and send message, then lower capabilities. */ - if (zserv_privs.change (ZPRIVS_RAISE)) - { - zlog_err("Can't raise privileges"); - return -1; - } - - ret = sendto (nl->sock, (void *)n, n->nlmsg_len, 0, - (struct sockaddr *) &snl, sizeof snl); - save_errno = errno; - - if (zserv_privs.change (ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - if (ret < 0) - { - zlog_err("%s sendto failed: %s", nl->name, safe_strerror(save_errno)); - return -1; - } - - return 0; + int ret; + struct sockaddr_nl snl; + int save_errno; + + /* Check netlink socket. */ + if (nl->sock < 0) { + zlog_err("%s socket isn't active.", nl->name); + return -1; + } + + /* Fill common fields for all requests. */ + n->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; + n->nlmsg_pid = nl->snl.nl_pid; + n->nlmsg_seq = ++nl->seq; + + memset(&snl, 0, sizeof snl); + snl.nl_family = AF_NETLINK; + + /* Raise capabilities and send message, then lower capabilities. */ + if (zserv_privs.change(ZPRIVS_RAISE)) { + zlog_err("Can't raise privileges"); + return -1; + } + + ret = sendto(nl->sock, (void *)n, n->nlmsg_len, 0, + (struct sockaddr *)&snl, sizeof snl); + save_errno = errno; + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + if (ret < 0) { + zlog_err("%s sendto failed: %s", nl->name, + safe_strerror(save_errno)); + return -1; + } + + return 0; } /* Exported interface function. This function simply calls netlink_socket (). */ -void -kernel_init (struct zebra_ns *zns) +void kernel_init(struct zebra_ns *zns) { - unsigned long groups; - - /* Initialize netlink sockets */ - groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR | - RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR | - RTMGRP_IPV4_MROUTE | RTMGRP_NEIGH; - - snprintf (zns->netlink.name, sizeof (zns->netlink.name), - "netlink-listen (NS %u)", zns->ns_id); - zns->netlink.sock = -1; - netlink_socket (&zns->netlink, groups, zns->ns_id); - - snprintf (zns->netlink_cmd.name, sizeof (zns->netlink_cmd.name), - "netlink-cmd (NS %u)", zns->ns_id); - zns->netlink_cmd.sock = -1; - netlink_socket (&zns->netlink_cmd, 0, zns->ns_id); - - /* Register kernel socket. */ - if (zns->netlink.sock > 0) - { - /* Only want non-blocking on the netlink event socket */ - if (fcntl (zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0) - zlog_err ("Can't set %s socket flags: %s", zns->netlink.name, - safe_strerror (errno)); - - /* Set receive buffer size if it's set from command line */ - if (nl_rcvbufsize) - netlink_recvbuf (&zns->netlink, nl_rcvbufsize); - - netlink_install_filter (zns->netlink.sock, zns->netlink_cmd.snl.nl_pid); - zns->t_netlink = NULL; - thread_add_read(zebrad.master, kernel_read, zns, zns->netlink.sock, - &zns->t_netlink); - } - - rt_netlink_init (); + unsigned long groups; + + /* Initialize netlink sockets */ + groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR + | RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_MROUTE + | RTMGRP_NEIGH; + + snprintf(zns->netlink.name, sizeof(zns->netlink.name), + "netlink-listen (NS %u)", zns->ns_id); + zns->netlink.sock = -1; + netlink_socket(&zns->netlink, groups, zns->ns_id); + + snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name), + "netlink-cmd (NS %u)", zns->ns_id); + zns->netlink_cmd.sock = -1; + netlink_socket(&zns->netlink_cmd, 0, zns->ns_id); + + /* Register kernel socket. */ + if (zns->netlink.sock > 0) { + /* Only want non-blocking on the netlink event socket */ + if (fcntl(zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0) + zlog_err("Can't set %s socket flags: %s", + zns->netlink.name, safe_strerror(errno)); + + /* Set receive buffer size if it's set from command line */ + if (nl_rcvbufsize) + netlink_recvbuf(&zns->netlink, nl_rcvbufsize); + + netlink_install_filter(zns->netlink.sock, + zns->netlink_cmd.snl.nl_pid); + zns->t_netlink = NULL; + thread_add_read(zebrad.master, kernel_read, zns, + zns->netlink.sock, &zns->t_netlink); + } + + rt_netlink_init(); } -void -kernel_terminate (struct zebra_ns *zns) +void kernel_terminate(struct zebra_ns *zns) { - THREAD_READ_OFF (zns->t_netlink); - - if (zns->netlink.sock >= 0) - { - close (zns->netlink.sock); - zns->netlink.sock = -1; - } - - if (zns->netlink_cmd.sock >= 0) - { - close (zns->netlink_cmd.sock); - zns->netlink_cmd.sock = -1; - } + THREAD_READ_OFF(zns->t_netlink); + + if (zns->netlink.sock >= 0) { + close(zns->netlink.sock); + zns->netlink.sock = -1; + } + + if (zns->netlink_cmd.sock >= 0) { + close(zns->netlink_cmd.sock); + zns->netlink_cmd.sock = -1; + } } diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index d64242323..e5a079af5 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -25,36 +25,36 @@ #define NL_PKT_BUF_SIZE 8192 -extern void netlink_parse_rtattr (struct rtattr **tb, int max, - struct rtattr *rta, int len); -extern int addattr_l (struct nlmsghdr *n, unsigned int maxlen, - int type, void *data, unsigned int alen); -extern int rta_addattr_l (struct rtattr *rta, unsigned int maxlen, - int type, void *data, unsigned int alen); -extern int addattr16 (struct nlmsghdr *n, unsigned int maxlen, - int type, u_int16_t data); -extern int addattr32 (struct nlmsghdr *n, unsigned int maxlen, - int type, int data); +extern void netlink_parse_rtattr(struct rtattr **tb, int max, + struct rtattr *rta, int len); +extern int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, + void *data, unsigned int alen); +extern int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type, + void *data, unsigned int alen); +extern int addattr16(struct nlmsghdr *n, unsigned int maxlen, int type, + u_int16_t data); +extern int addattr32(struct nlmsghdr *n, unsigned int maxlen, int type, + int data); extern struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type); extern int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest); -extern struct rtattr * rta_nest(struct rtattr *rta, int maxlen, int type); +extern struct rtattr *rta_nest(struct rtattr *rta, int maxlen, int type); extern int rta_nest_end(struct rtattr *rta, struct rtattr *nest); -extern const char * nl_msg_type_to_str (uint16_t msg_type); -extern const char * nl_rtproto_to_str (u_char rtproto); -extern const char * nl_family_to_str (u_char family); -extern const char * nl_rttype_to_str (u_char rttype); +extern const char *nl_msg_type_to_str(uint16_t msg_type); +extern const char *nl_rtproto_to_str(u_char rtproto); +extern const char *nl_family_to_str(u_char family); +extern const char *nl_rttype_to_str(u_char rttype); -extern int netlink_parse_info (int (*filter) (struct sockaddr_nl *, - struct nlmsghdr *, ns_id_t, int), - struct nlsock *nl, struct zebra_ns *zns, - int count, int startup); -extern int netlink_talk_filter (struct sockaddr_nl *, struct nlmsghdr *, - ns_id_t, int startup); -extern int netlink_talk (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, - ns_id_t, int startup), - struct nlmsghdr *n, struct nlsock *nl, - struct zebra_ns *zns, int startup); -extern int netlink_request (struct nlsock *nl, struct nlmsghdr *n); +extern int netlink_parse_info(int (*filter)(struct sockaddr_nl *, + struct nlmsghdr *, ns_id_t, int), + struct nlsock *nl, struct zebra_ns *zns, + int count, int startup); +extern int netlink_talk_filter(struct sockaddr_nl *, struct nlmsghdr *, ns_id_t, + int startup); +extern int netlink_talk(int (*filter)(struct sockaddr_nl *, struct nlmsghdr *, + ns_id_t, int startup), + struct nlmsghdr *n, struct nlsock *nl, + struct zebra_ns *zns, int startup); +extern int netlink_request(struct nlsock *nl, struct nlmsghdr *n); #endif /* HAVE_NETLINK */ diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 5b9236f7f..4b63a3eb0 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -90,7 +90,8 @@ extern struct zebra_privs_t zserv_privs; * intentional, to provoke filing bug reports with operating systems * that don't define RT_ROUNDUP or equivalent. */ -#warning "net/route.h does not define RT_ROUNDUP; making unwarranted assumptions!" +#warning \ + "net/route.h does not define RT_ROUNDUP; making unwarranted assumptions!" /* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */ #ifdef __APPLE__ @@ -99,8 +100,9 @@ extern struct zebra_privs_t zserv_privs; #define ROUNDUP_TYPE long #endif -#define ROUNDUP(a) \ - ((a) > 0 ? (1 + (((a) - 1) | (sizeof(ROUNDUP_TYPE) - 1))) : sizeof(ROUNDUP_TYPE)) +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a)-1) | (sizeof(ROUNDUP_TYPE) - 1))) \ + : sizeof(ROUNDUP_TYPE)) #endif /* defined(ROUNDUP) */ @@ -115,13 +117,14 @@ extern struct zebra_privs_t zserv_privs; * One would hope all fixed-size structure definitions are aligned, * but round them up nonetheless. */ -#define SAROUNDUP(X) \ - (((struct sockaddr *)(X))->sa_family == AF_INET ? \ - ROUNDUP(sizeof(struct sockaddr_in)):\ - (((struct sockaddr *)(X))->sa_family == AF_INET6 ? \ - ROUNDUP(sizeof(struct sockaddr_in6)) : \ - (((struct sockaddr *)(X))->sa_family == AF_LINK ? \ - ROUNDUP(sizeof(struct sockaddr_dl)) : sizeof(struct sockaddr)))) +#define SAROUNDUP(X) \ + (((struct sockaddr *)(X))->sa_family == AF_INET \ + ? ROUNDUP(sizeof(struct sockaddr_in)) \ + : (((struct sockaddr *)(X))->sa_family == AF_INET6 \ + ? ROUNDUP(sizeof(struct sockaddr_in6)) \ + : (((struct sockaddr *)(X))->sa_family == AF_LINK \ + ? ROUNDUP(sizeof(struct sockaddr_dl)) \ + : sizeof(struct sockaddr)))) #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ #endif /* !SA_SIZE */ @@ -133,152 +136,140 @@ extern struct zebra_privs_t zserv_privs; * 2. So the compiler doesn't complain when DEST is NULL, which is only true * when we are skipping the copy and incrementing to the next SA */ -static inline void -rta_copy (union sockunion *dest, caddr_t src) { - int len; - if (!dest) - return; +static inline void rta_copy(union sockunion *dest, caddr_t src) +{ + int len; + if (!dest) + return; #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN - len = (((struct sockaddr *)src)->sa_len > sizeof (*dest)) ? - sizeof (*dest) : ((struct sockaddr *)src)->sa_len ; + len = (((struct sockaddr *)src)->sa_len > sizeof(*dest)) + ? sizeof(*dest) + : ((struct sockaddr *)src)->sa_len; #else - len = (SAROUNDUP (src) > sizeof (*dest)) ? - sizeof (*dest) : SAROUNDUP (src) ; + len = (SAROUNDUP(src) > sizeof(*dest)) ? sizeof(*dest) : SAROUNDUP(src); #endif - memcpy (dest, src, len); + memcpy(dest, src, len); } -#define RTA_ADDR_GET(DEST, RTA, RTMADDRS, PNT) \ - if ((RTMADDRS) & (RTA)) \ - { \ - int len = SAROUNDUP ((PNT)); \ - if (af_check (((struct sockaddr *)(PNT))->sa_family)) \ - rta_copy((DEST), (PNT)); \ - (PNT) += len; \ - } -#define RTA_ATTR_GET(DEST, RTA, RTMADDRS, PNT) \ - if ((RTMADDRS) & (RTA)) \ - { \ - int len = SAROUNDUP ((PNT)); \ - rta_copy((DEST), (PNT)); \ - (PNT) += len; \ - } - -#define RTA_NAME_GET(DEST, RTA, RTMADDRS, PNT, LEN) \ - if ((RTMADDRS) & (RTA)) \ - { \ - u_char *pdest = (u_char *) (DEST); \ - int len = SAROUNDUP ((PNT)); \ - struct sockaddr_dl *sdl = (struct sockaddr_dl *)(PNT); \ - if (IS_ZEBRA_DEBUG_KERNEL) \ - zlog_debug ("%s: RTA_SDL_GET nlen %d, alen %d", \ - __func__, sdl->sdl_nlen, sdl->sdl_alen); \ - if ( ((DEST) != NULL) && (sdl->sdl_family == AF_LINK) \ - && (sdl->sdl_nlen < IFNAMSIZ) && (sdl->sdl_nlen <= len) ) \ - { \ - memcpy (pdest, sdl->sdl_data, sdl->sdl_nlen); \ - pdest[sdl->sdl_nlen] = '\0'; \ - (LEN) = sdl->sdl_nlen; \ - } \ - (PNT) += len; \ - } \ - else \ - { \ - (LEN) = 0; \ - } +#define RTA_ADDR_GET(DEST, RTA, RTMADDRS, PNT) \ + if ((RTMADDRS) & (RTA)) { \ + int len = SAROUNDUP((PNT)); \ + if (af_check(((struct sockaddr *)(PNT))->sa_family)) \ + rta_copy((DEST), (PNT)); \ + (PNT) += len; \ + } +#define RTA_ATTR_GET(DEST, RTA, RTMADDRS, PNT) \ + if ((RTMADDRS) & (RTA)) { \ + int len = SAROUNDUP((PNT)); \ + rta_copy((DEST), (PNT)); \ + (PNT) += len; \ + } + +#define RTA_NAME_GET(DEST, RTA, RTMADDRS, PNT, LEN) \ + if ((RTMADDRS) & (RTA)) { \ + u_char *pdest = (u_char *)(DEST); \ + int len = SAROUNDUP((PNT)); \ + struct sockaddr_dl *sdl = (struct sockaddr_dl *)(PNT); \ + if (IS_ZEBRA_DEBUG_KERNEL) \ + zlog_debug("%s: RTA_SDL_GET nlen %d, alen %d", \ + __func__, sdl->sdl_nlen, sdl->sdl_alen); \ + if (((DEST) != NULL) && (sdl->sdl_family == AF_LINK) \ + && (sdl->sdl_nlen < IFNAMSIZ) && (sdl->sdl_nlen <= len)) { \ + memcpy(pdest, sdl->sdl_data, sdl->sdl_nlen); \ + pdest[sdl->sdl_nlen] = '\0'; \ + (LEN) = sdl->sdl_nlen; \ + } \ + (PNT) += len; \ + } else { \ + (LEN) = 0; \ + } /* Routing socket message types. */ -const struct message rtm_type_str[] = -{ - {RTM_ADD, "RTM_ADD"}, - {RTM_DELETE, "RTM_DELETE"}, - {RTM_CHANGE, "RTM_CHANGE"}, - {RTM_GET, "RTM_GET"}, - {RTM_LOSING, "RTM_LOSING"}, - {RTM_REDIRECT, "RTM_REDIRECT"}, - {RTM_MISS, "RTM_MISS"}, - {RTM_LOCK, "RTM_LOCK"}, +const struct message rtm_type_str[] = {{RTM_ADD, "RTM_ADD"}, + {RTM_DELETE, "RTM_DELETE"}, + {RTM_CHANGE, "RTM_CHANGE"}, + {RTM_GET, "RTM_GET"}, + {RTM_LOSING, "RTM_LOSING"}, + {RTM_REDIRECT, "RTM_REDIRECT"}, + {RTM_MISS, "RTM_MISS"}, + {RTM_LOCK, "RTM_LOCK"}, #ifdef OLDADD - {RTM_OLDADD, "RTM_OLDADD"}, + {RTM_OLDADD, "RTM_OLDADD"}, #endif /* RTM_OLDADD */ #ifdef RTM_OLDDEL - {RTM_OLDDEL, "RTM_OLDDEL"}, + {RTM_OLDDEL, "RTM_OLDDEL"}, #endif /* RTM_OLDDEL */ - {RTM_RESOLVE, "RTM_RESOLVE"}, - {RTM_NEWADDR, "RTM_NEWADDR"}, - {RTM_DELADDR, "RTM_DELADDR"}, - {RTM_IFINFO, "RTM_IFINFO"}, + {RTM_RESOLVE, "RTM_RESOLVE"}, + {RTM_NEWADDR, "RTM_NEWADDR"}, + {RTM_DELADDR, "RTM_DELADDR"}, + {RTM_IFINFO, "RTM_IFINFO"}, #ifdef RTM_OIFINFO - {RTM_OIFINFO, "RTM_OIFINFO"}, + {RTM_OIFINFO, "RTM_OIFINFO"}, #endif /* RTM_OIFINFO */ #ifdef RTM_NEWMADDR - {RTM_NEWMADDR, "RTM_NEWMADDR"}, + {RTM_NEWMADDR, "RTM_NEWMADDR"}, #endif /* RTM_NEWMADDR */ #ifdef RTM_DELMADDR - {RTM_DELMADDR, "RTM_DELMADDR"}, + {RTM_DELMADDR, "RTM_DELMADDR"}, #endif /* RTM_DELMADDR */ #ifdef RTM_IFANNOUNCE - {RTM_IFANNOUNCE, "RTM_IFANNOUNCE"}, + {RTM_IFANNOUNCE, "RTM_IFANNOUNCE"}, #endif /* RTM_IFANNOUNCE */ - { 0 } -}; - -static const struct message rtm_flag_str[] = -{ - {RTF_UP, "UP"}, - {RTF_GATEWAY, "GATEWAY"}, - {RTF_HOST, "HOST"}, - {RTF_REJECT, "REJECT"}, - {RTF_DYNAMIC, "DYNAMIC"}, - {RTF_MODIFIED, "MODIFIED"}, - {RTF_DONE, "DONE"}, + {0}}; + +static const struct message rtm_flag_str[] = {{RTF_UP, "UP"}, + {RTF_GATEWAY, "GATEWAY"}, + {RTF_HOST, "HOST"}, + {RTF_REJECT, "REJECT"}, + {RTF_DYNAMIC, "DYNAMIC"}, + {RTF_MODIFIED, "MODIFIED"}, + {RTF_DONE, "DONE"}, #ifdef RTF_MASK - {RTF_MASK, "MASK"}, + {RTF_MASK, "MASK"}, #endif /* RTF_MASK */ #ifdef RTF_CLONING - {RTF_CLONING, "CLONING"}, + {RTF_CLONING, "CLONING"}, #endif /* RTF_CLONING */ #ifdef RTF_XRESOLVE - {RTF_XRESOLVE, "XRESOLVE"}, + {RTF_XRESOLVE, "XRESOLVE"}, #endif /* RTF_XRESOLVE */ #ifdef RTF_LLINFO - {RTF_LLINFO, "LLINFO"}, + {RTF_LLINFO, "LLINFO"}, #endif /* RTF_LLINFO */ - {RTF_STATIC, "STATIC"}, - {RTF_BLACKHOLE, "BLACKHOLE"}, + {RTF_STATIC, "STATIC"}, + {RTF_BLACKHOLE, "BLACKHOLE"}, #ifdef RTF_PRIVATE - {RTF_PRIVATE, "PRIVATE"}, + {RTF_PRIVATE, "PRIVATE"}, #endif /* RTF_PRIVATE */ - {RTF_PROTO1, "PROTO1"}, - {RTF_PROTO2, "PROTO2"}, + {RTF_PROTO1, "PROTO1"}, + {RTF_PROTO2, "PROTO2"}, #ifdef RTF_PRCLONING - {RTF_PRCLONING, "PRCLONING"}, + {RTF_PRCLONING, "PRCLONING"}, #endif /* RTF_PRCLONING */ #ifdef RTF_WASCLONED - {RTF_WASCLONED, "WASCLONED"}, + {RTF_WASCLONED, "WASCLONED"}, #endif /* RTF_WASCLONED */ #ifdef RTF_PROTO3 - {RTF_PROTO3, "PROTO3"}, + {RTF_PROTO3, "PROTO3"}, #endif /* RTF_PROTO3 */ #ifdef RTF_PINNED - {RTF_PINNED, "PINNED"}, + {RTF_PINNED, "PINNED"}, #endif /* RTF_PINNED */ #ifdef RTF_LOCAL - {RTF_LOCAL, "LOCAL"}, + {RTF_LOCAL, "LOCAL"}, #endif /* RTF_LOCAL */ #ifdef RTF_BROADCAST - {RTF_BROADCAST, "BROADCAST"}, + {RTF_BROADCAST, "BROADCAST"}, #endif /* RTF_BROADCAST */ #ifdef RTF_MULTICAST - {RTF_MULTICAST, "MULTICAST"}, + {RTF_MULTICAST, "MULTICAST"}, #endif /* RTF_MULTICAST */ #ifdef RTF_MULTIRT - {RTF_MULTIRT, "MULTIRT"}, + {RTF_MULTIRT, "MULTIRT"}, #endif /* RTF_MULTIRT */ #ifdef RTF_SETSRC - {RTF_SETSRC, "SETSRC"}, + {RTF_SETSRC, "SETSRC"}, #endif /* RTF_SETSRC */ - { 0 } -}; + {0}}; /* Kernel routing update socket. */ int routing_sock = -1; @@ -287,115 +278,117 @@ int routing_sock = -1; /* #define DEBUG */ /* Supported address family check. */ -static inline int -af_check (int family) +static inline int af_check(int family) { - if (family == AF_INET) - return 1; - if (family == AF_INET6) - return 1; - return 0; + if (family == AF_INET) + return 1; + if (family == AF_INET6) + return 1; + return 0; } /* Dump routing table flag for debug purpose. */ -static void -rtm_flag_dump (int flag) +static void rtm_flag_dump(int flag) { - const struct message *mes; - static char buf[BUFSIZ]; - - buf[0] = '\0'; - for (mes = rtm_flag_str; mes->key != 0; mes++) - { - if (mes->key & flag) - { - strlcat (buf, mes->str, BUFSIZ); - strlcat (buf, " ", BUFSIZ); + const struct message *mes; + static char buf[BUFSIZ]; + + buf[0] = '\0'; + for (mes = rtm_flag_str; mes->key != 0; mes++) { + if (mes->key & flag) { + strlcat(buf, mes->str, BUFSIZ); + strlcat(buf, " ", BUFSIZ); + } } - } - zlog_debug ("Kernel: %s", buf); + zlog_debug("Kernel: %s", buf); } #ifdef RTM_IFANNOUNCE /* Interface adding function */ -static int -ifan_read (struct if_announcemsghdr *ifan) +static int ifan_read(struct if_announcemsghdr *ifan) { - struct interface *ifp; - - ifp = if_lookup_by_index (ifan->ifan_index, VRF_DEFAULT); - - if (ifp) - assert ( (ifp->ifindex == ifan->ifan_index) - || (ifp->ifindex == IFINDEX_INTERNAL) ); - - if ( (ifp == NULL) - || ((ifp->ifindex == IFINDEX_INTERNAL) - && (ifan->ifan_what == IFAN_ARRIVAL)) ) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: creating interface for ifindex %d, name %s", - __func__, ifan->ifan_index, ifan->ifan_name); - - /* Create Interface */ - ifp = if_get_by_name_len(ifan->ifan_name, - strnlen(ifan->ifan_name, - sizeof(ifan->ifan_name)), - VRF_DEFAULT, 0); - ifp->ifindex = ifan->ifan_index; - - if_get_metric (ifp); - if_add_update (ifp); - } - else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE) - if_delete_update (ifp); - - if_get_flags (ifp); - if_get_mtu (ifp); - if_get_metric (ifp); - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: interface %s index %d", - __func__, ifan->ifan_name, ifan->ifan_index); - - return 0; + struct interface *ifp; + + ifp = if_lookup_by_index(ifan->ifan_index, VRF_DEFAULT); + + if (ifp) + assert((ifp->ifindex == ifan->ifan_index) + || (ifp->ifindex == IFINDEX_INTERNAL)); + + if ((ifp == NULL) || ((ifp->ifindex == IFINDEX_INTERNAL) + && (ifan->ifan_what == IFAN_ARRIVAL))) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: creating interface for ifindex %d, name %s", + __func__, ifan->ifan_index, ifan->ifan_name); + + /* Create Interface */ + ifp = if_get_by_name_len( + ifan->ifan_name, + strnlen(ifan->ifan_name, sizeof(ifan->ifan_name)), + VRF_DEFAULT, 0); + ifp->ifindex = ifan->ifan_index; + + if_get_metric(ifp); + if_add_update(ifp); + } else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE) + if_delete_update(ifp); + + if_get_flags(ifp); + if_get_mtu(ifp); + if_get_metric(ifp); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: interface %s index %d", __func__, + ifan->ifan_name, ifan->ifan_index); + + return 0; } #endif /* RTM_IFANNOUNCE */ #ifdef HAVE_BSD_IFI_LINK_STATE /* BSD link detect translation */ -static void -bsd_linkdetect_translate (struct if_msghdr *ifm) +static void bsd_linkdetect_translate(struct if_msghdr *ifm) { - if ((ifm->ifm_data.ifi_link_state >= LINK_STATE_UP) || - (ifm->ifm_data.ifi_link_state == LINK_STATE_UNKNOWN)) - SET_FLAG(ifm->ifm_flags, IFF_RUNNING); - else - UNSET_FLAG(ifm->ifm_flags, IFF_RUNNING); + if ((ifm->ifm_data.ifi_link_state >= LINK_STATE_UP) + || (ifm->ifm_data.ifi_link_state == LINK_STATE_UNKNOWN)) + SET_FLAG(ifm->ifm_flags, IFF_RUNNING); + else + UNSET_FLAG(ifm->ifm_flags, IFF_RUNNING); } #endif /* HAVE_BSD_IFI_LINK_STATE */ -static enum zebra_link_type -sdl_to_zebra_link_type (unsigned int sdlt) +static enum zebra_link_type sdl_to_zebra_link_type(unsigned int sdlt) { - switch (sdlt) - { - case IFT_ETHER: return ZEBRA_LLT_ETHER; - case IFT_X25: return ZEBRA_LLT_X25; - case IFT_FDDI: return ZEBRA_LLT_FDDI; - case IFT_PPP: return ZEBRA_LLT_PPP; - case IFT_LOOP: return ZEBRA_LLT_LOOPBACK; - case IFT_SLIP: return ZEBRA_LLT_SLIP; - case IFT_ARCNET: return ZEBRA_LLT_ARCNET; - case IFT_ATM: return ZEBRA_LLT_ATM; - case IFT_LOCALTALK: return ZEBRA_LLT_LOCALTLK; - case IFT_HIPPI: return ZEBRA_LLT_HIPPI; + switch (sdlt) { + case IFT_ETHER: + return ZEBRA_LLT_ETHER; + case IFT_X25: + return ZEBRA_LLT_X25; + case IFT_FDDI: + return ZEBRA_LLT_FDDI; + case IFT_PPP: + return ZEBRA_LLT_PPP; + case IFT_LOOP: + return ZEBRA_LLT_LOOPBACK; + case IFT_SLIP: + return ZEBRA_LLT_SLIP; + case IFT_ARCNET: + return ZEBRA_LLT_ARCNET; + case IFT_ATM: + return ZEBRA_LLT_ATM; + case IFT_LOCALTALK: + return ZEBRA_LLT_LOCALTLK; + case IFT_HIPPI: + return ZEBRA_LLT_HIPPI; #ifdef IFT_IEEE1394 - case IFT_IEEE1394: return ZEBRA_LLT_IEEE1394; + case IFT_IEEE1394: + return ZEBRA_LLT_IEEE1394; #endif - default: return ZEBRA_LLT_UNKNOWN; - } + default: + return ZEBRA_LLT_UNKNOWN; + } } /* @@ -403,341 +396,338 @@ sdl_to_zebra_link_type (unsigned int sdlt) * sysctl (from interface_list). There may or may not be sockaddrs * present after the header. */ -int -ifm_read (struct if_msghdr *ifm) +int ifm_read(struct if_msghdr *ifm) { - struct interface *ifp = NULL; - struct sockaddr_dl *sdl; - char ifname[IFNAMSIZ]; - short ifnlen = 0; - caddr_t cp; - - /* terminate ifname at head (for strnlen) and tail (for safety) */ - ifname[IFNAMSIZ - 1] = '\0'; - - /* paranoia: sanity check structure */ - if (ifm->ifm_msglen < sizeof(struct if_msghdr)) - { - zlog_err ("ifm_read: ifm->ifm_msglen %d too short\n", - ifm->ifm_msglen); - return -1; - } - - /* - * Check for a sockaddr_dl following the message. First, point to - * where a socakddr might be if one follows the message. - */ - cp = (void *)(ifm + 1); + struct interface *ifp = NULL; + struct sockaddr_dl *sdl; + char ifname[IFNAMSIZ]; + short ifnlen = 0; + caddr_t cp; + + /* terminate ifname at head (for strnlen) and tail (for safety) */ + ifname[IFNAMSIZ - 1] = '\0'; + + /* paranoia: sanity check structure */ + if (ifm->ifm_msglen < sizeof(struct if_msghdr)) { + zlog_err("ifm_read: ifm->ifm_msglen %d too short\n", + ifm->ifm_msglen); + return -1; + } + + /* + * Check for a sockaddr_dl following the message. First, point to + * where a socakddr might be if one follows the message. + */ + cp = (void *)(ifm + 1); #ifdef SUNOS_5 - /* - * XXX This behavior should be narrowed to only the kernel versions - * for which the structures returned do not match the headers. - * - * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions - * is 12 bytes larger than the 32 bit version. - */ - if (((struct sockaddr *) cp)->sa_family == AF_UNSPEC) - cp = cp + 12; + /* + * XXX This behavior should be narrowed to only the kernel versions + * for which the structures returned do not match the headers. + * + * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions + * is 12 bytes larger than the 32 bit version. + */ + if (((struct sockaddr *)cp)->sa_family == AF_UNSPEC) + cp = cp + 12; #endif - RTA_ADDR_GET (NULL, RTA_DST, ifm->ifm_addrs, cp); - RTA_ADDR_GET (NULL, RTA_GATEWAY, ifm->ifm_addrs, cp); - RTA_ATTR_GET (NULL, RTA_NETMASK, ifm->ifm_addrs, cp); - RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifm_addrs, cp); - sdl = (struct sockaddr_dl *)cp; - RTA_NAME_GET (ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen); - RTA_ADDR_GET (NULL, RTA_IFA, ifm->ifm_addrs, cp); - RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifm_addrs, cp); - RTA_ADDR_GET (NULL, RTA_BRD, ifm->ifm_addrs, cp); - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: sdl ifname %s", __func__, (ifnlen ? ifname : "(nil)")); - - /* - * Look up on ifindex first, because ifindices are the primary handle for - * interfaces across the user/kernel boundary, for most systems. (Some - * messages, such as up/down status changes on NetBSD, do not include a - * sockaddr_dl). - */ - if ( (ifp = if_lookup_by_index (ifm->ifm_index, VRF_DEFAULT)) != NULL ) - { - /* we have an ifp, verify that the name matches as some systems, - * eg Solaris, have a 1:many association of ifindex:ifname - * if they dont match, we dont have the correct ifp and should - * set it back to NULL to let next check do lookup by name - */ - if (ifnlen && (strncmp (ifp->name, ifname, IFNAMSIZ) != 0) ) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: ifp name %s doesnt match sdl name %s", - __func__, ifp->name, ifname); - ifp = NULL; - } - } - - /* - * If we dont have an ifp, try looking up by name. Particularly as some - * systems (Solaris) have a 1:many mapping of ifindex:ifname - the ifname - * is therefore our unique handle to that interface. - * - * Interfaces specified in the configuration file for which the ifindex - * has not been determined will have ifindex == IFINDEX_INTERNAL, and such - * interfaces are found by this search, and then their ifindex values can - * be filled in. - */ - if ( (ifp == NULL) && ifnlen) - ifp = if_lookup_by_name (ifname, VRF_DEFAULT); - - /* - * If ifp still does not exist or has an invalid index (IFINDEX_INTERNAL), - * create or fill in an interface. - */ - if ((ifp == NULL) || (ifp->ifindex == IFINDEX_INTERNAL)) - { - /* - * To create or fill in an interface, a sockaddr_dl (via - * RTA_IFP) is required. - */ - if (!ifnlen) - { - zlog_warn ("Interface index %d (new) missing ifname\n", - ifm->ifm_index); - return -1; + RTA_ADDR_GET(NULL, RTA_DST, ifm->ifm_addrs, cp); + RTA_ADDR_GET(NULL, RTA_GATEWAY, ifm->ifm_addrs, cp); + RTA_ATTR_GET(NULL, RTA_NETMASK, ifm->ifm_addrs, cp); + RTA_ADDR_GET(NULL, RTA_GENMASK, ifm->ifm_addrs, cp); + sdl = (struct sockaddr_dl *)cp; + RTA_NAME_GET(ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen); + RTA_ADDR_GET(NULL, RTA_IFA, ifm->ifm_addrs, cp); + RTA_ADDR_GET(NULL, RTA_AUTHOR, ifm->ifm_addrs, cp); + RTA_ADDR_GET(NULL, RTA_BRD, ifm->ifm_addrs, cp); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: sdl ifname %s", __func__, + (ifnlen ? ifname : "(nil)")); + + /* + * Look up on ifindex first, because ifindices are the primary handle + * for + * interfaces across the user/kernel boundary, for most systems. (Some + * messages, such as up/down status changes on NetBSD, do not include a + * sockaddr_dl). + */ + if ((ifp = if_lookup_by_index(ifm->ifm_index, VRF_DEFAULT)) != NULL) { + /* we have an ifp, verify that the name matches as some systems, + * eg Solaris, have a 1:many association of ifindex:ifname + * if they dont match, we dont have the correct ifp and should + * set it back to NULL to let next check do lookup by name + */ + if (ifnlen && (strncmp(ifp->name, ifname, IFNAMSIZ) != 0)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: ifp name %s doesnt match sdl name %s", + __func__, ifp->name, ifname); + ifp = NULL; + } } + /* + * If we dont have an ifp, try looking up by name. Particularly as some + * systems (Solaris) have a 1:many mapping of ifindex:ifname - the + * ifname + * is therefore our unique handle to that interface. + * + * Interfaces specified in the configuration file for which the ifindex + * has not been determined will have ifindex == IFINDEX_INTERNAL, and + * such + * interfaces are found by this search, and then their ifindex values + * can + * be filled in. + */ + if ((ifp == NULL) && ifnlen) + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); + + /* + * If ifp still does not exist or has an invalid index + * (IFINDEX_INTERNAL), + * create or fill in an interface. + */ + if ((ifp == NULL) || (ifp->ifindex == IFINDEX_INTERNAL)) { + /* + * To create or fill in an interface, a sockaddr_dl (via + * RTA_IFP) is required. + */ + if (!ifnlen) { + zlog_warn("Interface index %d (new) missing ifname\n", + ifm->ifm_index); + return -1; + } + #ifndef RTM_IFANNOUNCE - /* Down->Down interface should be ignored here. - * See further comment below. - */ - if (!CHECK_FLAG (ifm->ifm_flags, IFF_UP)) - return 0; + /* Down->Down interface should be ignored here. + * See further comment below. + */ + if (!CHECK_FLAG(ifm->ifm_flags, IFF_UP)) + return 0; #endif /* !RTM_IFANNOUNCE */ - - if (ifp == NULL) - { - /* Interface that zebra was not previously aware of, so create. */ - ifp = if_create (ifname, ifnlen, VRF_DEFAULT); - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: creating ifp for ifindex %d", - __func__, ifm->ifm_index); - } - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: updated/created ifp, ifname %s, ifindex %d", - __func__, ifp->name, ifp->ifindex); - /* - * Fill in newly created interface structure, or larval - * structure with ifindex IFINDEX_INTERNAL. - */ - ifp->ifindex = ifm->ifm_index; - + + if (ifp == NULL) { + /* Interface that zebra was not previously aware of, so + * create. */ + ifp = if_create(ifname, ifnlen, VRF_DEFAULT); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: creating ifp for ifindex %d", + __func__, ifm->ifm_index); + } + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: updated/created ifp, ifname %s, ifindex %d", + __func__, ifp->name, ifp->ifindex); + /* + * Fill in newly created interface structure, or larval + * structure with ifindex IFINDEX_INTERNAL. + */ + ifp->ifindex = ifm->ifm_index; + #ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */ - bsd_linkdetect_translate(ifm); + bsd_linkdetect_translate(ifm); #endif /* HAVE_BSD_IFI_LINK_STATE */ - if_flags_update (ifp, ifm->ifm_flags); + if_flags_update(ifp, ifm->ifm_flags); #if defined(__bsdi__) - if_kvm_get_mtu (ifp); + if_kvm_get_mtu(ifp); #else - if_get_mtu (ifp); + if_get_mtu(ifp); #endif /* __bsdi__ */ - if_get_metric (ifp); - - /* - * XXX sockaddr_dl contents can be larger than the structure - * definition. There are 2 big families here: - * - BSD has sdl_len + sdl_data[16] + overruns sdl_data - * we MUST use sdl_len here or we'll truncate data. - * - Solaris has no sdl_len, but sdl_data[244] - * presumably, it's not going to run past that, so sizeof() - * is fine here. - * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid - */ - ifp->ll_type = ZEBRA_LLT_UNKNOWN; - ifp->hw_addr_len = 0; - if (ifnlen) - { + if_get_metric(ifp); + + /* + * XXX sockaddr_dl contents can be larger than the structure + * definition. There are 2 big families here: + * - BSD has sdl_len + sdl_data[16] + overruns sdl_data + * we MUST use sdl_len here or we'll truncate data. + * - Solaris has no sdl_len, but sdl_data[244] + * presumably, it's not going to run past that, so sizeof() + * is fine here. + * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid + */ + ifp->ll_type = ZEBRA_LLT_UNKNOWN; + ifp->hw_addr_len = 0; + if (ifnlen) { #ifdef HAVE_STRUCT_SOCKADDR_DL_SDL_LEN - memcpy (&((struct zebra_if *)ifp->info)->sdl, sdl, sdl->sdl_len); + memcpy(&((struct zebra_if *)ifp->info)->sdl, sdl, + sdl->sdl_len); #else - memcpy (&((struct zebra_if *)ifp->info)->sdl, sdl, sizeof (struct sockaddr_dl)); + memcpy(&((struct zebra_if *)ifp->info)->sdl, sdl, + sizeof(struct sockaddr_dl)); #endif /* HAVE_STRUCT_SOCKADDR_DL_SDL_LEN */ - ifp->ll_type = sdl_to_zebra_link_type (sdl->sdl_type); - if (sdl->sdl_alen <= sizeof(ifp->hw_addr)) - { - memcpy (ifp->hw_addr, LLADDR(sdl), sdl->sdl_alen); - ifp->hw_addr_len = sdl->sdl_alen; - } - } - - if_add_update (ifp); - } - else - /* - * Interface structure exists. Adjust stored flags from - * notification. If interface has up->down or down->up - * transition, call state change routines (to adjust routes, - * notify routing daemons, etc.). (Other flag changes are stored - * but apparently do not trigger action.) - */ - { - if (ifp->ifindex != ifm->ifm_index) - { - zlog_warn ("%s: index mismatch, ifname %s, ifp index %d, " - "ifm index %d", - __func__, ifp->name, ifp->ifindex, ifm->ifm_index); - return -1; - } - + ifp->ll_type = sdl_to_zebra_link_type(sdl->sdl_type); + if (sdl->sdl_alen <= sizeof(ifp->hw_addr)) { + memcpy(ifp->hw_addr, LLADDR(sdl), + sdl->sdl_alen); + ifp->hw_addr_len = sdl->sdl_alen; + } + } + + if_add_update(ifp); + } else + /* + * Interface structure exists. Adjust stored flags from + * notification. If interface has up->down or down->up + * transition, call state change routines (to adjust routes, + * notify routing daemons, etc.). (Other flag changes are stored + * but apparently do not trigger action.) + */ + { + if (ifp->ifindex != ifm->ifm_index) { + zlog_warn( + "%s: index mismatch, ifname %s, ifp index %d, " + "ifm index %d", + __func__, ifp->name, ifp->ifindex, + ifm->ifm_index); + return -1; + } + #ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */ - bsd_linkdetect_translate(ifm); + bsd_linkdetect_translate(ifm); #endif /* HAVE_BSD_IFI_LINK_STATE */ - /* update flags and handle operative->inoperative transition, if any */ - if_flags_update (ifp, ifm->ifm_flags); - + /* update flags and handle operative->inoperative transition, if + * any */ + if_flags_update(ifp, ifm->ifm_flags); + #ifndef RTM_IFANNOUNCE - if (!if_is_up (ifp)) - { - /* No RTM_IFANNOUNCE on this platform, so we can never - * distinguish between ~IFF_UP and delete. We must presume - * it has been deleted. - * Eg, Solaris will not notify us of unplumb. - * - * XXX: Fixme - this should be runtime detected - * So that a binary compiled on a system with IFANNOUNCE - * will still behave correctly if run on a platform without - */ - if_delete_update (ifp); - } + if (!if_is_up(ifp)) { + /* No RTM_IFANNOUNCE on this platform, so we can never + * distinguish between ~IFF_UP and delete. We must + * presume + * it has been deleted. + * Eg, Solaris will not notify us of unplumb. + * + * XXX: Fixme - this should be runtime detected + * So that a binary compiled on a system with IFANNOUNCE + * will still behave correctly if run on a platform + * without + */ + if_delete_update(ifp); + } #endif /* RTM_IFANNOUNCE */ - if (if_is_up (ifp)) - { + if (if_is_up(ifp)) { #if defined(__bsdi__) - if_kvm_get_mtu (ifp); + if_kvm_get_mtu(ifp); #else - if_get_mtu (ifp); + if_get_mtu(ifp); #endif /* __bsdi__ */ - if_get_metric (ifp); - } - } + if_get_metric(ifp); + } + } #ifdef HAVE_NET_RT_IFLIST - ifp->stats = ifm->ifm_data; + ifp->stats = ifm->ifm_data; #endif /* HAVE_NET_RT_IFLIST */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: interface %s index %d", - __func__, ifp->name, ifp->ifindex); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: interface %s index %d", __func__, ifp->name, + ifp->ifindex); - return 0; + return 0; } /* Address read from struct ifa_msghdr. */ -static void -ifam_read_mesg (struct ifa_msghdr *ifm, - union sockunion *addr, - union sockunion *mask, - union sockunion *brd, - char *ifname, - short *ifnlen) +static void ifam_read_mesg(struct ifa_msghdr *ifm, union sockunion *addr, + union sockunion *mask, union sockunion *brd, + char *ifname, short *ifnlen) { - caddr_t pnt, end; - union sockunion dst; - union sockunion gateway; - - pnt = (caddr_t)(ifm + 1); - end = ((caddr_t)ifm) + ifm->ifam_msglen; - - /* Be sure structure is cleared */ - memset (mask, 0, sizeof (union sockunion)); - memset (addr, 0, sizeof (union sockunion)); - memset (brd, 0, sizeof (union sockunion)); - memset (&dst, 0, sizeof (union sockunion)); - memset (&gateway, 0, sizeof (union sockunion)); - - /* We fetch each socket variable into sockunion. */ - RTA_ADDR_GET (&dst, RTA_DST, ifm->ifam_addrs, pnt); - RTA_ADDR_GET (&gateway, RTA_GATEWAY, ifm->ifam_addrs, pnt); - RTA_ATTR_GET (mask, RTA_NETMASK, ifm->ifam_addrs, pnt); - RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifam_addrs, pnt); - RTA_NAME_GET (ifname, RTA_IFP, ifm->ifam_addrs, pnt, *ifnlen); - RTA_ADDR_GET (addr, RTA_IFA, ifm->ifam_addrs, pnt); - RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt); - RTA_ADDR_GET (brd, RTA_BRD, ifm->ifam_addrs, pnt); - - if (IS_ZEBRA_DEBUG_KERNEL) - { - int family = sockunion_family(addr); - switch (family) - { - case AF_INET: - case AF_INET6: - { - char buf[4][INET6_ADDRSTRLEN]; - zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x, " - "ifam_flags 0x%x, addr %s/%d broad %s dst %s " - "gateway %s", - __func__, ifm->ifam_index, - (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs, - ifm->ifam_flags, - inet_ntop(family,&addr->sin.sin_addr, - buf[0],sizeof(buf[0])), - ip_masklen(mask->sin.sin_addr), - inet_ntop(family,&brd->sin.sin_addr, - buf[1],sizeof(buf[1])), - inet_ntop(family,&dst.sin.sin_addr, - buf[2],sizeof(buf[2])), - inet_ntop(family,&gateway.sin.sin_addr, - buf[3],sizeof(buf[3]))); - } - break; - default: - zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x", - __func__, ifm->ifam_index, - (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs); - break; - } - } - - /* Assert read up end point matches to end point */ - if (pnt != end) - zlog_warn ("ifam_read() doesn't read all socket data"); + caddr_t pnt, end; + union sockunion dst; + union sockunion gateway; + + pnt = (caddr_t)(ifm + 1); + end = ((caddr_t)ifm) + ifm->ifam_msglen; + + /* Be sure structure is cleared */ + memset(mask, 0, sizeof(union sockunion)); + memset(addr, 0, sizeof(union sockunion)); + memset(brd, 0, sizeof(union sockunion)); + memset(&dst, 0, sizeof(union sockunion)); + memset(&gateway, 0, sizeof(union sockunion)); + + /* We fetch each socket variable into sockunion. */ + RTA_ADDR_GET(&dst, RTA_DST, ifm->ifam_addrs, pnt); + RTA_ADDR_GET(&gateway, RTA_GATEWAY, ifm->ifam_addrs, pnt); + RTA_ATTR_GET(mask, RTA_NETMASK, ifm->ifam_addrs, pnt); + RTA_ADDR_GET(NULL, RTA_GENMASK, ifm->ifam_addrs, pnt); + RTA_NAME_GET(ifname, RTA_IFP, ifm->ifam_addrs, pnt, *ifnlen); + RTA_ADDR_GET(addr, RTA_IFA, ifm->ifam_addrs, pnt); + RTA_ADDR_GET(NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt); + RTA_ADDR_GET(brd, RTA_BRD, ifm->ifam_addrs, pnt); + + if (IS_ZEBRA_DEBUG_KERNEL) { + int family = sockunion_family(addr); + switch (family) { + case AF_INET: + case AF_INET6: { + char buf[4][INET6_ADDRSTRLEN]; + zlog_debug( + "%s: ifindex %d, ifname %s, ifam_addrs 0x%x, " + "ifam_flags 0x%x, addr %s/%d broad %s dst %s " + "gateway %s", + __func__, ifm->ifam_index, + (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs, + ifm->ifam_flags, + inet_ntop(family, &addr->sin.sin_addr, buf[0], + sizeof(buf[0])), + ip_masklen(mask->sin.sin_addr), + inet_ntop(family, &brd->sin.sin_addr, buf[1], + sizeof(buf[1])), + inet_ntop(family, &dst.sin.sin_addr, buf[2], + sizeof(buf[2])), + inet_ntop(family, &gateway.sin.sin_addr, buf[3], + sizeof(buf[3]))); + } break; + default: + zlog_debug("%s: ifindex %d, ifname %s, ifam_addrs 0x%x", + __func__, ifm->ifam_index, + (ifnlen ? ifname : "(nil)"), + ifm->ifam_addrs); + break; + } + } + + /* Assert read up end point matches to end point */ + if (pnt != end) + zlog_warn("ifam_read() doesn't read all socket data"); } /* Interface's address information get. */ -int -ifam_read (struct ifa_msghdr *ifam) +int ifam_read(struct ifa_msghdr *ifam) { - struct interface *ifp = NULL; - union sockunion addr, mask, brd; - char ifname[INTERFACE_NAMSIZ]; - short ifnlen = 0; - char isalias = 0; - int flags = 0; - - ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0'; - - /* Allocate and read address information. */ - ifam_read_mesg (ifam, &addr, &mask, &brd, ifname, &ifnlen); - - if ((ifp = if_lookup_by_index(ifam->ifam_index, VRF_DEFAULT)) == NULL) - { - zlog_warn ("%s: no interface for ifname %s, index %d", - __func__, ifname, ifam->ifam_index); - return -1; - } - - if (ifnlen && strncmp (ifp->name, ifname, INTERFACE_NAMSIZ)) - isalias = 1; - - /* N.B. The info in ifa_msghdr does not tell us whether the RTA_BRD - field contains a broadcast address or a peer address, so we are forced to - rely upon the interface type. */ - if (if_is_pointopoint(ifp)) - SET_FLAG(flags, ZEBRA_IFA_PEER); + struct interface *ifp = NULL; + union sockunion addr, mask, brd; + char ifname[INTERFACE_NAMSIZ]; + short ifnlen = 0; + char isalias = 0; + int flags = 0; + + ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0'; + + /* Allocate and read address information. */ + ifam_read_mesg(ifam, &addr, &mask, &brd, ifname, &ifnlen); + + if ((ifp = if_lookup_by_index(ifam->ifam_index, VRF_DEFAULT)) == NULL) { + zlog_warn("%s: no interface for ifname %s, index %d", __func__, + ifname, ifam->ifam_index); + return -1; + } + + if (ifnlen && strncmp(ifp->name, ifname, INTERFACE_NAMSIZ)) + isalias = 1; + + /* N.B. The info in ifa_msghdr does not tell us whether the RTA_BRD + field contains a broadcast address or a peer address, so we are + forced to + rely upon the interface type. */ + if (if_is_pointopoint(ifp)) + SET_FLAG(flags, ZEBRA_IFA_PEER); #if 0 /* it might seem cute to grab the interface metric here, however @@ -748,450 +738,477 @@ ifam_read (struct ifa_msghdr *ifam) ifp->metric = ifam->ifam_metric; #endif - /* Add connected address. */ - switch (sockunion_family (&addr)) - { - case AF_INET: - if (ifam->ifam_type == RTM_NEWADDR) - connected_add_ipv4 (ifp, flags, &addr.sin.sin_addr, - ip_masklen (mask.sin.sin_addr), - &brd.sin.sin_addr, - (isalias ? ifname : NULL)); - else - connected_delete_ipv4 (ifp, flags, &addr.sin.sin_addr, - ip_masklen (mask.sin.sin_addr), - &brd.sin.sin_addr); - break; - case AF_INET6: - /* Unset interface index from link-local address when IPv6 stack - is KAME. */ - if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr)) - { - SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0); - } - - if (ifam->ifam_type == RTM_NEWADDR) - connected_add_ipv6 (ifp, flags, &addr.sin6.sin6_addr, - ip6_masklen (mask.sin6.sin6_addr), - &brd.sin6.sin6_addr, - (isalias ? ifname : NULL)); - else - connected_delete_ipv6 (ifp, - &addr.sin6.sin6_addr, - ip6_masklen (mask.sin6.sin6_addr), - &brd.sin6.sin6_addr); - break; - default: - /* Unsupported family silently ignore... */ - break; - } - - /* Check interface flag for implicit up of the interface. */ - if_refresh (ifp); + /* Add connected address. */ + switch (sockunion_family(&addr)) { + case AF_INET: + if (ifam->ifam_type == RTM_NEWADDR) + connected_add_ipv4(ifp, flags, &addr.sin.sin_addr, + ip_masklen(mask.sin.sin_addr), + &brd.sin.sin_addr, + (isalias ? ifname : NULL)); + else + connected_delete_ipv4(ifp, flags, &addr.sin.sin_addr, + ip_masklen(mask.sin.sin_addr), + &brd.sin.sin_addr); + break; + case AF_INET6: + /* Unset interface index from link-local address when IPv6 stack + is KAME. */ + if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6.sin6_addr)) { + SET_IN6_LINKLOCAL_IFINDEX(addr.sin6.sin6_addr, 0); + } + + if (ifam->ifam_type == RTM_NEWADDR) + connected_add_ipv6(ifp, flags, &addr.sin6.sin6_addr, + ip6_masklen(mask.sin6.sin6_addr), + &brd.sin6.sin6_addr, + (isalias ? ifname : NULL)); + else + connected_delete_ipv6(ifp, &addr.sin6.sin6_addr, + ip6_masklen(mask.sin6.sin6_addr), + &brd.sin6.sin6_addr); + break; + default: + /* Unsupported family silently ignore... */ + break; + } + + /* Check interface flag for implicit up of the interface. */ + if_refresh(ifp); #ifdef SUNOS_5 - /* In addition to lacking IFANNOUNCE, on SUNOS IFF_UP is strange. - * See comments for SUNOS_5 in interface.c::if_flags_mangle. - * - * Here we take care of case where the real IFF_UP was previously - * unset (as kept in struct zebra_if.primary_state) and the mangled - * IFF_UP (ie IFF_UP set || listcount(connected) has now transitioned - * to unset due to the lost non-primary address having DELADDR'd. - * - * we must delete the interface, because in between here and next - * event for this interface-name the administrator could unplumb - * and replumb the interface. - */ - if (!if_is_up (ifp)) - if_delete_update (ifp); + /* In addition to lacking IFANNOUNCE, on SUNOS IFF_UP is strange. + * See comments for SUNOS_5 in interface.c::if_flags_mangle. + * + * Here we take care of case where the real IFF_UP was previously + * unset (as kept in struct zebra_if.primary_state) and the mangled + * IFF_UP (ie IFF_UP set || listcount(connected) has now transitioned + * to unset due to the lost non-primary address having DELADDR'd. + * + * we must delete the interface, because in between here and next + * event for this interface-name the administrator could unplumb + * and replumb the interface. + */ + if (!if_is_up(ifp)) + if_delete_update(ifp); #endif /* SUNOS_5 */ - - return 0; + + return 0; } /* Interface function for reading kernel routing table information. */ -static int -rtm_read_mesg (struct rt_msghdr *rtm, - union sockunion *dest, - union sockunion *mask, - union sockunion *gate, - char *ifname, - short *ifnlen) +static int rtm_read_mesg(struct rt_msghdr *rtm, union sockunion *dest, + union sockunion *mask, union sockunion *gate, + char *ifname, short *ifnlen) { - caddr_t pnt, end; - - /* Pnt points out socket data start point. */ - pnt = (caddr_t)(rtm + 1); - end = ((caddr_t)rtm) + rtm->rtm_msglen; - - /* rt_msghdr version check. */ - if (rtm->rtm_version != RTM_VERSION) - zlog_warn("Routing message version different %d should be %d." "This may cause problem\n", - rtm->rtm_version, RTM_VERSION); - - /* Be sure structure is cleared */ - memset (dest, 0, sizeof (union sockunion)); - memset (gate, 0, sizeof (union sockunion)); - memset (mask, 0, sizeof (union sockunion)); - - /* We fetch each socket variable into sockunion. */ - RTA_ADDR_GET (dest, RTA_DST, rtm->rtm_addrs, pnt); - RTA_ADDR_GET (gate, RTA_GATEWAY, rtm->rtm_addrs, pnt); - RTA_ATTR_GET (mask, RTA_NETMASK, rtm->rtm_addrs, pnt); - RTA_ADDR_GET (NULL, RTA_GENMASK, rtm->rtm_addrs, pnt); - RTA_NAME_GET (ifname, RTA_IFP, rtm->rtm_addrs, pnt, *ifnlen); - RTA_ADDR_GET (NULL, RTA_IFA, rtm->rtm_addrs, pnt); - RTA_ADDR_GET (NULL, RTA_AUTHOR, rtm->rtm_addrs, pnt); - RTA_ADDR_GET (NULL, RTA_BRD, rtm->rtm_addrs, pnt); - - /* If there is netmask information set it's family same as - destination family*/ - if (rtm->rtm_addrs & RTA_NETMASK) - mask->sa.sa_family = dest->sa.sa_family; - - /* Assert read up to the end of pointer. */ - if (pnt != end) - zlog_warn("rtm_read() doesn't read all socket data."); - - return rtm->rtm_flags; + caddr_t pnt, end; + + /* Pnt points out socket data start point. */ + pnt = (caddr_t)(rtm + 1); + end = ((caddr_t)rtm) + rtm->rtm_msglen; + + /* rt_msghdr version check. */ + if (rtm->rtm_version != RTM_VERSION) + zlog_warn( + "Routing message version different %d should be %d." + "This may cause problem\n", + rtm->rtm_version, RTM_VERSION); + + /* Be sure structure is cleared */ + memset(dest, 0, sizeof(union sockunion)); + memset(gate, 0, sizeof(union sockunion)); + memset(mask, 0, sizeof(union sockunion)); + + /* We fetch each socket variable into sockunion. */ + RTA_ADDR_GET(dest, RTA_DST, rtm->rtm_addrs, pnt); + RTA_ADDR_GET(gate, RTA_GATEWAY, rtm->rtm_addrs, pnt); + RTA_ATTR_GET(mask, RTA_NETMASK, rtm->rtm_addrs, pnt); + RTA_ADDR_GET(NULL, RTA_GENMASK, rtm->rtm_addrs, pnt); + RTA_NAME_GET(ifname, RTA_IFP, rtm->rtm_addrs, pnt, *ifnlen); + RTA_ADDR_GET(NULL, RTA_IFA, rtm->rtm_addrs, pnt); + RTA_ADDR_GET(NULL, RTA_AUTHOR, rtm->rtm_addrs, pnt); + RTA_ADDR_GET(NULL, RTA_BRD, rtm->rtm_addrs, pnt); + + /* If there is netmask information set it's family same as + destination family*/ + if (rtm->rtm_addrs & RTA_NETMASK) + mask->sa.sa_family = dest->sa.sa_family; + + /* Assert read up to the end of pointer. */ + if (pnt != end) + zlog_warn("rtm_read() doesn't read all socket data."); + + return rtm->rtm_flags; } -void -rtm_read (struct rt_msghdr *rtm) +void rtm_read(struct rt_msghdr *rtm) { - int flags; - u_char zebra_flags; - union sockunion dest, mask, gate; - char ifname[INTERFACE_NAMSIZ + 1]; - short ifnlen = 0; - - zebra_flags = 0; - - /* Read destination and netmask and gateway from rtm message - structure. */ - flags = rtm_read_mesg (rtm, &dest, &mask, &gate, ifname, &ifnlen); - if (!(flags & RTF_DONE)) - return; - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: got rtm of type %d (%s)", __func__, rtm->rtm_type, - lookup_msg(rtm_type_str, rtm->rtm_type, NULL)); - -#ifdef RTF_CLONED /*bsdi, netbsd 1.6*/ - if (flags & RTF_CLONED) - return; + int flags; + u_char zebra_flags; + union sockunion dest, mask, gate; + char ifname[INTERFACE_NAMSIZ + 1]; + short ifnlen = 0; + + zebra_flags = 0; + + /* Read destination and netmask and gateway from rtm message + structure. */ + flags = rtm_read_mesg(rtm, &dest, &mask, &gate, ifname, &ifnlen); + if (!(flags & RTF_DONE)) + return; + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: got rtm of type %d (%s)", __func__, + rtm->rtm_type, + lookup_msg(rtm_type_str, rtm->rtm_type, NULL)); + +#ifdef RTF_CLONED /*bsdi, netbsd 1.6*/ + if (flags & RTF_CLONED) + return; #endif -#ifdef RTF_WASCLONED /*freebsd*/ - if (flags & RTF_WASCLONED) - return; +#ifdef RTF_WASCLONED /*freebsd*/ + if (flags & RTF_WASCLONED) + return; #endif - if ((rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) && ! (flags & RTF_UP)) - return; - - /* This is connected route. */ - if (! (flags & RTF_GATEWAY)) - return; - - if (flags & RTF_PROTO1) - SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE); - - /* This is persistent route. */ - if (flags & RTF_STATIC) - SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC); - - /* This is a reject or blackhole route */ - if (flags & RTF_REJECT) - SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT); - if (flags & RTF_BLACKHOLE) - SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE); - - if (dest.sa.sa_family == AF_INET) - { - struct prefix p; - - p.family = AF_INET; - p.u.prefix4 = dest.sin.sin_addr; - if (flags & RTF_HOST) - p.prefixlen = IPV4_MAX_PREFIXLEN; - else - p.prefixlen = ip_masklen (mask.sin.sin_addr); - - /* Catch self originated messages and match them against our current RIB. - * At the same time, ignore unconfirmed messages, they should be tracked - * by rtm_write() and kernel_rtm_ipv4(). - */ - if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) - { - char buf[PREFIX_STRLEN], gate_buf[INET_ADDRSTRLEN]; - int ret; - if (! IS_ZEBRA_DEBUG_RIB) - return; - ret = rib_lookup_ipv4_route ((struct prefix_ipv4 *)&p, &gate, VRF_DEFAULT); - prefix2str (&p, buf, sizeof(buf)); - switch (rtm->rtm_type) - { - case RTM_ADD: - case RTM_GET: - case RTM_CHANGE: - /* The kernel notifies us about a new route in FIB created by us. - Do we have a correspondent entry in our RIB? */ - switch (ret) - { - case ZEBRA_RIB_NOTFOUND: - zlog_debug ("%s: %s %s: desync: RR isn't yet in RIB, while already in FIB", - __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf); - break; - case ZEBRA_RIB_FOUND_CONNECTED: - case ZEBRA_RIB_FOUND_NOGATE: - inet_ntop (AF_INET, &gate.sin.sin_addr, gate_buf, INET_ADDRSTRLEN); - zlog_debug ("%s: %s %s: desync: RR is in RIB, but gate differs (ours is %s)", - __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf, gate_buf); - break; - case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR */ - zlog_debug ("%s: %s %s: done Ok", - __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf); - rib_lookup_and_dump ((struct prefix_ipv4 *)&p, VRF_DEFAULT); - return; - break; - } - break; - case RTM_DELETE: - /* The kernel notifies us about a route deleted by us. Do we still - have it in the RIB? Do we have anything instead? */ - switch (ret) - { - case ZEBRA_RIB_FOUND_EXACT: - zlog_debug ("%s: %s %s: desync: RR is still in RIB, while already not in FIB", - __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf); - rib_lookup_and_dump ((struct prefix_ipv4 *)&p, VRF_DEFAULT); - break; - case ZEBRA_RIB_FOUND_CONNECTED: - case ZEBRA_RIB_FOUND_NOGATE: - zlog_debug ("%s: %s %s: desync: RR is still in RIB, plus gate differs", - __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf); - rib_lookup_and_dump ((struct prefix_ipv4 *)&p, VRF_DEFAULT); - break; - case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */ - zlog_debug ("%s: %s %s: done Ok", - __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf); - rib_lookup_and_dump ((struct prefix_ipv4 *)&p, VRF_DEFAULT); - return; - break; - } - break; - default: - zlog_debug ("%s: %s: warning: loopback RTM of type %s received", - __func__, buf, lookup_msg(rtm_type_str, rtm->rtm_type, NULL)); - } - return; - } - - /* Change, delete the old prefix, we have no further information - * to specify the route really - */ - if (rtm->rtm_type == RTM_CHANGE) - rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, NULL, 0, 0); - - union g_addr ggate = { .ipv4 = gate.sin.sin_addr }; - if (rtm->rtm_type == RTM_GET - || rtm->rtm_type == RTM_ADD - || rtm->rtm_type == RTM_CHANGE) - rib_add (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, NULL, &ggate, NULL, 0, 0, 0, 0, 0); - else - rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, &ggate, 0, 0); - } - if (dest.sa.sa_family == AF_INET6) - { - /* One day we might have a debug section here like one in the - * IPv4 case above. Just ignore own messages at the moment. - */ - if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) - return; - struct prefix p; - ifindex_t ifindex = 0; - - p.family = AF_INET6; - p.u.prefix6 = dest.sin6.sin6_addr; - if (flags & RTF_HOST) - p.prefixlen = IPV6_MAX_PREFIXLEN; - else - p.prefixlen = ip6_masklen (mask.sin6.sin6_addr); + if ((rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) + && !(flags & RTF_UP)) + return; + + /* This is connected route. */ + if (!(flags & RTF_GATEWAY)) + return; + + if (flags & RTF_PROTO1) + SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE); + + /* This is persistent route. */ + if (flags & RTF_STATIC) + SET_FLAG(zebra_flags, ZEBRA_FLAG_STATIC); + + /* This is a reject or blackhole route */ + if (flags & RTF_REJECT) + SET_FLAG(zebra_flags, ZEBRA_FLAG_REJECT); + if (flags & RTF_BLACKHOLE) + SET_FLAG(zebra_flags, ZEBRA_FLAG_BLACKHOLE); + + if (dest.sa.sa_family == AF_INET) { + struct prefix p; + + p.family = AF_INET; + p.u.prefix4 = dest.sin.sin_addr; + if (flags & RTF_HOST) + p.prefixlen = IPV4_MAX_PREFIXLEN; + else + p.prefixlen = ip_masklen(mask.sin.sin_addr); + + /* Catch self originated messages and match them against our + * current RIB. + * At the same time, ignore unconfirmed messages, they should be + * tracked + * by rtm_write() and kernel_rtm_ipv4(). + */ + if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) { + char buf[PREFIX_STRLEN], gate_buf[INET_ADDRSTRLEN]; + int ret; + if (!IS_ZEBRA_DEBUG_RIB) + return; + ret = rib_lookup_ipv4_route((struct prefix_ipv4 *)&p, + &gate, VRF_DEFAULT); + prefix2str(&p, buf, sizeof(buf)); + switch (rtm->rtm_type) { + case RTM_ADD: + case RTM_GET: + case RTM_CHANGE: + /* The kernel notifies us about a new route in + FIB created by us. + Do we have a correspondent entry in our RIB? + */ + switch (ret) { + case ZEBRA_RIB_NOTFOUND: + zlog_debug( + "%s: %s %s: desync: RR isn't yet in RIB, while already in FIB", + __func__, + lookup_msg(rtm_type_str, + rtm->rtm_type, NULL), + buf); + break; + case ZEBRA_RIB_FOUND_CONNECTED: + case ZEBRA_RIB_FOUND_NOGATE: + inet_ntop(AF_INET, &gate.sin.sin_addr, + gate_buf, INET_ADDRSTRLEN); + zlog_debug( + "%s: %s %s: desync: RR is in RIB, but gate differs (ours is %s)", + __func__, + lookup_msg(rtm_type_str, + rtm->rtm_type, NULL), + buf, gate_buf); + break; + case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR + */ + zlog_debug( + "%s: %s %s: done Ok", __func__, + lookup_msg(rtm_type_str, + rtm->rtm_type, NULL), + buf); + rib_lookup_and_dump( + (struct prefix_ipv4 *)&p, + VRF_DEFAULT); + return; + break; + } + break; + case RTM_DELETE: + /* The kernel notifies us about a route deleted + by us. Do we still + have it in the RIB? Do we have anything + instead? */ + switch (ret) { + case ZEBRA_RIB_FOUND_EXACT: + zlog_debug( + "%s: %s %s: desync: RR is still in RIB, while already not in FIB", + __func__, + lookup_msg(rtm_type_str, + rtm->rtm_type, NULL), + buf); + rib_lookup_and_dump( + (struct prefix_ipv4 *)&p, + VRF_DEFAULT); + break; + case ZEBRA_RIB_FOUND_CONNECTED: + case ZEBRA_RIB_FOUND_NOGATE: + zlog_debug( + "%s: %s %s: desync: RR is still in RIB, plus gate differs", + __func__, + lookup_msg(rtm_type_str, + rtm->rtm_type, NULL), + buf); + rib_lookup_and_dump( + (struct prefix_ipv4 *)&p, + VRF_DEFAULT); + break; + case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */ + zlog_debug( + "%s: %s %s: done Ok", __func__, + lookup_msg(rtm_type_str, + rtm->rtm_type, NULL), + buf); + rib_lookup_and_dump( + (struct prefix_ipv4 *)&p, + VRF_DEFAULT); + return; + break; + } + break; + default: + zlog_debug( + "%s: %s: warning: loopback RTM of type %s received", + __func__, buf, + lookup_msg(rtm_type_str, rtm->rtm_type, + NULL)); + } + return; + } + + /* Change, delete the old prefix, we have no further information + * to specify the route really + */ + if (rtm->rtm_type == RTM_CHANGE) + rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, + ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, + NULL, 0, 0); + + union g_addr ggate = {.ipv4 = gate.sin.sin_addr}; + if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD + || rtm->rtm_type == RTM_CHANGE) + rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, + ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, + &ggate, NULL, 0, 0, 0, 0, 0); + else + rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, + ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, + &ggate, 0, 0); + } + if (dest.sa.sa_family == AF_INET6) { + /* One day we might have a debug section here like one in the + * IPv4 case above. Just ignore own messages at the moment. + */ + if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) + return; + struct prefix p; + ifindex_t ifindex = 0; + + p.family = AF_INET6; + p.u.prefix6 = dest.sin6.sin6_addr; + if (flags & RTF_HOST) + p.prefixlen = IPV6_MAX_PREFIXLEN; + else + p.prefixlen = ip6_masklen(mask.sin6.sin6_addr); #ifdef KAME - if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr)) - { - ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr); - SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0); - } + if (IN6_IS_ADDR_LINKLOCAL(&gate.sin6.sin6_addr)) { + ifindex = IN6_LINKLOCAL_IFINDEX(gate.sin6.sin6_addr); + SET_IN6_LINKLOCAL_IFINDEX(gate.sin6.sin6_addr, 0); + } #endif /* KAME */ - /* CHANGE: delete the old prefix, we have no further information - * to specify the route really - */ - if (rtm->rtm_type == RTM_CHANGE) - rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, NULL, 0, 0); - - union g_addr ggate = { .ipv6 = gate.sin6.sin6_addr }; - if (rtm->rtm_type == RTM_GET - || rtm->rtm_type == RTM_ADD - || rtm->rtm_type == RTM_CHANGE) - rib_add (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, &ggate, NULL, ifindex, - 0, 0, 0, 0); - else - rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, &ggate, ifindex, 0); - } + /* CHANGE: delete the old prefix, we have no further information + * to specify the route really + */ + if (rtm->rtm_type == RTM_CHANGE) + rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, + ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, + NULL, 0, 0); + + union g_addr ggate = {.ipv6 = gate.sin6.sin6_addr}; + if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD + || rtm->rtm_type == RTM_CHANGE) + rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, + ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, + &ggate, NULL, ifindex, 0, 0, 0, 0); + else + rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, + ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, + &ggate, ifindex, 0); + } } /* Interface function for the kernel routing table updates. Support * for RTM_CHANGE will be needed. * Exported only for rt_socket.c */ -int -rtm_write (int message, - union sockunion *dest, - union sockunion *mask, - union sockunion *gate, - union sockunion *mpls, - unsigned int index, - int zebra_flags, - int metric) +int rtm_write(int message, union sockunion *dest, union sockunion *mask, + union sockunion *gate, union sockunion *mpls, unsigned int index, + int zebra_flags, int metric) { - int ret; - caddr_t pnt; - struct interface *ifp; - - /* Sequencial number of routing message. */ - static int msg_seq = 0; - - /* Struct of rt_msghdr and buffer for storing socket's data. */ - struct - { - struct rt_msghdr rtm; - char buf[512]; - } msg; - - if (routing_sock < 0) - return ZEBRA_ERR_EPERM; - - /* Clear and set rt_msghdr values */ - memset (&msg, 0, sizeof (struct rt_msghdr)); - msg.rtm.rtm_version = RTM_VERSION; - msg.rtm.rtm_type = message; - msg.rtm.rtm_seq = msg_seq++; - msg.rtm.rtm_addrs = RTA_DST; - msg.rtm.rtm_addrs |= RTA_GATEWAY; - msg.rtm.rtm_flags = RTF_UP; + int ret; + caddr_t pnt; + struct interface *ifp; + + /* Sequencial number of routing message. */ + static int msg_seq = 0; + + /* Struct of rt_msghdr and buffer for storing socket's data. */ + struct { + struct rt_msghdr rtm; + char buf[512]; + } msg; + + if (routing_sock < 0) + return ZEBRA_ERR_EPERM; + + /* Clear and set rt_msghdr values */ + memset(&msg, 0, sizeof(struct rt_msghdr)); + msg.rtm.rtm_version = RTM_VERSION; + msg.rtm.rtm_type = message; + msg.rtm.rtm_seq = msg_seq++; + msg.rtm.rtm_addrs = RTA_DST; + msg.rtm.rtm_addrs |= RTA_GATEWAY; + msg.rtm.rtm_flags = RTF_UP; #ifdef __OpenBSD__ - msg.rtm.rtm_flags |= RTF_MPATH; - msg.rtm.rtm_fmask = RTF_MPLS; + msg.rtm.rtm_flags |= RTF_MPATH; + msg.rtm.rtm_fmask = RTF_MPLS; #endif - msg.rtm.rtm_index = index; + msg.rtm.rtm_index = index; - if (metric != 0) - { - msg.rtm.rtm_rmx.rmx_hopcount = metric; - msg.rtm.rtm_inits |= RTV_HOPCOUNT; - } + if (metric != 0) { + msg.rtm.rtm_rmx.rmx_hopcount = metric; + msg.rtm.rtm_inits |= RTV_HOPCOUNT; + } - ifp = if_lookup_by_index (index, VRF_DEFAULT); + ifp = if_lookup_by_index(index, VRF_DEFAULT); - if (gate && (message == RTM_ADD || message == RTM_CHANGE)) - msg.rtm.rtm_flags |= RTF_GATEWAY; + if (gate && (message == RTM_ADD || message == RTM_CHANGE)) + msg.rtm.rtm_flags |= RTF_GATEWAY; - /* When RTF_CLONING is unavailable on BSD, should we set some - * other flag instead? - */ +/* When RTF_CLONING is unavailable on BSD, should we set some + * other flag instead? + */ #ifdef RTF_CLONING - if (! gate && (message == RTM_ADD || message == RTM_CHANGE) && ifp && - (ifp->flags & IFF_POINTOPOINT) == 0) - msg.rtm.rtm_flags |= RTF_CLONING; + if (!gate && (message == RTM_ADD || message == RTM_CHANGE) && ifp + && (ifp->flags & IFF_POINTOPOINT) == 0) + msg.rtm.rtm_flags |= RTF_CLONING; #endif /* RTF_CLONING */ - /* If no protocol specific gateway is specified, use link - address for gateway. */ - if (! gate) - { - if (!ifp) - { - char dest_buf[INET_ADDRSTRLEN] = "NULL", mask_buf[INET_ADDRSTRLEN] = "255.255.255.255"; - if (dest) - inet_ntop (AF_INET, &dest->sin.sin_addr, dest_buf, INET_ADDRSTRLEN); - if (mask) - inet_ntop (AF_INET, &mask->sin.sin_addr, mask_buf, INET_ADDRSTRLEN); - zlog_warn ("%s: %s/%s: gate == NULL and no gateway found for ifindex %d", - __func__, dest_buf, mask_buf, index); - return -1; - } - gate = (union sockunion *) &((struct zebra_if *)ifp->info)->sdl; - } - - if (mask) - msg.rtm.rtm_addrs |= RTA_NETMASK; - else if (message == RTM_ADD || message == RTM_CHANGE) - msg.rtm.rtm_flags |= RTF_HOST; + /* If no protocol specific gateway is specified, use link + address for gateway. */ + if (!gate) { + if (!ifp) { + char dest_buf[INET_ADDRSTRLEN] = "NULL", + mask_buf[INET_ADDRSTRLEN] = "255.255.255.255"; + if (dest) + inet_ntop(AF_INET, &dest->sin.sin_addr, + dest_buf, INET_ADDRSTRLEN); + if (mask) + inet_ntop(AF_INET, &mask->sin.sin_addr, + mask_buf, INET_ADDRSTRLEN); + zlog_warn( + "%s: %s/%s: gate == NULL and no gateway found for ifindex %d", + __func__, dest_buf, mask_buf, index); + return -1; + } + gate = (union sockunion *)&((struct zebra_if *)ifp->info)->sdl; + } + + if (mask) + msg.rtm.rtm_addrs |= RTA_NETMASK; + else if (message == RTM_ADD || message == RTM_CHANGE) + msg.rtm.rtm_flags |= RTF_HOST; #ifdef __OpenBSD__ - if (mpls) - { - msg.rtm.rtm_addrs |= RTA_SRC; - msg.rtm.rtm_flags |= RTF_MPLS; - - if (mpls->smpls.smpls_label != htonl (MPLS_IMP_NULL_LABEL << MPLS_LABEL_OFFSET)) - msg.rtm.rtm_mpls = MPLS_OP_PUSH; - } + if (mpls) { + msg.rtm.rtm_addrs |= RTA_SRC; + msg.rtm.rtm_flags |= RTF_MPLS; + + if (mpls->smpls.smpls_label + != htonl(MPLS_IMP_NULL_LABEL << MPLS_LABEL_OFFSET)) + msg.rtm.rtm_mpls = MPLS_OP_PUSH; + } #endif - /* Tagging route with flags */ - msg.rtm.rtm_flags |= (RTF_PROTO1); + /* Tagging route with flags */ + msg.rtm.rtm_flags |= (RTF_PROTO1); - /* Additional flags. */ - if (zebra_flags & ZEBRA_FLAG_BLACKHOLE) - msg.rtm.rtm_flags |= RTF_BLACKHOLE; - if (zebra_flags & ZEBRA_FLAG_REJECT) - msg.rtm.rtm_flags |= RTF_REJECT; + /* Additional flags. */ + if (zebra_flags & ZEBRA_FLAG_BLACKHOLE) + msg.rtm.rtm_flags |= RTF_BLACKHOLE; + if (zebra_flags & ZEBRA_FLAG_REJECT) + msg.rtm.rtm_flags |= RTF_REJECT; -#define SOCKADDRSET(X,R) \ - if (msg.rtm.rtm_addrs & (R)) \ - { \ - int len = SAROUNDUP (X); \ - memcpy (pnt, (caddr_t)(X), len); \ - pnt += len; \ - } +#define SOCKADDRSET(X, R) \ + if (msg.rtm.rtm_addrs & (R)) { \ + int len = SAROUNDUP(X); \ + memcpy(pnt, (caddr_t)(X), len); \ + pnt += len; \ + } - pnt = (caddr_t) msg.buf; + pnt = (caddr_t)msg.buf; - /* Write each socket data into rtm message buffer */ - SOCKADDRSET (dest, RTA_DST); - SOCKADDRSET (gate, RTA_GATEWAY); - SOCKADDRSET (mask, RTA_NETMASK); + /* Write each socket data into rtm message buffer */ + SOCKADDRSET(dest, RTA_DST); + SOCKADDRSET(gate, RTA_GATEWAY); + SOCKADDRSET(mask, RTA_NETMASK); #ifdef __OpenBSD__ - SOCKADDRSET (mpls, RTA_SRC); + SOCKADDRSET(mpls, RTA_SRC); #endif - msg.rtm.rtm_msglen = pnt - (caddr_t) &msg; - - ret = write (routing_sock, &msg, msg.rtm.rtm_msglen); - - if (ret != msg.rtm.rtm_msglen) - { - if (errno == EEXIST) - return ZEBRA_ERR_RTEXIST; - if (errno == ENETUNREACH) - return ZEBRA_ERR_RTUNREACH; - if (errno == ESRCH) - return ZEBRA_ERR_RTNOEXIST; - - zlog_warn ("%s: write : %s (%d)", __func__, safe_strerror (errno), errno); - return ZEBRA_ERR_KERNEL; - } - return ZEBRA_ERR_NOERROR; + msg.rtm.rtm_msglen = pnt - (caddr_t)&msg; + + ret = write(routing_sock, &msg, msg.rtm.rtm_msglen); + + if (ret != msg.rtm.rtm_msglen) { + if (errno == EEXIST) + return ZEBRA_ERR_RTEXIST; + if (errno == ENETUNREACH) + return ZEBRA_ERR_RTUNREACH; + if (errno == ESRCH) + return ZEBRA_ERR_RTNOEXIST; + + zlog_warn("%s: write : %s (%d)", __func__, safe_strerror(errno), + errno); + return ZEBRA_ERR_KERNEL; + } + return ZEBRA_ERR_NOERROR; } @@ -1199,14 +1216,14 @@ rtm_write (int message, #include "zebra/zserv.h" /* For debug purpose. */ -static void -rtmsg_debug (struct rt_msghdr *rtm) +static void rtmsg_debug(struct rt_msghdr *rtm) { - zlog_debug ("Kernel: Len: %d Type: %s", rtm->rtm_msglen, lookup_msg(rtm_type_str, rtm->rtm_type, NULL)); - rtm_flag_dump (rtm->rtm_flags); - zlog_debug ("Kernel: message seq %d", rtm->rtm_seq); - zlog_debug ("Kernel: pid %lld, rtm_addrs 0x%x", - (long long)rtm->rtm_pid, rtm->rtm_addrs); + zlog_debug("Kernel: Len: %d Type: %s", rtm->rtm_msglen, + lookup_msg(rtm_type_str, rtm->rtm_type, NULL)); + rtm_flag_dump(rtm->rtm_flags); + zlog_debug("Kernel: message seq %d", rtm->rtm_seq); + zlog_debug("Kernel: pid %lld, rtm_addrs 0x%x", (long long)rtm->rtm_pid, + rtm->rtm_addrs); } /* This is pretty gross, better suggestions welcome -- mhandler */ @@ -1219,154 +1236,143 @@ rtmsg_debug (struct rt_msghdr *rtm) #endif /* RTAX_MAX */ /* Kernel routing table and interface updates via routing socket. */ -static int -kernel_read (struct thread *thread) +static int kernel_read(struct thread *thread) { - int sock; - int nbytes; - struct rt_msghdr *rtm; - - /* - * This must be big enough for any message the kernel might send. - * Rather than determining how many sockaddrs of what size might be - * in each particular message, just use RTAX_MAX of sockaddr_storage - * for each. Note that the sockaddrs must be after each message - * definition, or rather after whichever happens to be the largest, - * since the buffer needs to be big enough for a message and the - * sockaddrs together. - */ - union - { - /* Routing information. */ - struct - { - struct rt_msghdr rtm; - struct sockaddr_storage addr[RTAX_MAX]; - } r; - - /* Interface information. */ - struct - { - struct if_msghdr ifm; - struct sockaddr_storage addr[RTAX_MAX]; - } im; - - /* Interface address information. */ - struct - { - struct ifa_msghdr ifa; - struct sockaddr_storage addr[RTAX_MAX]; - } ia; + int sock; + int nbytes; + struct rt_msghdr *rtm; + + /* + * This must be big enough for any message the kernel might send. + * Rather than determining how many sockaddrs of what size might be + * in each particular message, just use RTAX_MAX of sockaddr_storage + * for each. Note that the sockaddrs must be after each message + * definition, or rather after whichever happens to be the largest, + * since the buffer needs to be big enough for a message and the + * sockaddrs together. + */ + union { + /* Routing information. */ + struct { + struct rt_msghdr rtm; + struct sockaddr_storage addr[RTAX_MAX]; + } r; + + /* Interface information. */ + struct { + struct if_msghdr ifm; + struct sockaddr_storage addr[RTAX_MAX]; + } im; + + /* Interface address information. */ + struct { + struct ifa_msghdr ifa; + struct sockaddr_storage addr[RTAX_MAX]; + } ia; #ifdef RTM_IFANNOUNCE - /* Interface arrival/departure */ - struct - { - struct if_announcemsghdr ifan; - struct sockaddr_storage addr[RTAX_MAX]; - } ian; + /* Interface arrival/departure */ + struct { + struct if_announcemsghdr ifan; + struct sockaddr_storage addr[RTAX_MAX]; + } ian; #endif /* RTM_IFANNOUNCE */ - } buf; + } buf; - /* Fetch routing socket. */ - sock = THREAD_FD (thread); + /* Fetch routing socket. */ + sock = THREAD_FD(thread); - nbytes= read (sock, &buf, sizeof buf); + nbytes = read(sock, &buf, sizeof buf); - if (nbytes <= 0) - { - if (nbytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN) - zlog_warn ("routing socket error: %s", safe_strerror (errno)); - return 0; - } + if (nbytes <= 0) { + if (nbytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN) + zlog_warn("routing socket error: %s", + safe_strerror(errno)); + return 0; + } - thread_add_read(zebrad.master, kernel_read, NULL, sock, NULL); + thread_add_read(zebrad.master, kernel_read, NULL, sock, NULL); - if (IS_ZEBRA_DEBUG_KERNEL) - rtmsg_debug (&buf.r.rtm); + if (IS_ZEBRA_DEBUG_KERNEL) + rtmsg_debug(&buf.r.rtm); - rtm = &buf.r.rtm; + rtm = &buf.r.rtm; - /* - * Ensure that we didn't drop any data, so that processing routines - * can assume they have the whole message. - */ - if (rtm->rtm_msglen != nbytes) - { - zlog_warn ("kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d\n", - rtm->rtm_msglen, nbytes, rtm->rtm_type); - return -1; - } - - switch (rtm->rtm_type) - { - case RTM_ADD: - case RTM_DELETE: - case RTM_CHANGE: - rtm_read (rtm); - break; - case RTM_IFINFO: - ifm_read (&buf.im.ifm); - break; - case RTM_NEWADDR: - case RTM_DELADDR: - ifam_read (&buf.ia.ifa); - break; + /* + * Ensure that we didn't drop any data, so that processing routines + * can assume they have the whole message. + */ + if (rtm->rtm_msglen != nbytes) { + zlog_warn( + "kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d\n", + rtm->rtm_msglen, nbytes, rtm->rtm_type); + return -1; + } + + switch (rtm->rtm_type) { + case RTM_ADD: + case RTM_DELETE: + case RTM_CHANGE: + rtm_read(rtm); + break; + case RTM_IFINFO: + ifm_read(&buf.im.ifm); + break; + case RTM_NEWADDR: + case RTM_DELADDR: + ifam_read(&buf.ia.ifa); + break; #ifdef RTM_IFANNOUNCE - case RTM_IFANNOUNCE: - ifan_read (&buf.ian.ifan); - break; + case RTM_IFANNOUNCE: + ifan_read(&buf.ian.ifan); + break; #endif /* RTM_IFANNOUNCE */ - default: - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("Unprocessed RTM_type: %d", rtm->rtm_type); - break; - } - return 0; + default: + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Unprocessed RTM_type: %d", rtm->rtm_type); + break; + } + return 0; } /* Make routing socket. */ -static void -routing_socket (struct zebra_ns *zns) +static void routing_socket(struct zebra_ns *zns) { - if ( zserv_privs.change (ZPRIVS_RAISE) ) - zlog_err ("routing_socket: Can't raise privileges"); - - routing_sock = socket (AF_ROUTE, SOCK_RAW, 0); - - if (routing_sock < 0) - { - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("routing_socket: Can't lower privileges"); - zlog_warn ("Can't init kernel routing socket"); - return; - } - - /* XXX: Socket should be NONBLOCK, however as we currently - * discard failed writes, this will lead to inconsistencies. - * For now, socket must be blocking. - */ - /*if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0) - zlog_warn ("Can't set O_NONBLOCK to routing socket");*/ - - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("routing_socket: Can't lower privileges"); - - /* kernel_read needs rewrite. */ - thread_add_read(zebrad.master, kernel_read, NULL, routing_sock, NULL); + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("routing_socket: Can't raise privileges"); + + routing_sock = socket(AF_ROUTE, SOCK_RAW, 0); + + if (routing_sock < 0) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("routing_socket: Can't lower privileges"); + zlog_warn("Can't init kernel routing socket"); + return; + } + + /* XXX: Socket should be NONBLOCK, however as we currently + * discard failed writes, this will lead to inconsistencies. + * For now, socket must be blocking. + */ + /*if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0) + zlog_warn ("Can't set O_NONBLOCK to routing socket");*/ + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("routing_socket: Can't lower privileges"); + + /* kernel_read needs rewrite. */ + thread_add_read(zebrad.master, kernel_read, NULL, routing_sock, NULL); } /* Exported interface function. This function simply calls routing_socket (). */ -void -kernel_init (struct zebra_ns *zns) +void kernel_init(struct zebra_ns *zns) { - routing_socket (zns); + routing_socket(zns); } -void -kernel_terminate (struct zebra_ns *zns) +void kernel_terminate(struct zebra_ns *zns) { - return; + return; } diff --git a/zebra/kernel_socket.h b/zebra/kernel_socket.h index 26cd6127f..41b322185 100644 --- a/zebra/kernel_socket.h +++ b/zebra/kernel_socket.h @@ -30,12 +30,12 @@ #define ZEBRA_ERR_RTNOEXIST -4 #define ZEBRA_ERR_KERNEL -5 -extern void rtm_read (struct rt_msghdr *); -extern int ifam_read (struct ifa_msghdr *); -extern int ifm_read (struct if_msghdr *); -extern int rtm_write (int, union sockunion *, union sockunion *, - union sockunion *, union sockunion *, - unsigned int, int, int); +extern void rtm_read(struct rt_msghdr *); +extern int ifam_read(struct ifa_msghdr *); +extern int ifm_read(struct if_msghdr *); +extern int rtm_write(int, union sockunion *, union sockunion *, + union sockunion *, union sockunion *, unsigned int, int, + int); extern const struct message rtm_type_str[]; #endif /* __ZEBRA_KERNEL_SOCKET_H */ diff --git a/zebra/label_manager.c b/zebra/label_manager.c index fbe4cea46..b50f75158 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -71,14 +71,14 @@ static int relay_response_back(struct zserv *zserv) stream_reset(src); ret = zclient_read_header(src, zclient->sock, &size, &marker, &version, - &vrf_id, &resp_cmd); + &vrf_id, &resp_cmd); if (ret < 0 && errno != EAGAIN) { - zlog_err("%s: Error reading Label Manager response: %s", __func__, - strerror(errno)); + zlog_err("%s: Error reading Label Manager response: %s", + __func__, strerror(errno)); return -1; } zlog_debug("%s: Label Manager response received, %d bytes", __func__, - size); + size); if (size == 0) return -1; @@ -87,11 +87,11 @@ static int relay_response_back(struct zserv *zserv) ret = writen(zserv->sock, dst->data, stream_get_endp(dst)); if (ret <= 0) { zlog_err("%s: Error sending Label Manager response back: %s", - __func__, strerror(errno)); + __func__, strerror(errno)); return -1; } zlog_debug("%s: Label Manager response (%d bytes) sent back", __func__, - ret); + ret); return 0; } @@ -111,23 +111,22 @@ static int lm_zclient_read(struct thread *t) return ret; } -static int reply_error (int cmd, struct zserv *zserv, vrf_id_t vrf_id) +static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id) { struct stream *s; s = zserv->obuf; - stream_reset (s); + stream_reset(s); - zserv_create_header (s, cmd, vrf_id); + zserv_create_header(s, cmd, vrf_id); /* result */ - stream_putc (s, 1); + stream_putc(s, 1); /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); - - return writen (zserv->sock, s->data, stream_get_endp (s)); + stream_putw_at(s, 0, stream_get_endp(s)); + return writen(zserv->sock, s->data, stream_get_endp(s)); } /** * Receive a request to get or release a label chunk and forward it to external @@ -140,15 +139,17 @@ static int reply_error (int cmd, struct zserv *zserv, vrf_id_t vrf_id) * @param zserv * @return 0 on success, -1 otherwise */ -int zread_relay_label_manager_request(int cmd, struct zserv *zserv, vrf_id_t vrf_id) +int zread_relay_label_manager_request(int cmd, struct zserv *zserv, + vrf_id_t vrf_id) { struct stream *src, *dst; int ret = 0; if (zclient->sock < 0) { - zlog_err("%s: Error relaying label chunk request: no zclient socket", - __func__); - reply_error (cmd, zserv, vrf_id); + zlog_err( + "%s: Error relaying label chunk request: no zclient socket", + __func__); + reply_error(cmd, zserv, vrf_id); return -1; } @@ -166,7 +167,7 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv, vrf_id_t vrf if (ret <= 0) { zlog_err("%s: Error relaying label chunk request: %s", __func__, strerror(errno)); - reply_error (cmd, zserv, vrf_id); + reply_error(cmd, zserv, vrf_id); return -1; } zlog_debug("%s: Label chunk request relayed. %d bytes sent", __func__, @@ -179,7 +180,7 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv, vrf_id_t vrf /* make sure we listen to the response */ if (!zclient->t_read) thread_add_read(zclient->master, lm_zclient_read, zserv, - zclient->sock, &zclient->t_read); + zclient->sock, &zclient->t_read); return 0; } @@ -200,7 +201,8 @@ static int lm_zclient_connect(struct thread *t) /* make socket non-blocking */ if (set_nonblocking(zclient->sock) < 0) - zlog_warn("%s: set_nonblocking(%d) failed", __func__, zclient->sock); + zlog_warn("%s: set_nonblocking(%d) failed", __func__, + zclient->sock); return 0; } @@ -234,7 +236,7 @@ void label_manager_init(char *lm_zserv_path) lm_is_external = false; lbl_mgr.lc_list = list_new(); lbl_mgr.lc_list->del = delete_label_chunk; - } else { /* it's acting just as a proxy */ + } else { /* it's acting just as a proxy */ zlog_debug("Initializing external label manager at %s", lm_zserv_path); lm_is_external = true; @@ -262,7 +264,8 @@ struct label_manager_chunk *assign_label_chunk(u_char proto, u_short instance, /* first check if there's one available */ for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) { - if (lmc->proto == NO_PROTO && lmc->end - lmc->start + 1 == size) { + if (lmc->proto == NO_PROTO + && lmc->end - lmc->start + 1 == size) { lmc->proto = proto; lmc->instance = instance; lmc->keep = keep; @@ -277,12 +280,14 @@ struct label_manager_chunk *assign_label_chunk(u_char proto, u_short instance, if (list_isempty(lbl_mgr.lc_list)) lmc->start = MPLS_MIN_UNRESERVED_LABEL; else - lmc->start = ((struct label_manager_chunk *) - listgetdata(listtail(lbl_mgr.lc_list)))->end + 1; + lmc->start = ((struct label_manager_chunk *)listgetdata( + listtail(lbl_mgr.lc_list))) + ->end + + 1; if (lmc->start > MPLS_MAX_UNRESERVED_LABEL - size + 1) { zlog_err("Reached max labels. Start: %u, size: %u", lmc->start, size); - XFREE(MTYPE_LM_CHUNK, lmc); + XFREE(MTYPE_LM_CHUNK, lmc); return NULL; } lmc->end = lmc->start + size - 1; @@ -303,9 +308,8 @@ struct label_manager_chunk *assign_label_chunk(u_char proto, u_short instance, * @param end Last label of the chunk * @return 0 on success, -1 otherwise */ -int -release_label_chunk(u_char proto, u_short instance, uint32_t start, - uint32_t end) +int release_label_chunk(u_char proto, u_short instance, uint32_t start, + uint32_t end) { struct listnode *node; struct label_manager_chunk *lmc; @@ -355,9 +359,8 @@ int release_daemon_chunks(u_char proto, u_short instance) for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) { if (lmc->proto == proto && lmc->instance == instance && lmc->keep == 0) { - ret = - release_label_chunk(lmc->proto, lmc->instance, - lmc->start, lmc->end); + ret = release_label_chunk(lmc->proto, lmc->instance, + lmc->start, lmc->end); if (ret == 0) count++; } diff --git a/zebra/label_manager.h b/zebra/label_manager.h index b7d6118a0..875698362 100644 --- a/zebra/label_manager.h +++ b/zebra/label_manager.h @@ -47,8 +47,8 @@ struct label_manager_chunk { u_char proto; u_short instance; u_char keep; - uint32_t start; /* First label of the chunk */ - uint32_t end; /* Last label of the chunk */ + uint32_t start; /* First label of the chunk */ + uint32_t end; /* Last label of the chunk */ }; /* @@ -61,7 +61,8 @@ struct label_manager { bool lm_is_external; -int zread_relay_label_manager_request(int cmd, struct zserv *zserv, vrf_id_t vrf_id); +int zread_relay_label_manager_request(int cmd, struct zserv *zserv, + vrf_id_t vrf_id); void label_manager_init(char *lm_zserv_path); struct label_manager_chunk *assign_label_chunk(u_char proto, u_short instance, u_char keep, uint32_t size); @@ -70,4 +71,4 @@ int release_label_chunk(u_char proto, u_short instance, uint32_t start, int release_daemon_chunks(u_char proto, u_short instance); void label_manager_close(void); -#endif /* _LABEL_MANAGER_H */ +#endif /* _LABEL_MANAGER_H */ diff --git a/zebra/main.c b/zebra/main.c index b136f8ae9..27a6f3e02 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -51,9 +51,8 @@ #define ZEBRA_PTM_SUPPORT /* Zebra instance */ -struct zebra_t zebrad = -{ - .rtm_table_default = 0, +struct zebra_t zebrad = { + .rtm_table_default = 0, }; /* process id. */ @@ -77,283 +76,271 @@ u_int32_t nl_rcvbufsize = 4194304; #endif /* HAVE_NETLINK */ /* Command line options. */ -struct option longopts[] = -{ - { "batch", no_argument, NULL, 'b'}, - { "allow_delete", no_argument, NULL, 'a'}, - { "keep_kernel", no_argument, NULL, 'k'}, - { "socket", required_argument, NULL, 'z'}, - { "ecmp", required_argument, NULL, 'e'}, - { "label_socket", no_argument, NULL, 'l'}, - { "retain", no_argument, NULL, 'r'}, +struct option longopts[] = {{"batch", no_argument, NULL, 'b'}, + {"allow_delete", no_argument, NULL, 'a'}, + {"keep_kernel", no_argument, NULL, 'k'}, + {"socket", required_argument, NULL, 'z'}, + {"ecmp", required_argument, NULL, 'e'}, + {"label_socket", no_argument, NULL, 'l'}, + {"retain", no_argument, NULL, 'r'}, #ifdef HAVE_NETLINK - { "nl-bufsize", required_argument, NULL, 's'}, + {"nl-bufsize", required_argument, NULL, 's'}, #endif /* HAVE_NETLINK */ - { 0 } -}; + {0}}; -zebra_capabilities_t _caps_p [] = -{ - ZCAP_NET_ADMIN, - ZCAP_SYS_ADMIN, - ZCAP_NET_RAW, +zebra_capabilities_t _caps_p[] = { + ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN, ZCAP_NET_RAW, }; /* zebra privileges to run with */ -struct zebra_privs_t zserv_privs = -{ +struct zebra_privs_t zserv_privs = { #if defined(FRR_USER) && defined(FRR_GROUP) - .user = FRR_USER, - .group = FRR_GROUP, + .user = FRR_USER, + .group = FRR_GROUP, #endif #ifdef VTY_GROUP - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = array_size(_caps_p), - .cap_num_i = 0 -}; + .caps_p = _caps_p, + .cap_num_p = array_size(_caps_p), + .cap_num_i = 0}; unsigned int multipath_num = MULTIPATH_NUM; /* SIGHUP handler. */ -static void -sighup (void) +static void sighup(void) { - zlog_info ("SIGHUP received"); + zlog_info("SIGHUP received"); - /* Reload of config file. */ - ; + /* Reload of config file. */ + ; } /* SIGINT handler. */ -static void -sigint (void) +static void sigint(void) { - struct vrf *vrf; - struct zebra_vrf *zvrf; - struct zebra_ns *zns; + struct vrf *vrf; + struct zebra_vrf *zvrf; + struct zebra_ns *zns; - zlog_notice ("Terminating on signal"); + zlog_notice("Terminating on signal"); #ifdef HAVE_IRDP - irdp_finish(); + irdp_finish(); #endif - zebra_ptm_finish(); - list_delete_all_node (zebrad.client_list); - - if (retain_mode) - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - zvrf = vrf->info; - if (zvrf) - SET_FLAG (zvrf->flags, ZEBRA_VRF_RETAIN); - } - vrf_terminate (); - - zns = zebra_ns_lookup (NS_DEFAULT); - zebra_ns_disable (0, (void **)&zns); - - access_list_reset (); - prefix_list_reset (); - route_map_finish (); - cmd_terminate (); - vty_terminate (); - zprivs_terminate (&zserv_privs); - list_delete (zebrad.client_list); - work_queue_free (zebrad.ribq); - if (zebrad.lsp_process_q) - work_queue_free (zebrad.lsp_process_q); - meta_queue_free (zebrad.mq); - thread_master_free (zebrad.master); - closezlog (); - - exit (0); + zebra_ptm_finish(); + list_delete_all_node(zebrad.client_list); + + if (retain_mode) + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + zvrf = vrf->info; + if (zvrf) + SET_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN); + } + vrf_terminate(); + + zns = zebra_ns_lookup(NS_DEFAULT); + zebra_ns_disable(0, (void **)&zns); + + access_list_reset(); + prefix_list_reset(); + route_map_finish(); + cmd_terminate(); + vty_terminate(); + zprivs_terminate(&zserv_privs); + list_delete(zebrad.client_list); + work_queue_free(zebrad.ribq); + if (zebrad.lsp_process_q) + work_queue_free(zebrad.lsp_process_q); + meta_queue_free(zebrad.mq); + thread_master_free(zebrad.master); + closezlog(); + + exit(0); } /* SIGUSR1 handler. */ -static void -sigusr1 (void) +static void sigusr1(void) { - zlog_rotate(); + zlog_rotate(); } -struct quagga_signal_t zebra_signals[] = -{ - { - .signal = SIGHUP, - .handler = &sighup, - }, - { - .signal = SIGUSR1, - .handler = &sigusr1, - }, - { - .signal = SIGINT, - .handler = &sigint, - }, - { - .signal = SIGTERM, - .handler = &sigint, - }, +struct quagga_signal_t zebra_signals[] = { + { + .signal = SIGHUP, + .handler = &sighup, + }, + { + .signal = SIGUSR1, + .handler = &sigusr1, + }, + { + .signal = SIGINT, + .handler = &sigint, + }, + { + .signal = SIGTERM, + .handler = &sigint, + }, }; -FRR_DAEMON_INFO(zebra, ZEBRA, - .vty_port = ZEBRA_VTY_PORT, - .flags = FRR_NO_ZCLIENT, +FRR_DAEMON_INFO( + zebra, ZEBRA, .vty_port = ZEBRA_VTY_PORT, .flags = FRR_NO_ZCLIENT, - .proghelp = "Daemon which manages kernel routing table management " + .proghelp = + "Daemon which manages kernel routing table management " "and\nredistribution between different routing protocols.", - .signals = zebra_signals, - .n_signals = array_size(zebra_signals), + .signals = zebra_signals, .n_signals = array_size(zebra_signals), - .privs = &zserv_privs, -) + .privs = &zserv_privs, ) /* Main startup routine. */ -int -main (int argc, char **argv) +int main(int argc, char **argv) { - // int batch_mode = 0; - char *zserv_path = NULL; - /* Socket to external label manager */ - char *lblmgr_path = NULL; + // int batch_mode = 0; + char *zserv_path = NULL; + /* Socket to external label manager */ + char *lblmgr_path = NULL; - frr_preinit(&zebra_di, argc, argv); + frr_preinit(&zebra_di, argc, argv); - frr_opt_add("bakz:e:l:r" + frr_opt_add( + "bakz:e:l:r" #ifdef HAVE_NETLINK - "s:" + "s:" #endif - , longopts, - " -b, --batch Runs in batch mode\n" - " -a, --allow_delete Allow other processes to delete zebra routes\n" - " -z, --socket Set path of zebra socket\n" - " -e, --ecmp Specify ECMP to use.\n" - " -l, --label_socket Socket to external label manager\n"\ - " -k, --keep_kernel Don't delete old routes which installed by zebra.\n" - " -r, --retain When program terminates, retain added route by zebra.\n" + , + longopts, + " -b, --batch Runs in batch mode\n" + " -a, --allow_delete Allow other processes to delete zebra routes\n" + " -z, --socket Set path of zebra socket\n" + " -e, --ecmp Specify ECMP to use.\n" + " -l, --label_socket Socket to external label manager\n" + " -k, --keep_kernel Don't delete old routes which installed by zebra.\n" + " -r, --retain When program terminates, retain added route by zebra.\n" #ifdef HAVE_NETLINK - " -s, --nl-bufsize Set netlink receive buffer size\n" + " -s, --nl-bufsize Set netlink receive buffer size\n" #endif /* HAVE_NETLINK */ - ); - - while (1) - { - int opt = frr_getopt(argc, argv, NULL); - - if (opt == EOF) - break; - - switch (opt) - { - case 0: - break; - case 'b': - // batch_mode = 1; - break; - case 'a': - allow_delete = 1; - break; - case 'k': - keep_kernel_mode = 1; - break; - case 'e': - multipath_num = atoi (optarg); - if (multipath_num > MULTIPATH_NUM || multipath_num <= 0) - { - zlog_err ("Multipath Number specified must be less than %d and greater than 0", MULTIPATH_NUM); - return 1; - } - break; - case 'z': - zserv_path = optarg; - break; - case 'l': - lblmgr_path = optarg; - break; - case 'r': - retain_mode = 1; - break; + ); + + while (1) { + int opt = frr_getopt(argc, argv, NULL); + + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + case 'b': + // batch_mode = 1; + break; + case 'a': + allow_delete = 1; + break; + case 'k': + keep_kernel_mode = 1; + break; + case 'e': + multipath_num = atoi(optarg); + if (multipath_num > MULTIPATH_NUM + || multipath_num <= 0) { + zlog_err( + "Multipath Number specified must be less than %d and greater than 0", + MULTIPATH_NUM); + return 1; + } + break; + case 'z': + zserv_path = optarg; + break; + case 'l': + lblmgr_path = optarg; + break; + case 'r': + retain_mode = 1; + break; #ifdef HAVE_NETLINK - case 's': - nl_rcvbufsize = atoi (optarg); - break; + case 's': + nl_rcvbufsize = atoi(optarg); + break; #endif /* HAVE_NETLINK */ - default: - frr_help_exit (1); - break; + default: + frr_help_exit(1); + break; + } } - } - - vty_config_lockless (); - zebrad.master = frr_init(); - - /* Zebra related initialize. */ - zebra_init (); - rib_init (); - zebra_if_init (); - zebra_debug_init (); - router_id_cmd_init (); - zebra_vty_init (); - access_list_init (); - prefix_list_init (); -#if defined (HAVE_RTADV) - rtadv_cmd_init (); + + vty_config_lockless(); + zebrad.master = frr_init(); + + /* Zebra related initialize. */ + zebra_init(); + rib_init(); + zebra_if_init(); + zebra_debug_init(); + router_id_cmd_init(); + zebra_vty_init(); + access_list_init(); + prefix_list_init(); +#if defined(HAVE_RTADV) + rtadv_cmd_init(); #endif #ifdef HAVE_IRDP - irdp_init(); + irdp_init(); #endif - /* PTM socket */ +/* PTM socket */ #ifdef ZEBRA_PTM_SUPPORT - zebra_ptm_init(); + zebra_ptm_init(); #endif - zebra_mpls_init (); - zebra_mpls_vty_init (); + zebra_mpls_init(); + zebra_mpls_vty_init(); - /* For debug purpose. */ - /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */ + /* For debug purpose. */ + /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */ - /* Initialize NS( and implicitly the VRF module), and make kernel routing socket. */ - zebra_ns_init (); + /* Initialize NS( and implicitly the VRF module), and make kernel + * routing socket. */ + zebra_ns_init(); - /* Process the configuration file. Among other configuration - * directives we can meet those installing static routes. Such - * requests will not be executed immediately, but queued in - * zebra->ribq structure until we enter the main execution loop. - * The notifications from kernel will show originating PID equal - * to that after daemon() completes (if ever called). - */ - frr_config_fork(); + /* Process the configuration file. Among other configuration + * directives we can meet those installing static routes. Such + * requests will not be executed immediately, but queued in + * zebra->ribq structure until we enter the main execution loop. + * The notifications from kernel will show originating PID equal + * to that after daemon() completes (if ever called). + */ + frr_config_fork(); - /* Clean up rib -- before fork (?) */ - /* rib_weed_tables (); */ + /* Clean up rib -- before fork (?) */ + /* rib_weed_tables (); */ - /* After we have successfully acquired the pidfile, we can be sure - * about being the only copy of zebra process, which is submitting - * changes to the FIB. - * Clean up zebra-originated routes. The requests will be sent to OS - * immediately, so originating PID in notifications from kernel - * will be equal to the current getpid(). To know about such routes, - * we have to have route_read() called before. - */ - if (! keep_kernel_mode) - rib_sweep_route (); + /* After we have successfully acquired the pidfile, we can be sure + * about being the only copy of zebra process, which is submitting + * changes to the FIB. + * Clean up zebra-originated routes. The requests will be sent to OS + * immediately, so originating PID in notifications from kernel + * will be equal to the current getpid(). To know about such routes, + * we have to have route_read() called before. + */ + if (!keep_kernel_mode) + rib_sweep_route(); - /* Needed for BSD routing socket. */ - pid = getpid (); + /* Needed for BSD routing socket. */ + pid = getpid(); - /* This must be done only after locking pidfile (bug #403). */ - zebra_zserv_socket_init (zserv_path); + /* This must be done only after locking pidfile (bug #403). */ + zebra_zserv_socket_init(zserv_path); - /* Init label manager */ - label_manager_init (lblmgr_path); + /* Init label manager */ + label_manager_init(lblmgr_path); - frr_run (zebrad.master); + frr_run(zebrad.master); - /* Not reached... */ - return 0; + /* Not reached... */ + return 0; } diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 97616a2a9..c3bbf40b3 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -49,722 +49,715 @@ static int zebra_import_table_used[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; static u_int32_t zebra_import_table_distance[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; -int -is_zebra_import_table_enabled(afi_t afi, u_int32_t table_id) +int is_zebra_import_table_enabled(afi_t afi, u_int32_t table_id) { - if (is_zebra_valid_kernel_table(table_id)) - return zebra_import_table_used[afi][table_id]; - return 0; + if (is_zebra_valid_kernel_table(table_id)) + return zebra_import_table_used[afi][table_id]; + return 0; } -int -is_default (struct prefix *p) +int is_default(struct prefix *p) { - if (p->family == AF_INET) - if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0) - return 1; -#if 0 /* IPv6 default separation is now pending until protocol daemon - can handle that. */ + if (p->family == AF_INET) + if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0) + return 1; +#if 0 /* IPv6 default separation is now pending until protocol daemon \ + can handle that. */ if (p->family == AF_INET6) if (IN6_IS_ADDR_UNSPECIFIED (&p->u.prefix6) && p->prefixlen == 0) return 1; #endif /* 0 */ - return 0; + return 0; } -static void -zebra_redistribute_default (struct zserv *client, vrf_id_t vrf_id) +static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id) { - int afi; - struct prefix p; - struct route_table *table; - struct route_node *rn; - struct route_entry *newre; - - for (afi = AFI_IP; afi <= AFI_IP6; afi++) - { - /* Lookup table. */ - table = zebra_vrf_table (afi, SAFI_UNICAST, vrf_id); - if (! table) - continue; - - /* Lookup default route. */ - memset (&p, 0, sizeof (p)); - p.family = afi2family (afi); - rn = route_node_lookup (table, &p); - if (! rn) - continue; - - RNODE_FOREACH_RE (rn, newre) - if (CHECK_FLAG (newre->flags, ZEBRA_FLAG_SELECTED) - && newre->distance != DISTANCE_INFINITY) - zsend_redistribute_route (1, client, &rn->p, NULL, newre); - - route_unlock_node (rn); - } + int afi; + struct prefix p; + struct route_table *table; + struct route_node *rn; + struct route_entry *newre; + + for (afi = AFI_IP; afi <= AFI_IP6; afi++) { + /* Lookup table. */ + table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id); + if (!table) + continue; + + /* Lookup default route. */ + memset(&p, 0, sizeof(p)); + p.family = afi2family(afi); + rn = route_node_lookup(table, &p); + if (!rn) + continue; + + RNODE_FOREACH_RE(rn, newre) + if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED) + && newre->distance != DISTANCE_INFINITY) + zsend_redistribute_route(1, client, &rn->p, NULL, + newre); + + route_unlock_node(rn); + } } /* Redistribute routes. */ -static void -zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t vrf_id, int afi) +static void zebra_redistribute(struct zserv *client, int type, u_short instance, + vrf_id_t vrf_id, int afi) { - struct route_entry *newre; - struct route_table *table; - struct route_node *rn; - - table = zebra_vrf_table (afi, SAFI_UNICAST, vrf_id); - if (! table) - return; - - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RE (rn, newre) - { - struct prefix *dst_p, *src_p; - srcdest_rnode_prefixes(rn, &dst_p, &src_p); - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: checking: selected=%d, type=%d, distance=%d, " - "zebra_check_addr=%d", __func__, - CHECK_FLAG (newre->flags, ZEBRA_FLAG_SELECTED), - newre->type, newre->distance, - zebra_check_addr (dst_p)); - - if (! CHECK_FLAG (newre->flags, ZEBRA_FLAG_SELECTED)) - continue; - if ((type != ZEBRA_ROUTE_ALL && - (newre->type != type || newre->instance != instance))) - continue; - if (newre->distance == DISTANCE_INFINITY) - continue; - if (! zebra_check_addr (dst_p)) - continue; - - zsend_redistribute_route (1, client, dst_p, src_p, newre); - } + struct route_entry *newre; + struct route_table *table; + struct route_node *rn; + + table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id); + if (!table) + return; + + for (rn = route_top(table); rn; rn = route_next(rn)) + RNODE_FOREACH_RE(rn, newre) + { + struct prefix *dst_p, *src_p; + srcdest_rnode_prefixes(rn, &dst_p, &src_p); + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s: checking: selected=%d, type=%d, distance=%d, " + "zebra_check_addr=%d", + __func__, + CHECK_FLAG(newre->flags, + ZEBRA_FLAG_SELECTED), + newre->type, newre->distance, + zebra_check_addr(dst_p)); + + if (!CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED)) + continue; + if ((type != ZEBRA_ROUTE_ALL + && (newre->type != type + || newre->instance != instance))) + continue; + if (newre->distance == DISTANCE_INFINITY) + continue; + if (!zebra_check_addr(dst_p)) + continue; + + zsend_redistribute_route(1, client, dst_p, src_p, + newre); + } } /* Either advertise a route for redistribution to registered clients or */ /* withdraw redistribution if add cannot be done for client */ -void -redistribute_update (struct prefix *p, struct prefix *src_p, - struct route_entry *re, struct route_entry *prev_re) +void redistribute_update(struct prefix *p, struct prefix *src_p, + struct route_entry *re, struct route_entry *prev_re) { - struct listnode *node, *nnode; - struct zserv *client; - int send_redistribute; - int afi; - char buf[INET6_ADDRSTRLEN]; - - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Redist update re %p (type %d), old %p (type %d)", - re->vrf_id, buf, p->prefixlen, re, re->type, - prev_re, prev_re ? prev_re->type : -1); - } - - afi = family2afi(p->family); - if (!afi) - { - zlog_warn("%s: Unknown AFI/SAFI prefix received\n", __FUNCTION__); - return; - } - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - send_redistribute = 0; - - if (is_default (p) && vrf_bitmap_check (client->redist_default, re->vrf_id)) - send_redistribute = 1; - else if (vrf_bitmap_check (client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id)) - send_redistribute = 1; - else if (re->instance && redist_check_instance (&client->mi_redist[afi][re->type], - re->instance)) - send_redistribute = 1; - else if (vrf_bitmap_check (client->redist[afi][re->type], re->vrf_id)) - send_redistribute = 1; - - if (send_redistribute) - { - zsend_redistribute_route (1, client, p, src_p, re); + struct listnode *node, *nnode; + struct zserv *client; + int send_redistribute; + int afi; + char buf[INET6_ADDRSTRLEN]; + + if (IS_ZEBRA_DEBUG_RIB) { + inet_ntop(p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); + zlog_debug( + "%u:%s/%d: Redist update re %p (type %d), old %p (type %d)", + re->vrf_id, buf, p->prefixlen, re, re->type, prev_re, + prev_re ? prev_re->type : -1); + } + + afi = family2afi(p->family); + if (!afi) { + zlog_warn("%s: Unknown AFI/SAFI prefix received\n", + __FUNCTION__); + return; } - else if (prev_re && - ((re->instance && - redist_check_instance(&client->mi_redist[afi][prev_re->type], - re->instance)) || - vrf_bitmap_check (client->redist[afi][prev_re->type], re->vrf_id))) - { - zsend_redistribute_route (0, client, p, src_p, prev_re); + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + send_redistribute = 0; + + if (is_default(p) + && vrf_bitmap_check(client->redist_default, re->vrf_id)) + send_redistribute = 1; + else if (vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL], + re->vrf_id)) + send_redistribute = 1; + else if (re->instance + && redist_check_instance( + &client->mi_redist[afi][re->type], + re->instance)) + send_redistribute = 1; + else if (vrf_bitmap_check(client->redist[afi][re->type], + re->vrf_id)) + send_redistribute = 1; + + if (send_redistribute) { + zsend_redistribute_route(1, client, p, src_p, re); + } else if (prev_re + && ((re->instance + && redist_check_instance( + &client->mi_redist[afi] + [prev_re->type], + re->instance)) + || vrf_bitmap_check( + client->redist[afi][prev_re->type], + re->vrf_id))) { + zsend_redistribute_route(0, client, p, src_p, prev_re); + } } - } } -void -redistribute_delete (struct prefix *p, struct prefix *src_p, struct route_entry *re) +void redistribute_delete(struct prefix *p, struct prefix *src_p, + struct route_entry *re) { - struct listnode *node, *nnode; - struct zserv *client; - char buf[INET6_ADDRSTRLEN]; - int afi; - - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Redist delete re %p (type %d)", - re->vrf_id, buf, p->prefixlen, re, re->type); - } - - /* Add DISTANCE_INFINITY check. */ - if (re->distance == DISTANCE_INFINITY) - return; - - afi = family2afi(p->family); - if (!afi) - { - zlog_warn("%s: Unknown AFI/SAFI prefix received\n", __FUNCTION__); - return; - } - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - if ((is_default (p) && - vrf_bitmap_check (client->redist_default, re->vrf_id)) || - vrf_bitmap_check (client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id) || - (re->instance && - redist_check_instance(&client->mi_redist[afi][re->type], - re->instance)) || - vrf_bitmap_check (client->redist[afi][re->type], re->vrf_id)) - { - zsend_redistribute_route (0, client, p, src_p, re); + struct listnode *node, *nnode; + struct zserv *client; + char buf[INET6_ADDRSTRLEN]; + int afi; + + if (IS_ZEBRA_DEBUG_RIB) { + inet_ntop(p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); + zlog_debug("%u:%s/%d: Redist delete re %p (type %d)", + re->vrf_id, buf, p->prefixlen, re, re->type); + } + + /* Add DISTANCE_INFINITY check. */ + if (re->distance == DISTANCE_INFINITY) + return; + + afi = family2afi(p->family); + if (!afi) { + zlog_warn("%s: Unknown AFI/SAFI prefix received\n", + __FUNCTION__); + return; + } + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + if ((is_default(p) + && vrf_bitmap_check(client->redist_default, re->vrf_id)) + || vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL], + re->vrf_id) + || (re->instance + && redist_check_instance( + &client->mi_redist[afi][re->type], + re->instance)) + || vrf_bitmap_check(client->redist[afi][re->type], + re->vrf_id)) { + zsend_redistribute_route(0, client, p, src_p, re); + } } - } } -void -zebra_redistribute_add (int command, struct zserv *client, int length, - struct zebra_vrf *zvrf) +void zebra_redistribute_add(int command, struct zserv *client, int length, + struct zebra_vrf *zvrf) { - afi_t afi; - int type; - u_short instance; - - afi = stream_getc (client->ibuf); - type = stream_getc (client->ibuf); - instance = stream_getw (client->ibuf); - - if (type == 0 || type >= ZEBRA_ROUTE_MAX) - return; - - if (instance) - { - if (! redist_check_instance (&client->mi_redist[afi][type], instance)) - { - redist_add_instance (&client->mi_redist[afi][type], instance); - zebra_redistribute (client, type, instance, zvrf_id (zvrf), afi); + afi_t afi; + int type; + u_short instance; + + afi = stream_getc(client->ibuf); + type = stream_getc(client->ibuf); + instance = stream_getw(client->ibuf); + + if (type == 0 || type >= ZEBRA_ROUTE_MAX) + return; + + if (instance) { + if (!redist_check_instance(&client->mi_redist[afi][type], + instance)) { + redist_add_instance(&client->mi_redist[afi][type], + instance); + zebra_redistribute(client, type, instance, + zvrf_id(zvrf), afi); + } + } else { + if (!vrf_bitmap_check(client->redist[afi][type], + zvrf_id(zvrf))) { + vrf_bitmap_set(client->redist[afi][type], + zvrf_id(zvrf)); + zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi); + } } - } else { - if (! vrf_bitmap_check (client->redist[afi][type], zvrf_id (zvrf))) - { - vrf_bitmap_set (client->redist[afi][type], zvrf_id (zvrf)); - zebra_redistribute (client, type, 0, zvrf_id (zvrf), afi); - } - } } -void -zebra_redistribute_delete (int command, struct zserv *client, int length, - struct zebra_vrf *zvrf) +void zebra_redistribute_delete(int command, struct zserv *client, int length, + struct zebra_vrf *zvrf) { - afi_t afi; - int type; - u_short instance; - - afi = stream_getc (client->ibuf); - type = stream_getc (client->ibuf); - instance = stream_getw (client->ibuf); - - if (type == 0 || type >= ZEBRA_ROUTE_MAX) - return; - - /* - * NOTE: no need to withdraw the previously advertised routes. The clients - * themselves should keep track of the received routes from zebra and - * withdraw them when necessary. - */ - if (instance) - redist_del_instance (&client->mi_redist[afi][type], instance); - else - vrf_bitmap_unset (client->redist[afi][type], zvrf_id (zvrf)); + afi_t afi; + int type; + u_short instance; + + afi = stream_getc(client->ibuf); + type = stream_getc(client->ibuf); + instance = stream_getw(client->ibuf); + + if (type == 0 || type >= ZEBRA_ROUTE_MAX) + return; + + /* + * NOTE: no need to withdraw the previously advertised routes. The + * clients + * themselves should keep track of the received routes from zebra and + * withdraw them when necessary. + */ + if (instance) + redist_del_instance(&client->mi_redist[afi][type], instance); + else + vrf_bitmap_unset(client->redist[afi][type], zvrf_id(zvrf)); } -void -zebra_redistribute_default_add (int command, struct zserv *client, int length, - struct zebra_vrf *zvrf) +void zebra_redistribute_default_add(int command, struct zserv *client, + int length, struct zebra_vrf *zvrf) { - vrf_bitmap_set (client->redist_default, zvrf_id (zvrf)); - zebra_redistribute_default (client, zvrf_id (zvrf)); -} + vrf_bitmap_set(client->redist_default, zvrf_id(zvrf)); + zebra_redistribute_default(client, zvrf_id(zvrf)); +} -void -zebra_redistribute_default_delete (int command, struct zserv *client, - int length, struct zebra_vrf *zvrf) +void zebra_redistribute_default_delete(int command, struct zserv *client, + int length, struct zebra_vrf *zvrf) { - vrf_bitmap_unset (client->redist_default, zvrf_id (zvrf)); -} + vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf)); +} /* Interface up information. */ -void -zebra_interface_up_update (struct interface *ifp) +void zebra_interface_up_update(struct interface *ifp) { - struct listnode *node, *nnode; - struct zserv *client; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_UP %s", ifp->name); - - if (ifp->ptm_status || !ifp->ptm_enable) { - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - if (client->ifinfo) - { - zsend_interface_update (ZEBRA_INTERFACE_UP, client, ifp); - zsend_interface_link_params (client, ifp); + struct listnode *node, *nnode; + struct zserv *client; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_INTERFACE_UP %s", ifp->name); + + if (ifp->ptm_status || !ifp->ptm_enable) { + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + if (client->ifinfo) { + zsend_interface_update(ZEBRA_INTERFACE_UP, + client, ifp); + zsend_interface_link_params(client, ifp); + } } - } } /* Interface down information. */ -void -zebra_interface_down_update (struct interface *ifp) +void zebra_interface_down_update(struct interface *ifp) { - struct listnode *node, *nnode; - struct zserv *client; + struct listnode *node, *nnode; + struct zserv *client; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DOWN %s", ifp->name); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_INTERFACE_DOWN %s", ifp->name); - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp); - } + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp); + } } /* Interface information update. */ -void -zebra_interface_add_update (struct interface *ifp) +void zebra_interface_add_update(struct interface *ifp) { - struct listnode *node, *nnode; - struct zserv *client; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADD %s[%d]", ifp->name, ifp->vrf_id); - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - if (client->ifinfo) - { - client->ifadd_cnt++; - zsend_interface_add (client, ifp); - zsend_interface_link_params (client, ifp); - } + struct listnode *node, *nnode; + struct zserv *client; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADD %s[%d]", ifp->name, + ifp->vrf_id); + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + if (client->ifinfo) { + client->ifadd_cnt++; + zsend_interface_add(client, ifp); + zsend_interface_link_params(client, ifp); + } } -void -zebra_interface_delete_update (struct interface *ifp) +void zebra_interface_delete_update(struct interface *ifp) { - struct listnode *node, *nnode; - struct zserv *client; + struct listnode *node, *nnode; + struct zserv *client; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DELETE %s", ifp->name); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_INTERFACE_DELETE %s", ifp->name); - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - client->ifdel_cnt++; - zsend_interface_delete (client, ifp); - } + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + client->ifdel_cnt++; + zsend_interface_delete(client, ifp); + } } /* Interface address addition. */ -void -zebra_interface_address_add_update (struct interface *ifp, - struct connected *ifc) +void zebra_interface_address_add_update(struct interface *ifp, + struct connected *ifc) { - struct listnode *node, *nnode; - struct zserv *client; - struct prefix *p; - - if (IS_ZEBRA_DEBUG_EVENT) - { - char buf[PREFIX_STRLEN]; - - p = ifc->address; - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s on %s", - prefix2str (p, buf, sizeof(buf)), - ifc->ifp->name); - } - - if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) - zlog_warn("WARNING: advertising address to clients that is not yet usable."); - - router_id_add_address(ifc); - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - { - client->connected_rt_add_cnt++; - zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client, ifp, ifc); - } + struct listnode *node, *nnode; + struct zserv *client; + struct prefix *p; + + if (IS_ZEBRA_DEBUG_EVENT) { + char buf[PREFIX_STRLEN]; + + p = ifc->address; + zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s on %s", + prefix2str(p, buf, sizeof(buf)), ifc->ifp->name); + } + + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + zlog_warn( + "WARNING: advertising address to clients that is not yet usable."); + + router_id_add_address(ifc); + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) { + client->connected_rt_add_cnt++; + zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_ADD, + client, ifp, ifc); + } } /* Interface address deletion. */ -void -zebra_interface_address_delete_update (struct interface *ifp, - struct connected *ifc) +void zebra_interface_address_delete_update(struct interface *ifp, + struct connected *ifc) { - struct listnode *node, *nnode; - struct zserv *client; - struct prefix *p; - - if (IS_ZEBRA_DEBUG_EVENT) - { - char buf[PREFIX_STRLEN]; - - p = ifc->address; - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s on %s", - prefix2str (p, buf, sizeof(buf)), - ifc->ifp->name); - } - - router_id_del_address(ifc); - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - { - client->connected_rt_del_cnt++; - zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_DELETE, client, ifp, ifc); - } + struct listnode *node, *nnode; + struct zserv *client; + struct prefix *p; + + if (IS_ZEBRA_DEBUG_EVENT) { + char buf[PREFIX_STRLEN]; + + p = ifc->address; + zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s on %s", + prefix2str(p, buf, sizeof(buf)), ifc->ifp->name); + } + + router_id_del_address(ifc); + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) { + client->connected_rt_del_cnt++; + zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_DELETE, + client, ifp, ifc); + } } /* Interface VRF change. May need to delete from clients not interested in * the new VRF. Note that this function is invoked *prior* to the VRF change. */ -void -zebra_interface_vrf_update_del (struct interface *ifp, vrf_id_t new_vrf_id) +void zebra_interface_vrf_update_del(struct interface *ifp, vrf_id_t new_vrf_id) { - struct listnode *node, *nnode; - struct zserv *client; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/DEL %s VRF Id %u -> %u", - ifp->name, ifp->vrf_id, new_vrf_id); - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - /* Need to delete if the client is not interested in the new VRF. */ - zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp); - client->ifdel_cnt++; - zsend_interface_delete (client, ifp); - zsend_interface_vrf_update (client, ifp, new_vrf_id); - } + struct listnode *node, *nnode; + struct zserv *client; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/DEL %s VRF Id %u -> %u", + ifp->name, ifp->vrf_id, new_vrf_id); + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + /* Need to delete if the client is not interested in the new + * VRF. */ + zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp); + client->ifdel_cnt++; + zsend_interface_delete(client, ifp); + zsend_interface_vrf_update(client, ifp, new_vrf_id); + } } /* Interface VRF change. This function is invoked *post* VRF change and sends an * add to clients who are interested in the new VRF but not in the old VRF. */ -void -zebra_interface_vrf_update_add (struct interface *ifp, vrf_id_t old_vrf_id) +void zebra_interface_vrf_update_add(struct interface *ifp, vrf_id_t old_vrf_id) { - struct listnode *node, *nnode; - struct zserv *client; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/ADD %s VRF Id %u -> %u", - ifp->name, old_vrf_id, ifp->vrf_id); - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - /* Need to add if the client is interested in the new VRF. */ - client->ifadd_cnt++; - zsend_interface_add (client, ifp); - zsend_interface_addresses (client, ifp); - } + struct listnode *node, *nnode; + struct zserv *client; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/ADD %s VRF Id %u -> %u", + ifp->name, old_vrf_id, ifp->vrf_id); + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + /* Need to add if the client is interested in the new VRF. */ + client->ifadd_cnt++; + zsend_interface_add(client, ifp); + zsend_interface_addresses(client, ifp); + } } -int -zebra_add_import_table_entry (struct route_node *rn, struct route_entry *re, const char *rmap_name) +int zebra_add_import_table_entry(struct route_node *rn, struct route_entry *re, + const char *rmap_name) { - struct route_entry *newre; - struct route_entry *same; - struct prefix p; - struct nexthop *nhop; - union g_addr *gate; - route_map_result_t ret = RMAP_MATCH; - - if (rmap_name) - ret = zebra_import_table_route_map_check (AFI_IP, re->type, &rn->p, re->nexthop, re->vrf_id, - re->tag, rmap_name); - - if (ret == RMAP_MATCH) - { - if (rn->p.family == AF_INET) - { - p.family = AF_INET; - p.prefixlen = rn->p.prefixlen; - p.u.prefix4 = rn->p.u.prefix4; - - RNODE_FOREACH_RE (rn, same) - { - if (CHECK_FLAG (same->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (same->type == re->type && same->instance == re->instance - && same->table == re->table - && same->type != ZEBRA_ROUTE_CONNECT) - break; - } - - if (same) - zebra_del_import_table_entry (rn, same); - - - if (re->nexthop_num == 1) - { - nhop = re->nexthop; - if (nhop->type == NEXTHOP_TYPE_IFINDEX) - gate = NULL; - else - gate = (union g_addr *)&nhop->gate.ipv4; - - rib_add (AFI_IP, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE, - re->table, 0, &p, NULL, gate, (union g_addr *)&nhop->src.ipv4, - nhop->ifindex, zebrad.rtm_table_default, - re->metric, re->mtu, - zebra_import_table_distance[AFI_IP][re->table]); - } - else if (re->nexthop_num > 1) - { - newre = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - newre->type = ZEBRA_ROUTE_TABLE; - newre->distance = zebra_import_table_distance[AFI_IP][re->table]; - newre->flags = re->flags; - newre->metric = re->metric; - newre->mtu = re->mtu; - newre->table = zebrad.rtm_table_default; - newre->nexthop_num = 0; - newre->uptime = time(NULL); - newre->instance = re->table; - route_entry_copy_nexthops(newre, re->nexthop); - - rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, NULL, newre); - } - } - } - else - { - zebra_del_import_table_entry (rn, re); - } - /* DD: Add IPv6 code */ - return 0; + struct route_entry *newre; + struct route_entry *same; + struct prefix p; + struct nexthop *nhop; + union g_addr *gate; + route_map_result_t ret = RMAP_MATCH; + + if (rmap_name) + ret = zebra_import_table_route_map_check( + AFI_IP, re->type, &rn->p, re->nexthop, re->vrf_id, + re->tag, rmap_name); + + if (ret == RMAP_MATCH) { + if (rn->p.family == AF_INET) { + p.family = AF_INET; + p.prefixlen = rn->p.prefixlen; + p.u.prefix4 = rn->p.u.prefix4; + + RNODE_FOREACH_RE(rn, same) + { + if (CHECK_FLAG(same->status, + ROUTE_ENTRY_REMOVED)) + continue; + + if (same->type == re->type + && same->instance == re->instance + && same->table == re->table + && same->type != ZEBRA_ROUTE_CONNECT) + break; + } + + if (same) + zebra_del_import_table_entry(rn, same); + + + if (re->nexthop_num == 1) { + nhop = re->nexthop; + if (nhop->type == NEXTHOP_TYPE_IFINDEX) + gate = NULL; + else + gate = (union g_addr *)&nhop->gate.ipv4; + + rib_add(AFI_IP, SAFI_UNICAST, re->vrf_id, + ZEBRA_ROUTE_TABLE, re->table, 0, &p, + NULL, gate, + (union g_addr *)&nhop->src.ipv4, + nhop->ifindex, zebrad.rtm_table_default, + re->metric, re->mtu, + zebra_import_table_distance[AFI_IP] + [re->table]); + } else if (re->nexthop_num > 1) { + newre = XCALLOC(MTYPE_RE, + sizeof(struct route_entry)); + newre->type = ZEBRA_ROUTE_TABLE; + newre->distance = + zebra_import_table_distance[AFI_IP] + [re->table]; + newre->flags = re->flags; + newre->metric = re->metric; + newre->mtu = re->mtu; + newre->table = zebrad.rtm_table_default; + newre->nexthop_num = 0; + newre->uptime = time(NULL); + newre->instance = re->table; + route_entry_copy_nexthops(newre, re->nexthop); + + rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, + NULL, newre); + } + } + } else { + zebra_del_import_table_entry(rn, re); + } + /* DD: Add IPv6 code */ + return 0; } -int -zebra_del_import_table_entry (struct route_node *rn, struct route_entry *re) +int zebra_del_import_table_entry(struct route_node *rn, struct route_entry *re) { - struct prefix p; + struct prefix p; - if (rn->p.family == AF_INET) - { - p.family = AF_INET; - p.prefixlen = rn->p.prefixlen; - p.u.prefix4 = rn->p.u.prefix4; + if (rn->p.family == AF_INET) { + p.family = AF_INET; + p.prefixlen = rn->p.prefixlen; + p.u.prefix4 = rn->p.u.prefix4; - rib_delete (AFI_IP, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE, - re->table, re->flags, &p, NULL, NULL, - 0, zebrad.rtm_table_default); - } - /* DD: Add IPv6 code */ + rib_delete(AFI_IP, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE, + re->table, re->flags, &p, NULL, NULL, 0, + zebrad.rtm_table_default); + } + /* DD: Add IPv6 code */ - return 0; + return 0; } /* Assuming no one calls this with the main routing table */ -int -zebra_import_table (afi_t afi, u_int32_t table_id, u_int32_t distance, const char *rmap_name, int add) +int zebra_import_table(afi_t afi, u_int32_t table_id, u_int32_t distance, + const char *rmap_name, int add) { - struct route_table *table; - struct route_entry *re; - struct route_node *rn; - - if (!is_zebra_valid_kernel_table(table_id) || - ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default))) - return (-1); - - if (afi >= AFI_MAX) - return (-1); - - table = zebra_vrf_other_route_table(afi, table_id, VRF_DEFAULT); - if (table == NULL) - { - return 0; - } - else if (IS_ZEBRA_DEBUG_RIB) - { - zlog_debug ("%s routes from table %d", - add ? "Importing" : "Unimporting", table_id); - } - - if (add) - { - if (rmap_name) - zebra_add_import_table_route_map (afi, rmap_name, table_id); - else - { - rmap_name = zebra_get_import_table_route_map (afi, table_id); - if (rmap_name) - zebra_del_import_table_route_map (afi, table_id); - } - - zebra_import_table_used[afi][table_id] = 1; - zebra_import_table_distance[afi][table_id] = distance; - } - else - { - zebra_import_table_used[afi][table_id] = 0; - zebra_import_table_distance[afi][table_id] = ZEBRA_TABLE_DISTANCE_DEFAULT; - - rmap_name = zebra_get_import_table_route_map (afi, table_id); - if (rmap_name) - zebra_del_import_table_route_map (afi, table_id); - } - - for (rn = route_top(table); rn; rn = route_next(rn)) - { - /* For each entry in the non-default routing table, - * add the entry in the main table - */ - if (!rn->info) - continue; - - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - break; + struct route_table *table; + struct route_entry *re; + struct route_node *rn; + + if (!is_zebra_valid_kernel_table(table_id) + || ((table_id == RT_TABLE_MAIN) + || (table_id == zebrad.rtm_table_default))) + return (-1); + + if (afi >= AFI_MAX) + return (-1); + + table = zebra_vrf_other_route_table(afi, table_id, VRF_DEFAULT); + if (table == NULL) { + return 0; + } else if (IS_ZEBRA_DEBUG_RIB) { + zlog_debug("%s routes from table %d", + add ? "Importing" : "Unimporting", table_id); } - if (!re) - continue; + if (add) { + if (rmap_name) + zebra_add_import_table_route_map(afi, rmap_name, + table_id); + else { + rmap_name = + zebra_get_import_table_route_map(afi, table_id); + if (rmap_name) + zebra_del_import_table_route_map(afi, table_id); + } - if (((afi == AFI_IP) && (rn->p.family == AF_INET)) || - ((afi == AFI_IP6) && (rn->p.family == AF_INET6))) - { - if (add) - zebra_add_import_table_entry (rn, re, rmap_name); - else - zebra_del_import_table_entry (rn, re); + zebra_import_table_used[afi][table_id] = 1; + zebra_import_table_distance[afi][table_id] = distance; + } else { + zebra_import_table_used[afi][table_id] = 0; + zebra_import_table_distance[afi][table_id] = + ZEBRA_TABLE_DISTANCE_DEFAULT; + + rmap_name = zebra_get_import_table_route_map(afi, table_id); + if (rmap_name) + zebra_del_import_table_route_map(afi, table_id); } - } - return 0; -} -int -zebra_import_table_config (struct vty *vty) -{ - int i; - afi_t afi; - int write = 0; - char afi_str[AFI_MAX][10] = {"", "ip", "ipv6", "ethernet"}; - const char *rmap_name; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) - { - if (is_zebra_import_table_enabled(afi, i)) - { - if (zebra_import_table_distance[afi][i] != ZEBRA_TABLE_DISTANCE_DEFAULT) - { - vty_out(vty, "%s import-table %d distance %d", afi_str[afi], - i, zebra_import_table_distance[afi][i]); - } - else + for (rn = route_top(table); rn; rn = route_next(rn)) { + /* For each entry in the non-default routing table, + * add the entry in the main table + */ + if (!rn->info) + continue; + + RNODE_FOREACH_RE(rn, re) { - vty_out(vty, "%s import-table %d", afi_str[afi], i); + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + break; } - rmap_name = zebra_get_import_table_route_map (afi, i); - if (rmap_name) - vty_out(vty, " route-map %s", rmap_name); + if (!re) + continue; - vty_out (vty, "\n"); - write = 1; - } + if (((afi == AFI_IP) && (rn->p.family == AF_INET)) + || ((afi == AFI_IP6) && (rn->p.family == AF_INET6))) { + if (add) + zebra_add_import_table_entry(rn, re, rmap_name); + else + zebra_del_import_table_entry(rn, re); + } + } + return 0; +} + +int zebra_import_table_config(struct vty *vty) +{ + int i; + afi_t afi; + int write = 0; + char afi_str[AFI_MAX][10] = {"", "ip", "ipv6", "ethernet"}; + const char *rmap_name; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) { + if (is_zebra_import_table_enabled(afi, i)) { + if (zebra_import_table_distance[afi][i] + != ZEBRA_TABLE_DISTANCE_DEFAULT) { + vty_out(vty, + "%s import-table %d distance %d", + afi_str[afi], i, + zebra_import_table_distance[afi] + [i]); + } else { + vty_out(vty, "%s import-table %d", + afi_str[afi], i); + } + + rmap_name = zebra_get_import_table_route_map( + afi, i); + if (rmap_name) + vty_out(vty, " route-map %s", + rmap_name); + + vty_out(vty, "\n"); + write = 1; + } + } } - } - return write; + return write; } -void -zebra_import_table_rm_update () +void zebra_import_table_rm_update() { - afi_t afi; - int i; - struct route_table *table; - struct route_entry *re; - struct route_node *rn; - const char *rmap_name; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) - { - if (is_zebra_import_table_enabled(afi, i)) - { - rmap_name = zebra_get_import_table_route_map (afi, i); - if (!rmap_name) - return; - - table = zebra_vrf_other_route_table(afi, i, VRF_DEFAULT); - for (rn = route_top(table); rn; rn = route_next(rn)) - { - /* For each entry in the non-default routing table, - * add the entry in the main table - */ - if (!rn->info) - continue; - - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - break; - } - - if (!re) - continue; - - if (((afi == AFI_IP) && (rn->p.family == AF_INET)) || - ((afi == AFI_IP6) && (rn->p.family == AF_INET6))) - zebra_add_import_table_entry (rn, re, rmap_name); - } - } + afi_t afi; + int i; + struct route_table *table; + struct route_entry *re; + struct route_node *rn; + const char *rmap_name; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) { + if (is_zebra_import_table_enabled(afi, i)) { + rmap_name = zebra_get_import_table_route_map( + afi, i); + if (!rmap_name) + return; + + table = zebra_vrf_other_route_table( + afi, i, VRF_DEFAULT); + for (rn = route_top(table); rn; + rn = route_next(rn)) { + /* For each entry in the non-default + * routing table, + * add the entry in the main table + */ + if (!rn->info) + continue; + + RNODE_FOREACH_RE(rn, re) + { + if (CHECK_FLAG( + re->status, + ROUTE_ENTRY_REMOVED)) + continue; + break; + } + + if (!re) + continue; + + if (((afi == AFI_IP) + && (rn->p.family == AF_INET)) + || ((afi == AFI_IP6) + && (rn->p.family == AF_INET6))) + zebra_add_import_table_entry( + rn, re, rmap_name); + } + } + } } - } - return; + return; } /* Interface parameters update */ -void -zebra_interface_parameters_update (struct interface *ifp) +void zebra_interface_parameters_update(struct interface *ifp) { - struct listnode *node, *nnode; - struct zserv *client; + struct listnode *node, *nnode; + struct zserv *client; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s", ifp->name); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s", + ifp->name); - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - if (client->ifinfo) - zsend_interface_link_params (client, ifp); + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + if (client->ifinfo) + zsend_interface_link_params(client, ifp); } diff --git a/zebra/redistribute.h b/zebra/redistribute.h index 429ec1bfd..819b67918 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -27,46 +27,51 @@ #include "vty.h" #include "vrf.h" -extern void zebra_redistribute_add (int, struct zserv *, int, struct zebra_vrf *zvrf); -extern void zebra_redistribute_delete (int, struct zserv *, int, struct zebra_vrf *zvrf); +extern void zebra_redistribute_add(int, struct zserv *, int, + struct zebra_vrf *zvrf); +extern void zebra_redistribute_delete(int, struct zserv *, int, + struct zebra_vrf *zvrf); -extern void zebra_redistribute_default_add (int, struct zserv *, int, - struct zebra_vrf *zvrf); -extern void zebra_redistribute_default_delete (int, struct zserv *, int, - struct zebra_vrf *zvrf); +extern void zebra_redistribute_default_add(int, struct zserv *, int, + struct zebra_vrf *zvrf); +extern void zebra_redistribute_default_delete(int, struct zserv *, int, + struct zebra_vrf *zvrf); -extern void redistribute_update (struct prefix *, struct prefix *, - struct route_entry *, struct route_entry *); -extern void redistribute_delete (struct prefix *, struct prefix *, struct route_entry *); +extern void redistribute_update(struct prefix *, struct prefix *, + struct route_entry *, struct route_entry *); +extern void redistribute_delete(struct prefix *, struct prefix *, + struct route_entry *); -extern void zebra_interface_up_update (struct interface *); -extern void zebra_interface_down_update (struct interface *); +extern void zebra_interface_up_update(struct interface *); +extern void zebra_interface_down_update(struct interface *); -extern void zebra_interface_add_update (struct interface *); -extern void zebra_interface_delete_update (struct interface *); +extern void zebra_interface_add_update(struct interface *); +extern void zebra_interface_delete_update(struct interface *); -extern void zebra_interface_address_add_update (struct interface *, - struct connected *); -extern void zebra_interface_address_delete_update (struct interface *, - struct connected *c); -extern void zebra_interface_parameters_update (struct interface *); -extern void zebra_interface_vrf_update_del (struct interface *, vrf_id_t new_vrf_id); -extern void zebra_interface_vrf_update_add (struct interface *, vrf_id_t old_vrf_id); +extern void zebra_interface_address_add_update(struct interface *, + struct connected *); +extern void zebra_interface_address_delete_update(struct interface *, + struct connected *c); +extern void zebra_interface_parameters_update(struct interface *); +extern void zebra_interface_vrf_update_del(struct interface *, + vrf_id_t new_vrf_id); +extern void zebra_interface_vrf_update_add(struct interface *, + vrf_id_t old_vrf_id); -extern int zebra_import_table (afi_t afi, u_int32_t table_id, - u_int32_t distance, const char *rmap_name, int add); +extern int zebra_import_table(afi_t afi, u_int32_t table_id, u_int32_t distance, + const char *rmap_name, int add); -extern int zebra_add_import_table_entry (struct route_node *rn, - struct route_entry *re, const char *rmap_name); -extern int zebra_del_import_table_entry (struct route_node *rn, - struct route_entry *re); +extern int zebra_add_import_table_entry(struct route_node *rn, + struct route_entry *re, + const char *rmap_name); +extern int zebra_del_import_table_entry(struct route_node *rn, + struct route_entry *re); extern int is_zebra_import_table_enabled(afi_t, u_int32_t table_id); extern int zebra_import_table_config(struct vty *); extern void zebra_import_table_rm_update(void); -extern int is_default (struct prefix *); +extern int is_default(struct prefix *); #endif /* _ZEBRA_REDISTRIBUTE_H */ - diff --git a/zebra/rib.h b/zebra/rib.h index 999266241..eca2be5ee 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -37,63 +37,62 @@ #define DISTANCE_INFINITY 255 #define ZEBRA_KERNEL_TABLE_MAX 252 /* support for no more than this rt tables */ -struct route_entry -{ - /* Link list. */ - struct route_entry *next; - struct route_entry *prev; - - /* Nexthop structure */ - struct nexthop *nexthop; - - /* Refrence count. */ - unsigned long refcnt; - - /* Tag */ - route_tag_t tag; - - /* Uptime. */ - time_t uptime; - - /* Type fo this route. */ - int type; - - /* Source protocol instance */ - u_short instance; - - /* VRF identifier. */ - vrf_id_t vrf_id; - - /* Which routing table */ - uint32_t table; - - /* Metric */ - u_int32_t metric; - - /* MTU */ - u_int32_t mtu; - u_int32_t nexthop_mtu; - - /* Distance. */ - u_char distance; - - /* Flags of this route. - * This flag's definition is in lib/zebra.h ZEBRA_FLAG_* and is exposed - * to clients via Zserv - */ - u_int32_t flags; - - /* RIB internal status */ - u_char status; +struct route_entry { + /* Link list. */ + struct route_entry *next; + struct route_entry *prev; + + /* Nexthop structure */ + struct nexthop *nexthop; + + /* Refrence count. */ + unsigned long refcnt; + + /* Tag */ + route_tag_t tag; + + /* Uptime. */ + time_t uptime; + + /* Type fo this route. */ + int type; + + /* Source protocol instance */ + u_short instance; + + /* VRF identifier. */ + vrf_id_t vrf_id; + + /* Which routing table */ + uint32_t table; + + /* Metric */ + u_int32_t metric; + + /* MTU */ + u_int32_t mtu; + u_int32_t nexthop_mtu; + + /* Distance. */ + u_char distance; + + /* Flags of this route. + * This flag's definition is in lib/zebra.h ZEBRA_FLAG_* and is exposed + * to clients via Zserv + */ + u_int32_t flags; + + /* RIB internal status */ + u_char status; #define ROUTE_ENTRY_REMOVED 0x1 - /* to simplify NHT logic when NHs change, instead of doing a NH by NH cmp */ +/* to simplify NHT logic when NHs change, instead of doing a NH by NH cmp */ #define ROUTE_ENTRY_NEXTHOPS_CHANGED 0x2 #define ROUTE_ENTRY_CHANGED 0x4 #define ROUTE_ENTRY_SELECTED_FIB 0x8 - /* Nexthop information. */ - u_char nexthop_num; - u_char nexthop_active_num; + /* Nexthop information. */ + u_char nexthop_num; + u_char nexthop_active_num; }; /* meta-queue structure: @@ -104,38 +103,36 @@ struct route_entry * sub-queue 4: any other origin (if any) */ #define MQ_SIZE 5 -struct meta_queue -{ - struct list *subq[MQ_SIZE]; - u_int32_t size; /* sum of lengths of all subqueues */ +struct meta_queue { + struct list *subq[MQ_SIZE]; + u_int32_t size; /* sum of lengths of all subqueues */ }; /* * Structure that represents a single destination (prefix). */ -typedef struct rib_dest_t_ -{ +typedef struct rib_dest_t_ { - /* - * Back pointer to the route node for this destination. This helps - * us get to the prefix that this structure is for. - */ - struct route_node *rnode; + /* + * Back pointer to the route node for this destination. This helps + * us get to the prefix that this structure is for. + */ + struct route_node *rnode; - /* - * Doubly-linked list of routes for this prefix. - */ - struct route_entry *routes; + /* + * Doubly-linked list of routes for this prefix. + */ + struct route_entry *routes; - /* - * Flags, see below. - */ - u_int32_t flags; + /* + * Flags, see below. + */ + u_int32_t flags; - /* - * Linkage to put dest on the FPM processing queue. - */ - TAILQ_ENTRY(rib_dest_t_) fpm_q_entries; + /* + * Linkage to put dest on the FPM processing queue. + */ + TAILQ_ENTRY(rib_dest_t_) fpm_q_entries; } rib_dest_t; @@ -161,34 +158,32 @@ typedef struct rib_dest_t_ /* * Macro to iterate over each route for a destination (prefix). */ -#define RE_DEST_FOREACH_ROUTE(dest, re) \ - for ((re) = (dest) ? (dest)->routes : NULL; (re); (re) = (re)->next) +#define RE_DEST_FOREACH_ROUTE(dest, re) \ + for ((re) = (dest) ? (dest)->routes : NULL; (re); (re) = (re)->next) /* * Same as above, but allows the current node to be unlinked. */ -#define RE_DEST_FOREACH_ROUTE_SAFE(dest, re, next) \ - for ((re) = (dest) ? (dest)->routes : NULL; \ - (re) && ((next) = (re)->next, 1); \ - (re) = (next)) +#define RE_DEST_FOREACH_ROUTE_SAFE(dest, re, next) \ + for ((re) = (dest) ? (dest)->routes : NULL; \ + (re) && ((next) = (re)->next, 1); (re) = (next)) -#define RNODE_FOREACH_RE(rn, re) \ - RE_DEST_FOREACH_ROUTE (rib_dest_from_rnode (rn), re) +#define RNODE_FOREACH_RE(rn, re) \ + RE_DEST_FOREACH_ROUTE(rib_dest_from_rnode(rn), re) -#define RNODE_FOREACH_RE_SAFE(rn, re, next) \ - RE_DEST_FOREACH_ROUTE_SAFE (rib_dest_from_rnode (rn), re, next) +#define RNODE_FOREACH_RE_SAFE(rn, re, next) \ + RE_DEST_FOREACH_ROUTE_SAFE(rib_dest_from_rnode(rn), re, next) -#if defined (HAVE_RTADV) +#if defined(HAVE_RTADV) /* Structure which hold status of router advertisement. */ -struct rtadv -{ - int sock; +struct rtadv { + int sock; - int adv_if_count; - int adv_msec_if_count; + int adv_if_count; + int adv_msec_if_count; - struct thread *ra_read; - struct thread *ra_timer; + struct thread *ra_read; + struct thread *ra_timer; }; #endif /* HAVE_RTADV */ @@ -198,142 +193,141 @@ struct rtadv * Structure that is hung off of a route_table that holds information about * the table. */ -typedef struct rib_table_info_t_ -{ +typedef struct rib_table_info_t_ { - /* - * Back pointer to zebra_vrf. - */ - struct zebra_vrf *zvrf; - afi_t afi; - safi_t safi; + /* + * Back pointer to zebra_vrf. + */ + struct zebra_vrf *zvrf; + afi_t afi; + safi_t safi; } rib_table_info_t; -typedef enum -{ - RIB_TABLES_ITER_S_INIT, - RIB_TABLES_ITER_S_ITERATING, - RIB_TABLES_ITER_S_DONE +typedef enum { + RIB_TABLES_ITER_S_INIT, + RIB_TABLES_ITER_S_ITERATING, + RIB_TABLES_ITER_S_DONE } rib_tables_iter_state_t; /* * Structure that holds state for iterating over all tables in the * Routing Information Base. */ -typedef struct rib_tables_iter_t_ -{ - vrf_id_t vrf_id; - int afi_safi_ix; +typedef struct rib_tables_iter_t_ { + vrf_id_t vrf_id; + int afi_safi_ix; - rib_tables_iter_state_t state; + rib_tables_iter_state_t state; } rib_tables_iter_t; /* Events/reasons triggering a RIB update. */ -typedef enum -{ - RIB_UPDATE_IF_CHANGE, - RIB_UPDATE_RMAP_CHANGE, - RIB_UPDATE_OTHER +typedef enum { + RIB_UPDATE_IF_CHANGE, + RIB_UPDATE_RMAP_CHANGE, + RIB_UPDATE_OTHER } rib_update_event_t; -extern struct nexthop *route_entry_nexthop_ifindex_add (struct route_entry *, ifindex_t); -extern struct nexthop *route_entry_nexthop_blackhole_add (struct route_entry *); -extern struct nexthop *route_entry_nexthop_ipv4_add (struct route_entry *, - struct in_addr *, - struct in_addr *); -extern struct nexthop *route_entry_nexthop_ipv4_ifindex_add (struct route_entry *, - struct in_addr *, - struct in_addr *, - ifindex_t); -extern void route_entry_nexthop_delete (struct route_entry *re, struct nexthop *nexthop); -extern struct nexthop *route_entry_nexthop_ipv6_add (struct route_entry *, - struct in6_addr *); -extern struct nexthop *route_entry_nexthop_ipv6_ifindex_add (struct route_entry *re, - struct in6_addr *ipv6, - ifindex_t ifindex); -extern void route_entry_nexthop_add (struct route_entry *re, struct nexthop *nexthop); -extern void route_entry_copy_nexthops (struct route_entry *re, struct nexthop *nh); +extern struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *, + ifindex_t); +extern struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *); +extern struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *, + struct in_addr *, + struct in_addr *); +extern struct nexthop * +route_entry_nexthop_ipv4_ifindex_add(struct route_entry *, struct in_addr *, + struct in_addr *, ifindex_t); +extern void route_entry_nexthop_delete(struct route_entry *re, + struct nexthop *nexthop); +extern struct nexthop *route_entry_nexthop_ipv6_add(struct route_entry *, + struct in6_addr *); +extern struct nexthop * +route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re, + struct in6_addr *ipv6, ifindex_t ifindex); +extern void route_entry_nexthop_add(struct route_entry *re, + struct nexthop *nexthop); +extern void route_entry_copy_nexthops(struct route_entry *re, + struct nexthop *nh); #define route_entry_dump(prefix, src, re) _route_entry_dump(__func__, prefix, src, re) -extern void _route_entry_dump (const char *, - union prefixconstptr, - union prefixconstptr, const struct route_entry *); +extern void _route_entry_dump(const char *, union prefixconstptr, + union prefixconstptr, const struct route_entry *); /* RPF lookup behaviour */ -enum multicast_mode -{ - MCAST_NO_CONFIG = 0, /* MIX_MRIB_FIRST, but no show in config write */ - MCAST_MRIB_ONLY, /* MRIB only */ - MCAST_URIB_ONLY, /* URIB only */ - MCAST_MIX_MRIB_FIRST, /* MRIB, if nothing at all then URIB */ - MCAST_MIX_DISTANCE, /* MRIB & URIB, lower distance wins */ - MCAST_MIX_PFXLEN, /* MRIB & URIB, longer prefix wins */ - /* on equal value, MRIB wins for last 2 */ +enum multicast_mode { + MCAST_NO_CONFIG = 0, /* MIX_MRIB_FIRST, but no show in config write */ + MCAST_MRIB_ONLY, /* MRIB only */ + MCAST_URIB_ONLY, /* URIB only */ + MCAST_MIX_MRIB_FIRST, /* MRIB, if nothing at all then URIB */ + MCAST_MIX_DISTANCE, /* MRIB & URIB, lower distance wins */ + MCAST_MIX_PFXLEN, /* MRIB & URIB, longer prefix wins */ + /* on equal value, MRIB wins for last 2 */ }; -extern void multicast_mode_ipv4_set (enum multicast_mode mode); -extern enum multicast_mode multicast_mode_ipv4_get (void); +extern void multicast_mode_ipv4_set(enum multicast_mode mode); +extern enum multicast_mode multicast_mode_ipv4_get(void); -extern void rib_lookup_and_dump (struct prefix_ipv4 *, vrf_id_t); -extern void rib_lookup_and_pushup (struct prefix_ipv4 *, vrf_id_t); +extern void rib_lookup_and_dump(struct prefix_ipv4 *, vrf_id_t); +extern void rib_lookup_and_pushup(struct prefix_ipv4 *, vrf_id_t); -extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *, - vrf_id_t); +extern int rib_lookup_ipv4_route(struct prefix_ipv4 *, union sockunion *, + vrf_id_t); #define ZEBRA_RIB_LOOKUP_ERROR -1 #define ZEBRA_RIB_FOUND_EXACT 0 #define ZEBRA_RIB_FOUND_NOGATE 1 #define ZEBRA_RIB_FOUND_CONNECTED 2 #define ZEBRA_RIB_NOTFOUND 3 - - extern int is_zebra_valid_kernel_table(u_int32_t table_id); extern int is_zebra_main_routing_table(u_int32_t table_id); -extern int zebra_check_addr (struct prefix *p); +extern int zebra_check_addr(struct prefix *p); -extern void rib_addnode (struct route_node *rn, struct route_entry *re, int process); -extern void rib_delnode (struct route_node *rn, struct route_entry *re); -extern int rib_install_kernel (struct route_node *rn, struct route_entry *re, struct route_entry *old); -extern int rib_uninstall_kernel (struct route_node *rn, struct route_entry *re); +extern void rib_addnode(struct route_node *rn, struct route_entry *re, + int process); +extern void rib_delnode(struct route_node *rn, struct route_entry *re); +extern int rib_install_kernel(struct route_node *rn, struct route_entry *re, + struct route_entry *old); +extern int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re); /* NOTE: * All rib_add function will not just add prefix into RIB, but * also implicitly withdraw equal prefix of same type. */ -extern int rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, - u_short instance, int flags, struct prefix *p, - struct prefix_ipv6 *src_p, union g_addr *gate, union g_addr *src, - ifindex_t ifindex, u_int32_t table_id, - u_int32_t, u_int32_t, u_char); - -extern int rib_add_multipath (afi_t afi, safi_t safi, struct prefix *, - struct prefix_ipv6 *src_p, struct route_entry *); - -extern void rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, - u_short instance, int flags, struct prefix *p, - struct prefix_ipv6 *src_p, union g_addr *gate, - ifindex_t ifindex, u_int32_t table_id); - -extern struct route_entry *rib_match (afi_t afi, safi_t safi, vrf_id_t, union g_addr *, - struct route_node **rn_out); -extern struct route_entry *rib_match_ipv4_multicast (vrf_id_t vrf_id, struct in_addr addr, - struct route_node **rn_out); - -extern struct route_entry *rib_lookup_ipv4 (struct prefix_ipv4 *, vrf_id_t); - -extern void rib_update (vrf_id_t, rib_update_event_t); -extern void rib_weed_tables (void); -extern void rib_sweep_route (void); -extern void rib_close_table (struct route_table *); -extern void rib_init (void); -extern unsigned long rib_score_proto (u_char proto, u_short instance); -extern void rib_queue_add (struct route_node *rn); -extern void meta_queue_free (struct meta_queue *mq); -extern int zebra_rib_labeled_unicast (struct route_entry *re); +extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, + u_short instance, int flags, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, + union g_addr *src, ifindex_t ifindex, u_int32_t table_id, + u_int32_t, u_int32_t, u_char); + +extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *, + struct prefix_ipv6 *src_p, struct route_entry *); + +extern void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, + u_short instance, int flags, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, + ifindex_t ifindex, u_int32_t table_id); + +extern struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t, + union g_addr *, + struct route_node **rn_out); +extern struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id, + struct in_addr addr, + struct route_node **rn_out); + +extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *, vrf_id_t); + +extern void rib_update(vrf_id_t, rib_update_event_t); +extern void rib_weed_tables(void); +extern void rib_sweep_route(void); +extern void rib_close_table(struct route_table *); +extern void rib_init(void); +extern unsigned long rib_score_proto(u_char proto, u_short instance); +extern void rib_queue_add(struct route_node *rn); +extern void meta_queue_free(struct meta_queue *mq); +extern int zebra_rib_labeled_unicast(struct route_entry *re); extern struct route_table *rib_table_ipv6; -extern void rib_unlink (struct route_node *, struct route_entry *); -extern int rib_gc_dest (struct route_node *rn); -extern struct route_table *rib_tables_iter_next (rib_tables_iter_t *iter); +extern void rib_unlink(struct route_node *, struct route_entry *); +extern int rib_gc_dest(struct route_node *rn); +extern struct route_table *rib_tables_iter_next(rib_tables_iter_t *iter); extern u_char route_distance(int type); @@ -344,19 +338,17 @@ extern u_char route_distance(int type); /* * rib_table_info */ -static inline rib_table_info_t * -rib_table_info (struct route_table *table) +static inline rib_table_info_t *rib_table_info(struct route_table *table) { - return (rib_table_info_t *) table->info; + return (rib_table_info_t *)table->info; } /* * rib_dest_from_rnode */ -static inline rib_dest_t * -rib_dest_from_rnode (struct route_node *rn) +static inline rib_dest_t *rib_dest_from_rnode(struct route_node *rn) { - return (rib_dest_t *) rn->info; + return (rib_dest_t *)rn->info; } /* @@ -365,25 +357,23 @@ rib_dest_from_rnode (struct route_node *rn) * Returns a pointer to the list of routes corresponding to the given * route_node. */ -static inline struct route_entry * -rnode_to_ribs (struct route_node *rn) +static inline struct route_entry *rnode_to_ribs(struct route_node *rn) { - rib_dest_t *dest; + rib_dest_t *dest; - dest = rib_dest_from_rnode (rn); - if (!dest) - return NULL; + dest = rib_dest_from_rnode(rn); + if (!dest) + return NULL; - return dest->routes; + return dest->routes; } /* * rib_dest_prefix */ -static inline struct prefix * -rib_dest_prefix (rib_dest_t *dest) +static inline struct prefix *rib_dest_prefix(rib_dest_t *dest) { - return &dest->rnode->p; + return &dest->rnode->p; } /* @@ -391,39 +381,35 @@ rib_dest_prefix (rib_dest_t *dest) * * Returns the address family that the destination is for. */ -static inline u_char -rib_dest_af (rib_dest_t *dest) +static inline u_char rib_dest_af(rib_dest_t *dest) { - return dest->rnode->p.family; + return dest->rnode->p.family; } /* * rib_dest_table */ -static inline struct route_table * -rib_dest_table (rib_dest_t *dest) +static inline struct route_table *rib_dest_table(rib_dest_t *dest) { - return srcdest_rnode_table(dest->rnode); + return srcdest_rnode_table(dest->rnode); } /* * rib_dest_vrf */ -static inline struct zebra_vrf * -rib_dest_vrf (rib_dest_t *dest) +static inline struct zebra_vrf *rib_dest_vrf(rib_dest_t *dest) { - return rib_table_info (rib_dest_table (dest))->zvrf; + return rib_table_info(rib_dest_table(dest))->zvrf; } /* * rib_tables_iter_init */ -static inline void -rib_tables_iter_init (rib_tables_iter_t *iter) +static inline void rib_tables_iter_init(rib_tables_iter_t *iter) { - memset (iter, 0, sizeof (*iter)); - iter->state = RIB_TABLES_ITER_S_INIT; + memset(iter, 0, sizeof(*iter)); + iter->state = RIB_TABLES_ITER_S_INIT; } /* @@ -432,21 +418,20 @@ rib_tables_iter_init (rib_tables_iter_t *iter) * Returns TRUE if this iterator has started iterating over the set of * tables. */ -static inline int -rib_tables_iter_started (rib_tables_iter_t *iter) +static inline int rib_tables_iter_started(rib_tables_iter_t *iter) { - return iter->state != RIB_TABLES_ITER_S_INIT; + return iter->state != RIB_TABLES_ITER_S_INIT; } /* * rib_tables_iter_cleanup */ -static inline void -rib_tables_iter_cleanup (rib_tables_iter_t *iter) +static inline void rib_tables_iter_cleanup(rib_tables_iter_t *iter) { - iter->state = RIB_TABLES_ITER_S_DONE; + iter->state = RIB_TABLES_ITER_S_DONE; } -DECLARE_HOOK(rib_update, (struct route_node *rn, const char *reason), (rn, reason)) +DECLARE_HOOK(rib_update, (struct route_node * rn, const char *reason), + (rn, reason)) #endif /*_ZEBRA_RIB_H */ diff --git a/zebra/router-id.c b/zebra/router-id.c index e23178cb7..383f21864 100644 --- a/zebra/router-id.c +++ b/zebra/router-id.c @@ -1,7 +1,7 @@ /* * Router ID for zebra daemon. * - * Copyright (C) 2004 James R. Leu + * Copyright (C) 2004 James R. Leu * * This file is part of Quagga routing suite. * @@ -46,169 +46,160 @@ /* master zebra server structure */ extern struct zebra_t zebrad; -static struct connected * -router_id_find_node (struct list *l, struct connected *ifc) +static struct connected *router_id_find_node(struct list *l, + struct connected *ifc) { - struct listnode *node; - struct connected *c; + struct listnode *node; + struct connected *c; - for (ALL_LIST_ELEMENTS_RO (l, node, c)) - if (prefix_same (ifc->address, c->address)) - return c; + for (ALL_LIST_ELEMENTS_RO(l, node, c)) + if (prefix_same(ifc->address, c->address)) + return c; - return NULL; + return NULL; } -static int -router_id_bad_address (struct connected *ifc) +static int router_id_bad_address(struct connected *ifc) { - if (ifc->address->family != AF_INET) - return 1; - - /* non-redistributable addresses shouldn't be used for RIDs either */ - if (!zebra_check_addr (ifc->address)) - return 1; - - return 0; + if (ifc->address->family != AF_INET) + return 1; + + /* non-redistributable addresses shouldn't be used for RIDs either */ + if (!zebra_check_addr(ifc->address)) + return 1; + + return 0; } -void -router_id_get (struct prefix *p, vrf_id_t vrf_id) +void router_id_get(struct prefix *p, vrf_id_t vrf_id) { - struct listnode *node; - struct connected *c; - struct zebra_vrf *zvrf = vrf_info_get (vrf_id); - - p->u.prefix4.s_addr = 0; - p->family = AF_INET; - p->prefixlen = 32; - - if (zvrf->rid_user_assigned.u.prefix4.s_addr) - p->u.prefix4.s_addr = zvrf->rid_user_assigned.u.prefix4.s_addr; - else if (!list_isempty (zvrf->rid_lo_sorted_list)) - { - node = listtail (zvrf->rid_lo_sorted_list); - c = listgetdata (node); - p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; - } - else if (!list_isempty (zvrf->rid_all_sorted_list)) - { - node = listtail (zvrf->rid_all_sorted_list); - c = listgetdata (node); - p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; - } + struct listnode *node; + struct connected *c; + struct zebra_vrf *zvrf = vrf_info_get(vrf_id); + + p->u.prefix4.s_addr = 0; + p->family = AF_INET; + p->prefixlen = 32; + + if (zvrf->rid_user_assigned.u.prefix4.s_addr) + p->u.prefix4.s_addr = zvrf->rid_user_assigned.u.prefix4.s_addr; + else if (!list_isempty(zvrf->rid_lo_sorted_list)) { + node = listtail(zvrf->rid_lo_sorted_list); + c = listgetdata(node); + p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; + } else if (!list_isempty(zvrf->rid_all_sorted_list)) { + node = listtail(zvrf->rid_all_sorted_list); + c = listgetdata(node); + p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; + } } -static void -router_id_set (struct prefix *p, vrf_id_t vrf_id) +static void router_id_set(struct prefix *p, vrf_id_t vrf_id) { - struct prefix p2; - struct listnode *node; - struct zserv *client; - struct zebra_vrf *zvrf; - - if (p->u.prefix4.s_addr == 0) /* unset */ - { - zvrf = vrf_info_lookup (vrf_id); - if (! zvrf) - return; - } - else /* set */ - zvrf = vrf_info_get (vrf_id); - - zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr; - - router_id_get (&p2, vrf_id); - - for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) - zsend_router_id_update (client, &p2, vrf_id); + struct prefix p2; + struct listnode *node; + struct zserv *client; + struct zebra_vrf *zvrf; + + if (p->u.prefix4.s_addr == 0) /* unset */ + { + zvrf = vrf_info_lookup(vrf_id); + if (!zvrf) + return; + } else /* set */ + zvrf = vrf_info_get(vrf_id); + + zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr; + + router_id_get(&p2, vrf_id); + + for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) + zsend_router_id_update(client, &p2, vrf_id); } -void -router_id_add_address (struct connected *ifc) +void router_id_add_address(struct connected *ifc) { - struct list *l = NULL; - struct listnode *node; - struct prefix before; - struct prefix after; - struct zserv *client; - struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id); - - if (router_id_bad_address (ifc)) - return; - - router_id_get (&before, zvrf_id (zvrf)); - - if (!strncmp (ifc->ifp->name, "lo", 2) - || !strncmp (ifc->ifp->name, "dummy", 5)) - l = zvrf->rid_lo_sorted_list; - else - l = zvrf->rid_all_sorted_list; - - if (!router_id_find_node (l, ifc)) - listnode_add_sort (l, ifc); - - router_id_get (&after, zvrf_id (zvrf)); - - if (prefix_same (&before, &after)) - return; - - for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) - zsend_router_id_update (client, &after, zvrf_id (zvrf)); + struct list *l = NULL; + struct listnode *node; + struct prefix before; + struct prefix after; + struct zserv *client; + struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id); + + if (router_id_bad_address(ifc)) + return; + + router_id_get(&before, zvrf_id(zvrf)); + + if (!strncmp(ifc->ifp->name, "lo", 2) + || !strncmp(ifc->ifp->name, "dummy", 5)) + l = zvrf->rid_lo_sorted_list; + else + l = zvrf->rid_all_sorted_list; + + if (!router_id_find_node(l, ifc)) + listnode_add_sort(l, ifc); + + router_id_get(&after, zvrf_id(zvrf)); + + if (prefix_same(&before, &after)) + return; + + for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) + zsend_router_id_update(client, &after, zvrf_id(zvrf)); } -void -router_id_del_address (struct connected *ifc) +void router_id_del_address(struct connected *ifc) { - struct connected *c; - struct list *l; - struct prefix after; - struct prefix before; - struct listnode *node; - struct zserv *client; - struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id); + struct connected *c; + struct list *l; + struct prefix after; + struct prefix before; + struct listnode *node; + struct zserv *client; + struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id); - if (router_id_bad_address (ifc)) - return; + if (router_id_bad_address(ifc)) + return; - router_id_get (&before, zvrf_id (zvrf)); + router_id_get(&before, zvrf_id(zvrf)); - if (!strncmp (ifc->ifp->name, "lo", 2) - || !strncmp (ifc->ifp->name, "dummy", 5)) - l = zvrf->rid_lo_sorted_list; - else - l = zvrf->rid_all_sorted_list; + if (!strncmp(ifc->ifp->name, "lo", 2) + || !strncmp(ifc->ifp->name, "dummy", 5)) + l = zvrf->rid_lo_sorted_list; + else + l = zvrf->rid_all_sorted_list; - if ((c = router_id_find_node (l, ifc))) - listnode_delete (l, c); + if ((c = router_id_find_node(l, ifc))) + listnode_delete(l, c); - router_id_get (&after, zvrf_id (zvrf)); + router_id_get(&after, zvrf_id(zvrf)); - if (prefix_same (&before, &after)) - return; + if (prefix_same(&before, &after)) + return; - for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) - zsend_router_id_update (client, &after, zvrf_id (zvrf)); + for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) + zsend_router_id_update(client, &after, zvrf_id(zvrf)); } -void -router_id_write (struct vty *vty) +void router_id_write(struct vty *vty) { - struct vrf *vrf; - struct zebra_vrf *zvrf; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - if (zvrf->rid_user_assigned.u.prefix4.s_addr) - { - if (zvrf_id (zvrf) == VRF_DEFAULT) - vty_out (vty, "router-id %s\n", - inet_ntoa(zvrf->rid_user_assigned.u.prefix4)); - else - vty_out (vty, "router-id %s vrf %s\n", - inet_ntoa (zvrf->rid_user_assigned.u.prefix4), - zvrf_name(zvrf)); - } + struct vrf *vrf; + struct zebra_vrf *zvrf; + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) + if (zvrf->rid_user_assigned.u.prefix4.s_addr) { + if (zvrf_id(zvrf) == VRF_DEFAULT) + vty_out(vty, "router-id %s\n", + inet_ntoa(zvrf->rid_user_assigned.u + .prefix4)); + else + vty_out(vty, "router-id %s vrf %s\n", + inet_ntoa(zvrf->rid_user_assigned.u + .prefix4), + zvrf_name(zvrf)); + } } DEFUN (router_id, @@ -218,25 +209,25 @@ DEFUN (router_id, "IP address to use for router-id\n" VRF_CMD_HELP_STR) { - int idx_ipv4 = 1; - int idx_name = 3; + int idx_ipv4 = 1; + int idx_name = 3; - struct prefix rid; - vrf_id_t vrf_id = VRF_DEFAULT; + struct prefix rid; + vrf_id_t vrf_id = VRF_DEFAULT; - rid.u.prefix4.s_addr = inet_addr (argv[idx_ipv4]->arg); - if (!rid.u.prefix4.s_addr) - return CMD_WARNING_CONFIG_FAILED; + rid.u.prefix4.s_addr = inet_addr(argv[idx_ipv4]->arg); + if (!rid.u.prefix4.s_addr) + return CMD_WARNING_CONFIG_FAILED; - rid.prefixlen = 32; - rid.family = AF_INET; + rid.prefixlen = 32; + rid.family = AF_INET; - if (argc > 2) - VRF_GET_ID (vrf_id, argv[idx_name]->arg); + if (argc > 2) + VRF_GET_ID(vrf_id, argv[idx_name]->arg); - router_id_set (&rid, vrf_id); + router_id_set(&rid, vrf_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_router_id, @@ -247,54 +238,52 @@ DEFUN (no_router_id, "IP address to use for router-id\n" VRF_CMD_HELP_STR) { - int idx_name = 4; + int idx_name = 4; - struct prefix rid; - vrf_id_t vrf_id = VRF_DEFAULT; + struct prefix rid; + vrf_id_t vrf_id = VRF_DEFAULT; - rid.u.prefix4.s_addr = 0; - rid.prefixlen = 0; - rid.family = AF_INET; + rid.u.prefix4.s_addr = 0; + rid.prefixlen = 0; + rid.family = AF_INET; - if (argc > 3) - VRF_GET_ID (vrf_id, argv[idx_name]->arg); + if (argc > 3) + VRF_GET_ID(vrf_id, argv[idx_name]->arg); - router_id_set (&rid, vrf_id); + router_id_set(&rid, vrf_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } - -static int -router_id_cmp (void *a, void *b) +static int router_id_cmp(void *a, void *b) { - const struct connected *ifa = (const struct connected *)a; - const struct connected *ifb = (const struct connected *)b; + const struct connected *ifa = (const struct connected *)a; + const struct connected *ifb = (const struct connected *)b; - return IPV4_ADDR_CMP(&ifa->address->u.prefix4.s_addr,&ifb->address->u.prefix4.s_addr); + return IPV4_ADDR_CMP(&ifa->address->u.prefix4.s_addr, + &ifb->address->u.prefix4.s_addr); } -void -router_id_cmd_init (void) +void router_id_cmd_init(void) { - install_element (CONFIG_NODE, &router_id_cmd); - install_element (CONFIG_NODE, &no_router_id_cmd); + install_element(CONFIG_NODE, &router_id_cmd); + install_element(CONFIG_NODE, &no_router_id_cmd); } -void -router_id_init (struct zebra_vrf *zvrf) +void router_id_init(struct zebra_vrf *zvrf) { - zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list; - zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list; + zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list; + zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list; - memset (zvrf->rid_all_sorted_list, 0, sizeof (zvrf->_rid_all_sorted_list)); - memset (zvrf->rid_lo_sorted_list, 0, sizeof (zvrf->_rid_lo_sorted_list)); - memset (&zvrf->rid_user_assigned, 0, sizeof (zvrf->rid_user_assigned)); + memset(zvrf->rid_all_sorted_list, 0, + sizeof(zvrf->_rid_all_sorted_list)); + memset(zvrf->rid_lo_sorted_list, 0, sizeof(zvrf->_rid_lo_sorted_list)); + memset(&zvrf->rid_user_assigned, 0, sizeof(zvrf->rid_user_assigned)); - zvrf->rid_all_sorted_list->cmp = router_id_cmp; - zvrf->rid_lo_sorted_list->cmp = router_id_cmp; + zvrf->rid_all_sorted_list->cmp = router_id_cmp; + zvrf->rid_lo_sorted_list->cmp = router_id_cmp; - zvrf->rid_user_assigned.family = AF_INET; - zvrf->rid_user_assigned.prefixlen = 32; + zvrf->rid_user_assigned.family = AF_INET; + zvrf->rid_user_assigned.prefixlen = 32; } diff --git a/zebra/rt.h b/zebra/rt.h index 90654fb3e..81dffdf44 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -30,31 +30,32 @@ #include "zebra/zebra_ns.h" #include "zebra/zebra_mpls.h" -extern int kernel_route_rib (struct prefix *, struct prefix *, - struct route_entry *, struct route_entry *); - -extern int kernel_address_add_ipv4 (struct interface *, struct connected *); -extern int kernel_address_delete_ipv4 (struct interface *, struct connected *); -extern int kernel_neigh_update (int, int, uint32_t, char *, int); - -extern int kernel_add_lsp (zebra_lsp_t *); -extern int kernel_upd_lsp (zebra_lsp_t *); -extern int kernel_del_lsp (zebra_lsp_t *); -extern int mpls_kernel_init (void); - -extern int kernel_get_ipmr_sg_stats (void *mroute); -extern int kernel_add_vtep (vni_t vni, struct interface *ifp, - struct in_addr *vtep_ip); -extern int kernel_del_vtep (vni_t vni, struct interface *ifp, - struct in_addr *vtep_ip); -extern int kernel_add_mac (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, - u_char sticky); -extern int kernel_del_mac (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, int local); - -extern int kernel_add_neigh (struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac); -extern int kernel_del_neigh (struct interface *ifp, struct ipaddr *ip); +extern int kernel_route_rib(struct prefix *, struct prefix *, + struct route_entry *, struct route_entry *); + +extern int kernel_address_add_ipv4(struct interface *, struct connected *); +extern int kernel_address_delete_ipv4(struct interface *, struct connected *); +extern int kernel_neigh_update(int, int, uint32_t, char *, int); + +extern int kernel_add_lsp(zebra_lsp_t *); +extern int kernel_upd_lsp(zebra_lsp_t *); +extern int kernel_del_lsp(zebra_lsp_t *); +extern int mpls_kernel_init(void); + +extern int kernel_get_ipmr_sg_stats(void *mroute); +extern int kernel_add_vtep(vni_t vni, struct interface *ifp, + struct in_addr *vtep_ip); +extern int kernel_del_vtep(vni_t vni, struct interface *ifp, + struct in_addr *vtep_ip); +extern int kernel_add_mac(struct interface *ifp, vlanid_t vid, + struct ethaddr *mac, struct in_addr vtep_ip, + u_char sticky); +extern int kernel_del_mac(struct interface *ifp, vlanid_t vid, + struct ethaddr *mac, struct in_addr vtep_ip, + int local); + +extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, + struct ethaddr *mac); +extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip); #endif /* _ZEBRA_RT_H */ diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index e017eb78e..c02774ca6 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -119,11 +119,10 @@ static vlanid_t filter_vlan = 0; -struct gw_family_t -{ - u_int16_t filler; - u_int16_t family; - union g_addr gate; +struct gw_family_t { + u_int16_t filler; + u_int16_t family; + union g_addr gate; }; char ipv4_ll_buf[16] = "169.254.0.1"; @@ -135,592 +134,582 @@ struct in_addr ipv4_ll; * correct value one time instead for every * install/remove of a 5549 type route */ -void -rt_netlink_init (void) +void rt_netlink_init(void) { - inet_pton (AF_INET, ipv4_ll_buf, &ipv4_ll); + inet_pton(AF_INET, ipv4_ll_buf, &ipv4_ll); } static inline int is_selfroute(int proto) { - if ((proto == RTPROT_BGP) || (proto == RTPROT_OSPF) || - (proto == RTPROT_STATIC) || (proto == RTPROT_ZEBRA) || - (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG) || - (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP) || - (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)) { - return 1; - } - - return 0; + if ((proto == RTPROT_BGP) || (proto == RTPROT_OSPF) + || (proto == RTPROT_STATIC) || (proto == RTPROT_ZEBRA) + || (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG) + || (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP) + || (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)) { + return 1; + } + + return 0; } static inline int get_rt_proto(int proto) { - switch (proto) { - case ZEBRA_ROUTE_BABEL: - proto = RTPROT_BABEL; - break; - case ZEBRA_ROUTE_BGP: - proto = RTPROT_BGP; - break; - case ZEBRA_ROUTE_OSPF: - case ZEBRA_ROUTE_OSPF6: - proto = RTPROT_OSPF; - break; - case ZEBRA_ROUTE_STATIC: - proto = RTPROT_STATIC; - break; - case ZEBRA_ROUTE_ISIS: - proto = RTPROT_ISIS; - break; - case ZEBRA_ROUTE_RIP: - proto = RTPROT_RIP; - break; - case ZEBRA_ROUTE_RIPNG: - proto = RTPROT_RIPNG; - break; - case ZEBRA_ROUTE_NHRP: - proto = RTPROT_NHRP; - break; - case ZEBRA_ROUTE_EIGRP: - proto = RTPROT_EIGRP; - break; - case ZEBRA_ROUTE_LDP: - proto = RTPROT_LDP; - break; - default: - proto = RTPROT_ZEBRA; - break; - } - - return proto; + switch (proto) { + case ZEBRA_ROUTE_BABEL: + proto = RTPROT_BABEL; + break; + case ZEBRA_ROUTE_BGP: + proto = RTPROT_BGP; + break; + case ZEBRA_ROUTE_OSPF: + case ZEBRA_ROUTE_OSPF6: + proto = RTPROT_OSPF; + break; + case ZEBRA_ROUTE_STATIC: + proto = RTPROT_STATIC; + break; + case ZEBRA_ROUTE_ISIS: + proto = RTPROT_ISIS; + break; + case ZEBRA_ROUTE_RIP: + proto = RTPROT_RIP; + break; + case ZEBRA_ROUTE_RIPNG: + proto = RTPROT_RIPNG; + break; + case ZEBRA_ROUTE_NHRP: + proto = RTPROT_NHRP; + break; + case ZEBRA_ROUTE_EIGRP: + proto = RTPROT_EIGRP; + break; + case ZEBRA_ROUTE_LDP: + proto = RTPROT_LDP; + break; + default: + proto = RTPROT_ZEBRA; + break; + } + + return proto; } /* Pending: create an efficient table_id (in a tree/hash) based lookup) */ -static vrf_id_t -vrf_lookup_by_table (u_int32_t table_id) +static vrf_id_t vrf_lookup_by_table(u_int32_t table_id) { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - { - if ((zvrf = vrf->info) == NULL || - (zvrf->table_id != table_id)) - continue; + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + { + if ((zvrf = vrf->info) == NULL || (zvrf->table_id != table_id)) + continue; - return zvrf_id (zvrf); - } + return zvrf_id(zvrf); + } - return VRF_DEFAULT; + return VRF_DEFAULT; } /* Looking up routing table by netlink interface. */ -static int -netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, + struct nlmsghdr *h, ns_id_t ns_id, + int startup) { - int len; - struct rtmsg *rtm; - struct rtattr *tb[RTA_MAX + 1]; - u_char flags = 0; - struct prefix p; - struct prefix_ipv6 src_p; - vrf_id_t vrf_id = VRF_DEFAULT; - - char anyaddr[16] = { 0 }; - - int index = 0; - int table; - int metric = 0; - u_int32_t mtu = 0; - - void *dest = NULL; - void *gate = NULL; - void *prefsrc = NULL; /* IPv4 preferred source host address */ - void *src = NULL; /* IPv6 srcdest source prefix */ - - rtm = NLMSG_DATA (h); - - if (startup && h->nlmsg_type != RTM_NEWROUTE) - return 0; - if (startup && rtm->rtm_type != RTN_UNICAST) - return 0; - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); - if (len < 0) - return -1; - - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len); - - if (rtm->rtm_flags & RTM_F_CLONED) - return 0; - if (rtm->rtm_protocol == RTPROT_REDIRECT) - return 0; - if (rtm->rtm_protocol == RTPROT_KERNEL) - return 0; - - if (!startup && - is_selfroute (rtm->rtm_protocol) && - h->nlmsg_type == RTM_NEWROUTE) - return 0; - - /* We don't care about change notifications for the MPLS table. */ - /* TODO: Revisit this. */ - if (rtm->rtm_family == AF_MPLS) - return 0; - - /* Table corresponding to route. */ - if (tb[RTA_TABLE]) - table = *(int *) RTA_DATA (tb[RTA_TABLE]); - else - table = rtm->rtm_table; - - /* Map to VRF */ - vrf_id = vrf_lookup_by_table(table); - if (vrf_id == VRF_DEFAULT) - { - if (!is_zebra_valid_kernel_table(table) && - !is_zebra_main_routing_table(table)) - return 0; - } - - /* Route which inserted by Zebra. */ - if (is_selfroute(rtm->rtm_protocol)) - flags |= ZEBRA_FLAG_SELFROUTE; - - if (tb[RTA_OIF]) - index = *(int *) RTA_DATA (tb[RTA_OIF]); - - if (tb[RTA_DST]) - dest = RTA_DATA (tb[RTA_DST]); - else - dest = anyaddr; - - if (tb[RTA_SRC]) - src = RTA_DATA (tb[RTA_SRC]); - else - src = anyaddr; - - if (tb[RTA_PREFSRC]) - prefsrc = RTA_DATA (tb[RTA_PREFSRC]); - - if (tb[RTA_GATEWAY]) - gate = RTA_DATA (tb[RTA_GATEWAY]); - - if (h->nlmsg_type == RTM_NEWROUTE) - { - if (tb[RTA_PRIORITY]) - metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); - - if (tb[RTA_METRICS]) - { - struct rtattr *mxrta[RTAX_MAX+1]; - - memset (mxrta, 0, sizeof mxrta); - netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]), - RTA_PAYLOAD(tb[RTA_METRICS])); - - if (mxrta[RTAX_MTU]) - mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]); - } - } - - if (rtm->rtm_family == AF_INET) - { - p.family = AF_INET; - memcpy (&p.u.prefix4, dest, 4); - p.prefixlen = rtm->rtm_dst_len; - - src_p.prefixlen = 0; // Forces debug below to not display anything - } - else if (rtm->rtm_family == AF_INET6) - { - p.family = AF_INET6; - memcpy (&p.u.prefix6, dest, 16); - p.prefixlen = rtm->rtm_dst_len; - - src_p.family = AF_INET6; - memcpy (&src_p.prefix, src, 16); - src_p.prefixlen = rtm->rtm_src_len; - } - - if (rtm->rtm_src_len != 0) - { - char buf[PREFIX_STRLEN]; - zlog_warn ("unsupported IPv[4|6] sourcedest route (dest %s vrf %u)", - prefix2str (&p, buf, sizeof(buf)), vrf_id); - return 0; - } - - if (IS_ZEBRA_DEBUG_KERNEL) - { - char buf[PREFIX_STRLEN]; - char buf2[PREFIX_STRLEN]; - zlog_debug ("%s %s%s%s vrf %u", - nl_msg_type_to_str (h->nlmsg_type), - prefix2str (&p, buf, sizeof(buf)), - src_p.prefixlen ? " from " : "", - src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "", - vrf_id); - } - - afi_t afi = AFI_IP; - if (rtm->rtm_family == AF_INET6) - afi = AFI_IP6; - - if (h->nlmsg_type == RTM_NEWROUTE) - { - if (!tb[RTA_MULTIPATH]) - rib_add (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, flags, &p, NULL, gate, prefsrc, index, - table, metric, mtu, 0); - else - { - /* This is a multipath route */ - - struct route_entry *re; - struct rtnexthop *rtnh = - (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]); - - len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); - - re = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - re->type = ZEBRA_ROUTE_KERNEL; - re->distance = 0; - re->flags = flags; - re->metric = metric; - re->mtu = mtu; - re->vrf_id = vrf_id; - re->table = table; - re->nexthop_num = 0; - re->uptime = time (NULL); - - for (;;) - { - if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) - break; - - index = rtnh->rtnh_ifindex; - gate = 0; - if (rtnh->rtnh_len > sizeof (*rtnh)) - { - memset (tb, 0, sizeof (tb)); - netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh), - rtnh->rtnh_len - sizeof (*rtnh)); - if (tb[RTA_GATEWAY]) - gate = RTA_DATA (tb[RTA_GATEWAY]); - } - - if (gate) - { - if (rtm->rtm_family == AF_INET) - { - if (index) - route_entry_nexthop_ipv4_ifindex_add (re, gate, prefsrc, index); - else - route_entry_nexthop_ipv4_add (re, gate, prefsrc); - } - else if (rtm->rtm_family == AF_INET6) - { - if (index) - route_entry_nexthop_ipv6_ifindex_add (re, gate, index); - else - route_entry_nexthop_ipv6_add (re,gate); - } - } - else - route_entry_nexthop_ifindex_add (re, index); - - len -= NLMSG_ALIGN(rtnh->rtnh_len); - rtnh = RTNH_NEXT(rtnh); - } - - zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, - re->nexthop_num); - if (re->nexthop_num == 0) - XFREE (MTYPE_RE, re); - else - rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, re); - } - } - else - { - if (!tb[RTA_MULTIPATH]) - rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags, - &p, NULL, gate, index, table); - else - { - struct rtnexthop *rtnh = - (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]); - - len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); - - for (;;) - { - if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) - break; - - gate = NULL; - if (rtnh->rtnh_len > sizeof (*rtnh)) - { - memset (tb, 0, sizeof (tb)); - netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh), - rtnh->rtnh_len - sizeof (*rtnh)); - if (tb[RTA_GATEWAY]) - gate = RTA_DATA (tb[RTA_GATEWAY]); - } - - if (gate) - rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags, - &p, NULL, gate, index, table); - - len -= NLMSG_ALIGN(rtnh->rtnh_len); - rtnh = RTNH_NEXT(rtnh); - } - } - } - - return 0; + int len; + struct rtmsg *rtm; + struct rtattr *tb[RTA_MAX + 1]; + u_char flags = 0; + struct prefix p; + struct prefix_ipv6 src_p; + vrf_id_t vrf_id = VRF_DEFAULT; + + char anyaddr[16] = {0}; + + int index = 0; + int table; + int metric = 0; + u_int32_t mtu = 0; + + void *dest = NULL; + void *gate = NULL; + void *prefsrc = NULL; /* IPv4 preferred source host address */ + void *src = NULL; /* IPv6 srcdest source prefix */ + + rtm = NLMSG_DATA(h); + + if (startup && h->nlmsg_type != RTM_NEWROUTE) + return 0; + if (startup && rtm->rtm_type != RTN_UNICAST) + return 0; + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg)); + if (len < 0) + return -1; + + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len); + + if (rtm->rtm_flags & RTM_F_CLONED) + return 0; + if (rtm->rtm_protocol == RTPROT_REDIRECT) + return 0; + if (rtm->rtm_protocol == RTPROT_KERNEL) + return 0; + + if (!startup && is_selfroute(rtm->rtm_protocol) + && h->nlmsg_type == RTM_NEWROUTE) + return 0; + + /* We don't care about change notifications for the MPLS table. */ + /* TODO: Revisit this. */ + if (rtm->rtm_family == AF_MPLS) + return 0; + + /* Table corresponding to route. */ + if (tb[RTA_TABLE]) + table = *(int *)RTA_DATA(tb[RTA_TABLE]); + else + table = rtm->rtm_table; + + /* Map to VRF */ + vrf_id = vrf_lookup_by_table(table); + if (vrf_id == VRF_DEFAULT) { + if (!is_zebra_valid_kernel_table(table) + && !is_zebra_main_routing_table(table)) + return 0; + } + + /* Route which inserted by Zebra. */ + if (is_selfroute(rtm->rtm_protocol)) + flags |= ZEBRA_FLAG_SELFROUTE; + + if (tb[RTA_OIF]) + index = *(int *)RTA_DATA(tb[RTA_OIF]); + + if (tb[RTA_DST]) + dest = RTA_DATA(tb[RTA_DST]); + else + dest = anyaddr; + + if (tb[RTA_SRC]) + src = RTA_DATA(tb[RTA_SRC]); + else + src = anyaddr; + + if (tb[RTA_PREFSRC]) + prefsrc = RTA_DATA(tb[RTA_PREFSRC]); + + if (tb[RTA_GATEWAY]) + gate = RTA_DATA(tb[RTA_GATEWAY]); + + if (h->nlmsg_type == RTM_NEWROUTE) { + if (tb[RTA_PRIORITY]) + metric = *(int *)RTA_DATA(tb[RTA_PRIORITY]); + + if (tb[RTA_METRICS]) { + struct rtattr *mxrta[RTAX_MAX + 1]; + + memset(mxrta, 0, sizeof mxrta); + netlink_parse_rtattr(mxrta, RTAX_MAX, + RTA_DATA(tb[RTA_METRICS]), + RTA_PAYLOAD(tb[RTA_METRICS])); + + if (mxrta[RTAX_MTU]) + mtu = *(u_int32_t *)RTA_DATA(mxrta[RTAX_MTU]); + } + } + + if (rtm->rtm_family == AF_INET) { + p.family = AF_INET; + memcpy(&p.u.prefix4, dest, 4); + p.prefixlen = rtm->rtm_dst_len; + + src_p.prefixlen = + 0; // Forces debug below to not display anything + } else if (rtm->rtm_family == AF_INET6) { + p.family = AF_INET6; + memcpy(&p.u.prefix6, dest, 16); + p.prefixlen = rtm->rtm_dst_len; + + src_p.family = AF_INET6; + memcpy(&src_p.prefix, src, 16); + src_p.prefixlen = rtm->rtm_src_len; + } + + if (rtm->rtm_src_len != 0) { + char buf[PREFIX_STRLEN]; + zlog_warn( + "unsupported IPv[4|6] sourcedest route (dest %s vrf %u)", + prefix2str(&p, buf, sizeof(buf)), vrf_id); + return 0; + } + + if (IS_ZEBRA_DEBUG_KERNEL) { + char buf[PREFIX_STRLEN]; + char buf2[PREFIX_STRLEN]; + zlog_debug( + "%s %s%s%s vrf %u", nl_msg_type_to_str(h->nlmsg_type), + prefix2str(&p, buf, sizeof(buf)), + src_p.prefixlen ? " from " : "", + src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) + : "", + vrf_id); + } + + afi_t afi = AFI_IP; + if (rtm->rtm_family == AF_INET6) + afi = AFI_IP6; + + if (h->nlmsg_type == RTM_NEWROUTE) { + if (!tb[RTA_MULTIPATH]) + rib_add(afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, flags, &p, NULL, gate, prefsrc, index, table, + metric, mtu, 0); + else { + /* This is a multipath route */ + + struct route_entry *re; + struct rtnexthop *rtnh = + (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); + + len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); + + re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + re->type = ZEBRA_ROUTE_KERNEL; + re->distance = 0; + re->flags = flags; + re->metric = metric; + re->mtu = mtu; + re->vrf_id = vrf_id; + re->table = table; + re->nexthop_num = 0; + re->uptime = time(NULL); + + for (;;) { + if (len < (int)sizeof(*rtnh) + || rtnh->rtnh_len > len) + break; + + index = rtnh->rtnh_ifindex; + gate = 0; + if (rtnh->rtnh_len > sizeof(*rtnh)) { + memset(tb, 0, sizeof(tb)); + netlink_parse_rtattr( + tb, RTA_MAX, RTNH_DATA(rtnh), + rtnh->rtnh_len - sizeof(*rtnh)); + if (tb[RTA_GATEWAY]) + gate = RTA_DATA( + tb[RTA_GATEWAY]); + } + + if (gate) { + if (rtm->rtm_family == AF_INET) { + if (index) + route_entry_nexthop_ipv4_ifindex_add( + re, gate, + prefsrc, index); + else + route_entry_nexthop_ipv4_add( + re, gate, + prefsrc); + } else if (rtm->rtm_family + == AF_INET6) { + if (index) + route_entry_nexthop_ipv6_ifindex_add( + re, gate, + index); + else + route_entry_nexthop_ipv6_add( + re, gate); + } + } else + route_entry_nexthop_ifindex_add(re, + index); + + len -= NLMSG_ALIGN(rtnh->rtnh_len); + rtnh = RTNH_NEXT(rtnh); + } + + zserv_nexthop_num_warn(__func__, + (const struct prefix *)&p, + re->nexthop_num); + if (re->nexthop_num == 0) + XFREE(MTYPE_RE, re); + else + rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, + NULL, re); + } + } else { + if (!tb[RTA_MULTIPATH]) + rib_delete(afi, SAFI_UNICAST, vrf_id, + ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, gate, + index, table); + else { + struct rtnexthop *rtnh = + (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); + + len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); + + for (;;) { + if (len < (int)sizeof(*rtnh) + || rtnh->rtnh_len > len) + break; + + gate = NULL; + if (rtnh->rtnh_len > sizeof(*rtnh)) { + memset(tb, 0, sizeof(tb)); + netlink_parse_rtattr( + tb, RTA_MAX, RTNH_DATA(rtnh), + rtnh->rtnh_len - sizeof(*rtnh)); + if (tb[RTA_GATEWAY]) + gate = RTA_DATA( + tb[RTA_GATEWAY]); + } + + if (gate) + rib_delete(afi, SAFI_UNICAST, vrf_id, + ZEBRA_ROUTE_KERNEL, 0, flags, + &p, NULL, gate, index, + table); + + len -= NLMSG_ALIGN(rtnh->rtnh_len); + rtnh = RTNH_NEXT(rtnh); + } + } + } + + return 0; } static struct mcast_route_data *mroute = NULL; -static int -netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +static int netlink_route_change_read_multicast(struct sockaddr_nl *snl, + struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct rtmsg *rtm; - struct rtattr *tb[RTA_MAX + 1]; - struct mcast_route_data *m; - struct mcast_route_data mr; - int iif = 0; - int count; - int oif[256]; - int oif_count = 0; - char sbuf[40]; - char gbuf[40]; - char oif_list[256] = "\0"; - vrf_id_t vrf = ns_id; - - if (mroute) - m = mroute; - else - { - memset (&mr, 0, sizeof (mr)); - m = &mr; - } - - rtm = NLMSG_DATA (h); - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); - - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len); - - if (tb[RTA_IIF]) - iif = *(int *)RTA_DATA (tb[RTA_IIF]); - - if (tb[RTA_SRC]) - m->sg.src = *(struct in_addr *)RTA_DATA (tb[RTA_SRC]); - - if (tb[RTA_DST]) - m->sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]); - - if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES]) - m->lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]); - - if (tb[RTA_MULTIPATH]) - { - struct rtnexthop *rtnh = - (struct rtnexthop *)RTA_DATA (tb[RTA_MULTIPATH]); - - len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); - for (;;) - { - if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) - break; - - oif[oif_count] = rtnh->rtnh_ifindex; - oif_count++; - - len -= NLMSG_ALIGN (rtnh->rtnh_len); - rtnh = RTNH_NEXT (rtnh); - } - } - - if (IS_ZEBRA_DEBUG_KERNEL) - { - struct interface *ifp; - strcpy (sbuf, inet_ntoa (m->sg.src)); - strcpy (gbuf, inet_ntoa (m->sg.grp)); - for (count = 0; count < oif_count; count++) - { - ifp = if_lookup_by_index (oif[count], vrf); - char temp[256]; + int len; + struct rtmsg *rtm; + struct rtattr *tb[RTA_MAX + 1]; + struct mcast_route_data *m; + struct mcast_route_data mr; + int iif = 0; + int count; + int oif[256]; + int oif_count = 0; + char sbuf[40]; + char gbuf[40]; + char oif_list[256] = "\0"; + vrf_id_t vrf = ns_id; + + if (mroute) + m = mroute; + else { + memset(&mr, 0, sizeof(mr)); + m = &mr; + } + + rtm = NLMSG_DATA(h); + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg)); + + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len); - sprintf (temp, "%s ", ifp->name); - strcat (oif_list, temp); + if (tb[RTA_IIF]) + iif = *(int *)RTA_DATA(tb[RTA_IIF]); + + if (tb[RTA_SRC]) + m->sg.src = *(struct in_addr *)RTA_DATA(tb[RTA_SRC]); + + if (tb[RTA_DST]) + m->sg.grp = *(struct in_addr *)RTA_DATA(tb[RTA_DST]); + + if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES]) + m->lastused = *(unsigned long long *)RTA_DATA(tb[RTA_EXPIRES]); + + if (tb[RTA_MULTIPATH]) { + struct rtnexthop *rtnh = + (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); + + len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); + for (;;) { + if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len) + break; + + oif[oif_count] = rtnh->rtnh_ifindex; + oif_count++; + + len -= NLMSG_ALIGN(rtnh->rtnh_len); + rtnh = RTNH_NEXT(rtnh); + } + } + + if (IS_ZEBRA_DEBUG_KERNEL) { + struct interface *ifp; + strcpy(sbuf, inet_ntoa(m->sg.src)); + strcpy(gbuf, inet_ntoa(m->sg.grp)); + for (count = 0; count < oif_count; count++) { + ifp = if_lookup_by_index(oif[count], vrf); + char temp[256]; + + sprintf(temp, "%s ", ifp->name); + strcat(oif_list, temp); + } + ifp = if_lookup_by_index(iif, vrf); + zlog_debug("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld", + nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf, + ifp->name, oif_list, m->lastused); } - ifp = if_lookup_by_index (iif, vrf); - zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld", - nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf, ifp->name, oif_list, m->lastused); - } - return 0; + return 0; } -int -netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +int netlink_route_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - vrf_id_t vrf_id = ns_id; - struct rtmsg *rtm; - - rtm = NLMSG_DATA (h); - - if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) - { - /* If this is not route add/delete message print warning. */ - zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id); - return 0; - } - - /* Connected route. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s %s %s proto %s vrf %u", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (rtm->rtm_family), - nl_rttype_to_str (rtm->rtm_type), - nl_rtproto_to_str (rtm->rtm_protocol), - vrf_id); - - /* We don't care about change notifications for the MPLS table. */ - /* TODO: Revisit this. */ - if (rtm->rtm_family == AF_MPLS) - return 0; - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); - if (len < 0) - return -1; - - switch (rtm->rtm_type) - { - case RTN_UNICAST: - netlink_route_change_read_unicast (snl, h, ns_id, startup); - break; - case RTN_MULTICAST: - netlink_route_change_read_multicast (snl, h, ns_id, startup); - break; - default: - return 0; - break; - } - - return 0; + int len; + vrf_id_t vrf_id = ns_id; + struct rtmsg *rtm; + + rtm = NLMSG_DATA(h); + + if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) { + /* If this is not route add/delete message print warning. */ + zlog_warn("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id); + return 0; + } + + /* Connected route. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s %s %s proto %s vrf %u", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(rtm->rtm_family), + nl_rttype_to_str(rtm->rtm_type), + nl_rtproto_to_str(rtm->rtm_protocol), vrf_id); + + /* We don't care about change notifications for the MPLS table. */ + /* TODO: Revisit this. */ + if (rtm->rtm_family == AF_MPLS) + return 0; + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg)); + if (len < 0) + return -1; + + switch (rtm->rtm_type) { + case RTN_UNICAST: + netlink_route_change_read_unicast(snl, h, ns_id, startup); + break; + case RTN_MULTICAST: + netlink_route_change_read_multicast(snl, h, ns_id, startup); + break; + default: + return 0; + break; + } + + return 0; } /* Request for specific route information from the kernel */ -static int -netlink_request_route (struct zebra_ns *zns, int family, int type) +static int netlink_request_route(struct zebra_ns *zns, int family, int type) { - struct - { - struct nlmsghdr n; - struct rtmsg rtm; - } req; - - /* Form the request, specifying filter (rtattr) if needed. */ - memset (&req, 0, sizeof (req)); - req.n.nlmsg_type = type; - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); - req.rtm.rtm_family = family; - - return netlink_request (&zns->netlink_cmd, &req.n); + struct { + struct nlmsghdr n; + struct rtmsg rtm; + } req; + + /* Form the request, specifying filter (rtattr) if needed. */ + memset(&req, 0, sizeof(req)); + req.n.nlmsg_type = type; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + req.rtm.rtm_family = family; + + return netlink_request(&zns->netlink_cmd, &req.n); } /* Routing table read function using netlink interface. Only called bootstrap time. */ -int -netlink_route_read (struct zebra_ns *zns) +int netlink_route_read(struct zebra_ns *zns) { - int ret; - - /* Get IPv4 routing table. */ - ret = netlink_request_route (zns, AF_INET, RTM_GETROUTE); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1); - if (ret < 0) - return ret; - - /* Get IPv6 routing table. */ - ret = netlink_request_route (zns, AF_INET6, RTM_GETROUTE); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1); - if (ret < 0) - return ret; - - return 0; + int ret; + + /* Get IPv4 routing table. */ + ret = netlink_request_route(zns, AF_INET, RTM_GETROUTE); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_route_change_read_unicast, + &zns->netlink_cmd, zns, 0, 1); + if (ret < 0) + return ret; + + /* Get IPv6 routing table. */ + ret = netlink_request_route(zns, AF_INET6, RTM_GETROUTE); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_route_change_read_unicast, + &zns->netlink_cmd, zns, 0, 1); + if (ret < 0) + return ret; + + return 0; } -static void -_netlink_route_nl_add_gateway_info (u_char route_family, u_char gw_family, - struct nlmsghdr *nlmsg, - size_t req_size, int bytelen, - struct nexthop *nexthop) +static void _netlink_route_nl_add_gateway_info(u_char route_family, + u_char gw_family, + struct nlmsghdr *nlmsg, + size_t req_size, int bytelen, + struct nexthop *nexthop) { - if (route_family == AF_MPLS) - { - struct gw_family_t gw_fam; - - gw_fam.family = gw_family; - if (gw_family == AF_INET) - memcpy (&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen); - else - memcpy (&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen); - addattr_l (nlmsg, req_size, RTA_VIA, &gw_fam.family, bytelen+2); - } - else - { - if (gw_family == AF_INET) - addattr_l (nlmsg, req_size, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen); - else - addattr_l (nlmsg, req_size, RTA_GATEWAY, &nexthop->gate.ipv6, bytelen); - } + if (route_family == AF_MPLS) { + struct gw_family_t gw_fam; + + gw_fam.family = gw_family; + if (gw_family == AF_INET) + memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen); + else + memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen); + addattr_l(nlmsg, req_size, RTA_VIA, &gw_fam.family, + bytelen + 2); + } else { + if (gw_family == AF_INET) + addattr_l(nlmsg, req_size, RTA_GATEWAY, + &nexthop->gate.ipv4, bytelen); + else + addattr_l(nlmsg, req_size, RTA_GATEWAY, + &nexthop->gate.ipv6, bytelen); + } } -static void -_netlink_route_rta_add_gateway_info (u_char route_family, u_char gw_family, - struct rtattr *rta, struct rtnexthop *rtnh, - size_t req_size, int bytelen, - struct nexthop *nexthop) +static void _netlink_route_rta_add_gateway_info(u_char route_family, + u_char gw_family, + struct rtattr *rta, + struct rtnexthop *rtnh, + size_t req_size, int bytelen, + struct nexthop *nexthop) { - if (route_family == AF_MPLS) - { - struct gw_family_t gw_fam; - - gw_fam.family = gw_family; - if (gw_family == AF_INET) - memcpy (&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen); - else - memcpy (&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen); - rta_addattr_l (rta, req_size, RTA_VIA, &gw_fam.family, bytelen+2); - rtnh->rtnh_len += RTA_LENGTH (bytelen + 2); - } - else - { - if (gw_family == AF_INET) - rta_addattr_l (rta, req_size, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen); - else - rta_addattr_l (rta, req_size, RTA_GATEWAY, &nexthop->gate.ipv6, bytelen); - rtnh->rtnh_len += sizeof (struct rtattr) + bytelen; - } + if (route_family == AF_MPLS) { + struct gw_family_t gw_fam; + + gw_fam.family = gw_family; + if (gw_family == AF_INET) + memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen); + else + memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen); + rta_addattr_l(rta, req_size, RTA_VIA, &gw_fam.family, + bytelen + 2); + rtnh->rtnh_len += RTA_LENGTH(bytelen + 2); + } else { + if (gw_family == AF_INET) + rta_addattr_l(rta, req_size, RTA_GATEWAY, + &nexthop->gate.ipv4, bytelen); + else + rta_addattr_l(rta, req_size, RTA_GATEWAY, + &nexthop->gate.ipv6, bytelen); + rtnh->rtnh_len += sizeof(struct rtattr) + bytelen; + } } /* This function takes a nexthop as argument and adds @@ -734,194 +723,186 @@ _netlink_route_rta_add_gateway_info (u_char route_family, u_char gw_family, * @param nlmsg: nlmsghdr structure to fill in. * @param req_size: The size allocated for the message. */ -static void -_netlink_route_build_singlepath( - const char *routedesc, - int bytelen, - struct nexthop *nexthop, - struct nlmsghdr *nlmsg, - struct rtmsg *rtmsg, - size_t req_size, - int cmd) +static void _netlink_route_build_singlepath(const char *routedesc, int bytelen, + struct nexthop *nexthop, + struct nlmsghdr *nlmsg, + struct rtmsg *rtmsg, + size_t req_size, int cmd) { - struct nexthop_label *nh_label; - mpls_lse_t out_lse[MPLS_MAX_LABELS]; - char label_buf[100]; - - /* - * label_buf is *only* currently used within debugging. - * As such when we assign it we are guarding it inside - * a debug test. If you want to change this make sure - * you fix this assumption - */ - label_buf[0] = '\0'; - /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP - * (in the case of LER) - */ - nh_label = nexthop->nh_label; - if (rtmsg->rtm_family == AF_MPLS) - { - assert (nh_label); - assert (nh_label->num_labels == 1); - } - - if (nh_label && nh_label->num_labels) - { - int i, num_labels = 0; - u_int32_t bos; - char label_buf1[20]; - - for (i = 0; i < nh_label->num_labels; i++) - { - if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) - { - bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0); - out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos); - if (IS_ZEBRA_DEBUG_KERNEL) - { - if (!num_labels) - sprintf (label_buf, "label %d", nh_label->label[i]); - else - { - sprintf (label_buf1, "/%d", nh_label->label[i]); - strcat (label_buf, label_buf1); - } + struct nexthop_label *nh_label; + mpls_lse_t out_lse[MPLS_MAX_LABELS]; + char label_buf[100]; + + /* + * label_buf is *only* currently used within debugging. + * As such when we assign it we are guarding it inside + * a debug test. If you want to change this make sure + * you fix this assumption + */ + label_buf[0] = '\0'; + /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP + * (in the case of LER) + */ + nh_label = nexthop->nh_label; + if (rtmsg->rtm_family == AF_MPLS) { + assert(nh_label); + assert(nh_label->num_labels == 1); + } + + if (nh_label && nh_label->num_labels) { + int i, num_labels = 0; + u_int32_t bos; + char label_buf1[20]; + + for (i = 0; i < nh_label->num_labels; i++) { + if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) { + bos = ((i == (nh_label->num_labels - 1)) ? 1 + : 0); + out_lse[i] = mpls_lse_encode(nh_label->label[i], + 0, 0, bos); + if (IS_ZEBRA_DEBUG_KERNEL) { + if (!num_labels) + sprintf(label_buf, "label %d", + nh_label->label[i]); + else { + sprintf(label_buf1, "/%d", + nh_label->label[i]); + strcat(label_buf, label_buf1); + } + } + num_labels++; + } + } + if (num_labels) { + if (rtmsg->rtm_family == AF_MPLS) + addattr_l(nlmsg, req_size, RTA_NEWDST, &out_lse, + num_labels * sizeof(mpls_lse_t)); + else { + struct rtattr *nest; + u_int16_t encap = LWTUNNEL_ENCAP_MPLS; + + addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE, + &encap, sizeof(u_int16_t)); + nest = addattr_nest(nlmsg, req_size, RTA_ENCAP); + addattr_l(nlmsg, req_size, MPLS_IPTUNNEL_DST, + &out_lse, + num_labels * sizeof(mpls_lse_t)); + addattr_nest_end(nlmsg, nest); + } } - num_labels++; - } - } - if (num_labels) - { - if (rtmsg->rtm_family == AF_MPLS) - addattr_l (nlmsg, req_size, RTA_NEWDST, - &out_lse, num_labels * sizeof(mpls_lse_t)); - else - { - struct rtattr *nest; - u_int16_t encap = LWTUNNEL_ENCAP_MPLS; - - addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE, - &encap, sizeof (u_int16_t)); - nest = addattr_nest(nlmsg, req_size, RTA_ENCAP); - addattr_l (nlmsg, req_size, MPLS_IPTUNNEL_DST, - &out_lse, num_labels * sizeof(mpls_lse_t)); - addattr_nest_end(nlmsg, nest); - } - } - } - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) - rtmsg->rtm_flags |= RTNH_F_ONLINK; - - if (rtmsg->rtm_family == AF_INET && - (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) - { - rtmsg->rtm_flags |= RTNH_F_ONLINK; - addattr_l (nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4); - addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex); - - if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->rmap_src.ipv4, bytelen); - else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->src.ipv4, bytelen); - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): " - "nexthop via %s %s if %u", - routedesc, ipv4_ll_buf, label_buf, nexthop->ifindex); - return; - } - - if (nexthop->type == NEXTHOP_TYPE_IPV4 - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - /* Send deletes to the kernel without specifying the next-hop */ - if (cmd != RTM_DELROUTE) - _netlink_route_nl_add_gateway_info (rtmsg->rtm_family, AF_INET, nlmsg, - req_size, bytelen, nexthop); - - if (cmd == RTM_NEWROUTE) - { - if (nexthop->rmap_src.ipv4.s_addr) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->rmap_src.ipv4, bytelen); - else if (nexthop->src.ipv4.s_addr) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->src.ipv4, bytelen); } - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via %s %s if %u", - routedesc, - inet_ntoa (nexthop->gate.ipv4), - label_buf, nexthop->ifindex); - } - - if (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - _netlink_route_nl_add_gateway_info (rtmsg->rtm_family, AF_INET6, nlmsg, - req_size, bytelen, nexthop); - - if (cmd == RTM_NEWROUTE) - { - if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->rmap_src.ipv6, bytelen); - else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->src.ipv6, bytelen); + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) + rtmsg->rtm_flags |= RTNH_F_ONLINK; + + if (rtmsg->rtm_family == AF_INET + && (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) { + rtmsg->rtm_flags |= RTNH_F_ONLINK; + addattr_l(nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4); + addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex); + + if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->rmap_src.ipv4, bytelen); + else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + " 5549: _netlink_route_build_singlepath() (%s): " + "nexthop via %s %s if %u", + routedesc, ipv4_ll_buf, label_buf, + nexthop->ifindex); + return; } - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via %s %s if %u", - routedesc, - inet6_ntoa (nexthop->gate.ipv6), - label_buf, nexthop->ifindex); - } - if (nexthop->type == NEXTHOP_TYPE_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex); - - if (cmd == RTM_NEWROUTE) - { - if (nexthop->rmap_src.ipv4.s_addr) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->rmap_src.ipv4, bytelen); - else if (nexthop->src.ipv4.s_addr) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->src.ipv4, bytelen); + if (nexthop->type == NEXTHOP_TYPE_IPV4 + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + /* Send deletes to the kernel without specifying the next-hop */ + if (cmd != RTM_DELROUTE) + _netlink_route_nl_add_gateway_info( + rtmsg->rtm_family, AF_INET, nlmsg, req_size, + bytelen, nexthop); + + if (cmd == RTM_NEWROUTE) { + if (nexthop->rmap_src.ipv4.s_addr) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->rmap_src.ipv4, bytelen); + else if (nexthop->src.ipv4.s_addr) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); + } + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via %s %s if %u", + routedesc, inet_ntoa(nexthop->gate.ipv4), + label_buf, nexthop->ifindex); } - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via if %u", routedesc, nexthop->ifindex); - } + if (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + _netlink_route_nl_add_gateway_info(rtmsg->rtm_family, AF_INET6, + nlmsg, req_size, bytelen, + nexthop); + + if (cmd == RTM_NEWROUTE) { + if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->rmap_src.ipv6, bytelen); + else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->src.ipv6, bytelen); + } - if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via %s %s if %u", + routedesc, inet6_ntoa(nexthop->gate.ipv6), + label_buf, nexthop->ifindex); + } + if (nexthop->type == NEXTHOP_TYPE_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex); + + if (cmd == RTM_NEWROUTE) { + if (nexthop->rmap_src.ipv4.s_addr) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->rmap_src.ipv4, bytelen); + else if (nexthop->src.ipv4.s_addr) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); + } - if (cmd == RTM_NEWROUTE) - { - if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->rmap_src.ipv6, bytelen); - else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->src.ipv6, bytelen); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via if %u", + routedesc, nexthop->ifindex); } - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via if %u", routedesc, nexthop->ifindex); - } + if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex); + + if (cmd == RTM_NEWROUTE) { + if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->rmap_src.ipv6, bytelen); + else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->src.ipv6, bytelen); + } + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via if %u", + routedesc, nexthop->ifindex); + } } /* This function takes a nexthop as argument and @@ -940,217 +921,206 @@ _netlink_route_build_singlepath( * @param src: pointer pointing to a location where * the prefsrc should be stored. */ -static void -_netlink_route_build_multipath( - const char *routedesc, - int bytelen, - struct nexthop *nexthop, - struct rtattr *rta, - struct rtnexthop *rtnh, - struct rtmsg *rtmsg, - union g_addr **src) +static void _netlink_route_build_multipath(const char *routedesc, int bytelen, + struct nexthop *nexthop, + struct rtattr *rta, + struct rtnexthop *rtnh, + struct rtmsg *rtmsg, + union g_addr **src) { - struct nexthop_label *nh_label; - mpls_lse_t out_lse[MPLS_MAX_LABELS]; - char label_buf[100]; - - rtnh->rtnh_len = sizeof (*rtnh); - rtnh->rtnh_flags = 0; - rtnh->rtnh_hops = 0; - rta->rta_len += rtnh->rtnh_len; - - /* - * label_buf is *only* currently used within debugging. - * As such when we assign it we are guarding it inside - * a debug test. If you want to change this make sure - * you fix this assumption - */ - label_buf[0] = '\0'; - /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP - * (in the case of LER) - */ - nh_label = nexthop->nh_label; - if (rtmsg->rtm_family == AF_MPLS) - { - assert (nh_label); - assert (nh_label->num_labels == 1); - } - - if (nh_label && nh_label->num_labels) - { - int i, num_labels = 0; - u_int32_t bos; - char label_buf1[20]; - - for (i = 0; i < nh_label->num_labels; i++) - { - if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) - { - bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0); - out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos); - if (IS_ZEBRA_DEBUG_KERNEL) - { - if (!num_labels) - sprintf (label_buf, "label %d", nh_label->label[i]); - else - { - sprintf (label_buf1, "/%d", nh_label->label[i]); - strcat (label_buf, label_buf1); - } + struct nexthop_label *nh_label; + mpls_lse_t out_lse[MPLS_MAX_LABELS]; + char label_buf[100]; + + rtnh->rtnh_len = sizeof(*rtnh); + rtnh->rtnh_flags = 0; + rtnh->rtnh_hops = 0; + rta->rta_len += rtnh->rtnh_len; + + /* + * label_buf is *only* currently used within debugging. + * As such when we assign it we are guarding it inside + * a debug test. If you want to change this make sure + * you fix this assumption + */ + label_buf[0] = '\0'; + /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP + * (in the case of LER) + */ + nh_label = nexthop->nh_label; + if (rtmsg->rtm_family == AF_MPLS) { + assert(nh_label); + assert(nh_label->num_labels == 1); + } + + if (nh_label && nh_label->num_labels) { + int i, num_labels = 0; + u_int32_t bos; + char label_buf1[20]; + + for (i = 0; i < nh_label->num_labels; i++) { + if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) { + bos = ((i == (nh_label->num_labels - 1)) ? 1 + : 0); + out_lse[i] = mpls_lse_encode(nh_label->label[i], + 0, 0, bos); + if (IS_ZEBRA_DEBUG_KERNEL) { + if (!num_labels) + sprintf(label_buf, "label %d", + nh_label->label[i]); + else { + sprintf(label_buf1, "/%d", + nh_label->label[i]); + strcat(label_buf, label_buf1); + } + } + num_labels++; + } + } + if (num_labels) { + if (rtmsg->rtm_family == AF_MPLS) { + rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_NEWDST, + &out_lse, + num_labels * sizeof(mpls_lse_t)); + rtnh->rtnh_len += RTA_LENGTH( + num_labels * sizeof(mpls_lse_t)); + } else { + struct rtattr *nest; + u_int16_t encap = LWTUNNEL_ENCAP_MPLS; + int len = rta->rta_len; + + rta_addattr_l(rta, NL_PKT_BUF_SIZE, + RTA_ENCAP_TYPE, &encap, + sizeof(u_int16_t)); + nest = rta_nest(rta, NL_PKT_BUF_SIZE, + RTA_ENCAP); + rta_addattr_l(rta, NL_PKT_BUF_SIZE, + MPLS_IPTUNNEL_DST, &out_lse, + num_labels * sizeof(mpls_lse_t)); + rta_nest_end(rta, nest); + rtnh->rtnh_len += rta->rta_len - len; + } } - num_labels++; - } - } - if (num_labels) - { - if (rtmsg->rtm_family == AF_MPLS) - { - rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_NEWDST, - &out_lse, num_labels * sizeof(mpls_lse_t)); - rtnh->rtnh_len += RTA_LENGTH (num_labels * sizeof(mpls_lse_t)); - } - else - { - struct rtattr *nest; - u_int16_t encap = LWTUNNEL_ENCAP_MPLS; - int len = rta->rta_len; - - rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_ENCAP_TYPE, - &encap, sizeof (u_int16_t)); - nest = rta_nest(rta, NL_PKT_BUF_SIZE, RTA_ENCAP); - rta_addattr_l (rta, NL_PKT_BUF_SIZE, MPLS_IPTUNNEL_DST, - &out_lse, num_labels * sizeof(mpls_lse_t)); - rta_nest_end(rta, nest); - rtnh->rtnh_len += rta->rta_len - len; - } - } - } - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) - rtnh->rtnh_flags |= RTNH_F_ONLINK; - - if (rtmsg->rtm_family == AF_INET && - (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) - { - bytelen = 4; - rtnh->rtnh_flags |= RTNH_F_ONLINK; - rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY, - &ipv4_ll, bytelen); - rtnh->rtnh_len += sizeof (struct rtattr) + bytelen; - rtnh->rtnh_ifindex = nexthop->ifindex; - - if (nexthop->rmap_src.ipv4.s_addr) - *src = &nexthop->rmap_src; - else if (nexthop->src.ipv4.s_addr) - *src = &nexthop->src; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug(" 5549: netlink_route_build_multipath() (%s): " - "nexthop via %s %s if %u", - routedesc, ipv4_ll_buf, label_buf, nexthop->ifindex); - return; - } - - if (nexthop->type == NEXTHOP_TYPE_IPV4 - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - _netlink_route_rta_add_gateway_info (rtmsg->rtm_family, AF_INET, rta, - rtnh, NL_PKT_BUF_SIZE, bytelen, nexthop); - if (nexthop->rmap_src.ipv4.s_addr) - *src = &nexthop->rmap_src; - else if (nexthop->src.ipv4.s_addr) - *src = &nexthop->src; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via %s %s if %u", - routedesc, - inet_ntoa (nexthop->gate.ipv4), - label_buf, nexthop->ifindex); - } - if (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - _netlink_route_rta_add_gateway_info (rtmsg->rtm_family, AF_INET6, rta, - rtnh, NL_PKT_BUF_SIZE, bytelen, nexthop); - - if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) - *src = &nexthop->rmap_src; - else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) - *src = &nexthop->src; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via %s %s if %u", - routedesc, - inet6_ntoa (nexthop->gate.ipv6), - label_buf, nexthop->ifindex); - } - /* ifindex */ - if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IFINDEX) - { - rtnh->rtnh_ifindex = nexthop->ifindex; - - if (nexthop->rmap_src.ipv4.s_addr) - *src = &nexthop->rmap_src; - else if (nexthop->src.ipv4.s_addr) - *src = &nexthop->src; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via if %u", routedesc, nexthop->ifindex); - } - else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - rtnh->rtnh_ifindex = nexthop->ifindex; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via if %u", routedesc, nexthop->ifindex); - } - else - { - rtnh->rtnh_ifindex = 0; - } + } + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) + rtnh->rtnh_flags |= RTNH_F_ONLINK; + + if (rtmsg->rtm_family == AF_INET + && (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) { + bytelen = 4; + rtnh->rtnh_flags |= RTNH_F_ONLINK; + rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_GATEWAY, &ipv4_ll, + bytelen); + rtnh->rtnh_len += sizeof(struct rtattr) + bytelen; + rtnh->rtnh_ifindex = nexthop->ifindex; + + if (nexthop->rmap_src.ipv4.s_addr) + *src = &nexthop->rmap_src; + else if (nexthop->src.ipv4.s_addr) + *src = &nexthop->src; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + " 5549: netlink_route_build_multipath() (%s): " + "nexthop via %s %s if %u", + routedesc, ipv4_ll_buf, label_buf, + nexthop->ifindex); + return; + } + + if (nexthop->type == NEXTHOP_TYPE_IPV4 + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET, + rta, rtnh, NL_PKT_BUF_SIZE, + bytelen, nexthop); + if (nexthop->rmap_src.ipv4.s_addr) + *src = &nexthop->rmap_src; + else if (nexthop->src.ipv4.s_addr) + *src = &nexthop->src; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via %s %s if %u", + routedesc, inet_ntoa(nexthop->gate.ipv4), + label_buf, nexthop->ifindex); + } + if (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET6, + rta, rtnh, NL_PKT_BUF_SIZE, + bytelen, nexthop); + + if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) + *src = &nexthop->rmap_src; + else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) + *src = &nexthop->src; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via %s %s if %u", + routedesc, inet6_ntoa(nexthop->gate.ipv6), + label_buf, nexthop->ifindex); + } + /* ifindex */ + if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IFINDEX) { + rtnh->rtnh_ifindex = nexthop->ifindex; + + if (nexthop->rmap_src.ipv4.s_addr) + *src = &nexthop->rmap_src; + else if (nexthop->src.ipv4.s_addr) + *src = &nexthop->src; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via if %u", + routedesc, nexthop->ifindex); + } else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + rtnh->rtnh_ifindex = nexthop->ifindex; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via if %u", + routedesc, nexthop->ifindex); + } else { + rtnh->rtnh_ifindex = 0; + } } -static inline void -_netlink_mpls_build_singlepath( - const char *routedesc, - zebra_nhlfe_t *nhlfe, - struct nlmsghdr *nlmsg, - struct rtmsg *rtmsg, - size_t req_size, - int cmd) +static inline void _netlink_mpls_build_singlepath(const char *routedesc, + zebra_nhlfe_t *nhlfe, + struct nlmsghdr *nlmsg, + struct rtmsg *rtmsg, + size_t req_size, int cmd) { - int bytelen; - u_char family; + int bytelen; + u_char family; - family = NHLFE_FAMILY (nhlfe); - bytelen = (family == AF_INET ? 4 : 16); - _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop, - nlmsg, rtmsg, req_size, cmd); + family = NHLFE_FAMILY(nhlfe); + bytelen = (family == AF_INET ? 4 : 16); + _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop, + nlmsg, rtmsg, req_size, cmd); } static inline void -_netlink_mpls_build_multipath( - const char *routedesc, - zebra_nhlfe_t *nhlfe, - struct rtattr *rta, - struct rtnexthop *rtnh, - struct rtmsg *rtmsg, - union g_addr **src) +_netlink_mpls_build_multipath(const char *routedesc, zebra_nhlfe_t *nhlfe, + struct rtattr *rta, struct rtnexthop *rtnh, + struct rtmsg *rtmsg, union g_addr **src) { - int bytelen; - u_char family; + int bytelen; + u_char family; - family = NHLFE_FAMILY (nhlfe); - bytelen = (family == AF_INET ? 4 : 16); - _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop, - rta, rtnh, rtmsg, src); + family = NHLFE_FAMILY(nhlfe); + bytelen = (family == AF_INET ? 4 : 16); + _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop, rta, + rtnh, rtmsg, src); } @@ -1164,1316 +1134,1311 @@ _netlink_mpls_build_multipath( * (recursive, multipath, etc.) * @param family: Address family which the change concerns */ -static void -_netlink_route_debug( - int cmd, - struct prefix *p, - struct nexthop *nexthop, - const char *routedesc, - int family, - struct zebra_vrf *zvrf) +static void _netlink_route_debug(int cmd, struct prefix *p, + struct nexthop *nexthop, const char *routedesc, + int family, struct zebra_vrf *zvrf) { - if (IS_ZEBRA_DEBUG_KERNEL) - { - char buf[PREFIX_STRLEN]; - zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s", - routedesc, - nl_msg_type_to_str (cmd), - prefix2str (p, buf, sizeof(buf)), zvrf_id (zvrf), - (nexthop) ? nexthop_type_to_str (nexthop->type) : "UNK"); - } - } - -static void -_netlink_mpls_debug( - int cmd, - u_int32_t label, - const char *routedesc) + if (IS_ZEBRA_DEBUG_KERNEL) { + char buf[PREFIX_STRLEN]; + zlog_debug( + "netlink_route_multipath() (%s): %s %s vrf %u type %s", + routedesc, nl_msg_type_to_str(cmd), + prefix2str(p, buf, sizeof(buf)), zvrf_id(zvrf), + (nexthop) ? nexthop_type_to_str(nexthop->type) : "UNK"); + } +} + +static void _netlink_mpls_debug(int cmd, u_int32_t label, const char *routedesc) { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("netlink_mpls_multipath() (%s): %s %u/20", - routedesc, nl_msg_type_to_str (cmd), label); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("netlink_mpls_multipath() (%s): %s %u/20", routedesc, + nl_msg_type_to_str(cmd), label); } -static int -netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen) +static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, + int llalen) { - struct { - struct nlmsghdr n; - struct ndmsg ndm; - char buf[256]; - } req; + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); - memset(&req.n, 0, sizeof(req.n)); - memset(&req.ndm, 0, sizeof(req.ndm)); + memset(&req.n, 0, sizeof(req.n)); + memset(&req.ndm, 0, sizeof(req.ndm)); - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); - req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; - req.n.nlmsg_type = cmd; //RTM_NEWNEIGH or RTM_DELNEIGH - req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; + req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH + req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; - req.ndm.ndm_family = AF_INET; - req.ndm.ndm_state = NUD_PERMANENT; - req.ndm.ndm_ifindex = ifindex; - req.ndm.ndm_type = RTN_UNICAST; + req.ndm.ndm_family = AF_INET; + req.ndm.ndm_state = NUD_PERMANENT; + req.ndm.ndm_ifindex = ifindex; + req.ndm.ndm_type = RTN_UNICAST; - addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); - addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); + addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); + addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } /* Routing table change via netlink interface. */ /* Update flag indicates whether this is a "replace" or not. */ -static int -netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p, - struct route_entry *re, int update) +static int netlink_route_multipath(int cmd, struct prefix *p, + struct prefix *src_p, struct route_entry *re, + int update) { - int bytelen; - struct sockaddr_nl snl; - struct nexthop *nexthop = NULL; - unsigned int nexthop_num; - int discard; - int family = PREFIX_FAMILY(p); - const char *routedesc; - int setsrc = 0; - union g_addr src; - - struct - { - struct nlmsghdr n; - struct rtmsg r; - char buf[NL_PKT_BUF_SIZE]; - } req; - - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - struct zebra_vrf *zvrf = vrf_info_lookup (re->vrf_id); - - memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); - - bytelen = (family == AF_INET ? 4 : 16); - - req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); - req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; - if ((cmd == RTM_NEWROUTE) && update) - req.n.nlmsg_flags |= NLM_F_REPLACE; - req.n.nlmsg_type = cmd; - req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; - - req.r.rtm_family = family; - req.r.rtm_dst_len = p->prefixlen; - req.r.rtm_src_len = src_p ? src_p->prefixlen : 0; - req.r.rtm_protocol = get_rt_proto(re->type); - req.r.rtm_scope = RT_SCOPE_UNIVERSE; - - if ((re->flags & ZEBRA_FLAG_BLACKHOLE) || (re->flags & ZEBRA_FLAG_REJECT)) - discard = 1; - else - discard = 0; - - if (cmd == RTM_NEWROUTE) - { - if (discard) - { - if (re->flags & ZEBRA_FLAG_BLACKHOLE) - req.r.rtm_type = RTN_BLACKHOLE; - else if (re->flags & ZEBRA_FLAG_REJECT) - req.r.rtm_type = RTN_UNREACHABLE; - else - assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */ - } - else - req.r.rtm_type = RTN_UNICAST; - } - - addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen); - if (src_p) - addattr_l (&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, bytelen); - - /* Metric. */ - /* Hardcode the metric for all routes coming from zebra. Metric isn't used - * either by the kernel or by zebra. Its purely for calculating best path(s) - * by the routing protocol and for communicating with protocol peers. - */ - addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC); - - /* Table corresponding to this route. */ - if (re->table < 256) - req.r.rtm_table = re->table; - else - { - req.r.rtm_table = RT_TABLE_UNSPEC; - addattr32(&req.n, sizeof req, RTA_TABLE, re->table); - } - - if (re->mtu || re->nexthop_mtu) - { - char buf[NL_PKT_BUF_SIZE]; - struct rtattr *rta = (void *) buf; - u_int32_t mtu = re->mtu; - if (!mtu || (re->nexthop_mtu && re->nexthop_mtu < mtu)) - mtu = re->nexthop_mtu; - rta->rta_type = RTA_METRICS; - rta->rta_len = RTA_LENGTH(0); - rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu); - addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta), - RTA_PAYLOAD (rta)); - } - - if (discard) - { - if (cmd == RTM_NEWROUTE) - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - /* We shouldn't encounter recursive nexthops on discard routes, - * but it is probably better to handle that case correctly anyway. - */ - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - } - goto skip; - } - - /* Count overall nexthops so we can decide whether to use singlepath - * or multipath case. */ - nexthop_num = 0; - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - if (cmd == RTM_NEWROUTE && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - continue; - if (cmd == RTM_DELROUTE && !CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - continue; - - nexthop_num++; - } - - /* Singlepath case. */ - if (nexthop_num == 1 || multipath_num == 1) - { - nexthop_num = 0; - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - { - if (!setsrc) - { - if (family == AF_INET) - { - if (nexthop->rmap_src.ipv4.s_addr != 0) - { - src.ipv4 = nexthop->rmap_src.ipv4; - setsrc = 1; - } - else if (nexthop->src.ipv4.s_addr != 0) - { - src.ipv4 = nexthop->src.ipv4; - setsrc = 1; - } - } - else if (family == AF_INET6) - { - if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) - { - src.ipv6 = nexthop->rmap_src.ipv6; - setsrc = 1; - } - else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) - { - src.ipv6 = nexthop->src.ipv6; - setsrc = 1; - } - } - } - continue; - } - - if ((cmd == RTM_NEWROUTE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - || (cmd == RTM_DELROUTE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))) - { - routedesc = nexthop->rparent ? "recursive, 1 hop" : "single hop"; - - _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf); - _netlink_route_build_singlepath(routedesc, bytelen, - nexthop, &req.n, &req.r, - sizeof req, cmd); - nexthop_num++; - break; - } - } - if (setsrc && (cmd == RTM_NEWROUTE)) - { - if (family == AF_INET) - addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen); - else if (family == AF_INET6) - addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen); + int bytelen; + struct sockaddr_nl snl; + struct nexthop *nexthop = NULL; + unsigned int nexthop_num; + int discard; + int family = PREFIX_FAMILY(p); + const char *routedesc; + int setsrc = 0; + union g_addr src; + + struct { + struct nlmsghdr n; + struct rtmsg r; + char buf[NL_PKT_BUF_SIZE]; + } req; + + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); + + memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); + + bytelen = (family == AF_INET ? 4 : 16); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; + if ((cmd == RTM_NEWROUTE) && update) + req.n.nlmsg_flags |= NLM_F_REPLACE; + req.n.nlmsg_type = cmd; + req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; + + req.r.rtm_family = family; + req.r.rtm_dst_len = p->prefixlen; + req.r.rtm_src_len = src_p ? src_p->prefixlen : 0; + req.r.rtm_protocol = get_rt_proto(re->type); + req.r.rtm_scope = RT_SCOPE_UNIVERSE; + + if ((re->flags & ZEBRA_FLAG_BLACKHOLE) + || (re->flags & ZEBRA_FLAG_REJECT)) + discard = 1; + else + discard = 0; + + if (cmd == RTM_NEWROUTE) { + if (discard) { + if (re->flags & ZEBRA_FLAG_BLACKHOLE) + req.r.rtm_type = RTN_BLACKHOLE; + else if (re->flags & ZEBRA_FLAG_REJECT) + req.r.rtm_type = RTN_UNREACHABLE; + else + assert(RTN_BLACKHOLE + != RTN_UNREACHABLE); /* false */ + } else + req.r.rtm_type = RTN_UNICAST; } - } - else - { - char buf[NL_PKT_BUF_SIZE]; - struct rtattr *rta = (void *) buf; - struct rtnexthop *rtnh; - union g_addr *src1 = NULL; - - rta->rta_type = RTA_MULTIPATH; - rta->rta_len = RTA_LENGTH (0); - rtnh = RTA_DATA (rta); - - nexthop_num = 0; - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (nexthop_num >= multipath_num) - break; - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - { - /* This only works for IPv4 now */ - if (!setsrc) - { - if (family == AF_INET) - { - if (nexthop->rmap_src.ipv4.s_addr != 0) - { - src.ipv4 = nexthop->rmap_src.ipv4; - setsrc = 1; - } - else if (nexthop->src.ipv4.s_addr != 0) - { - src.ipv4 = nexthop->src.ipv4; - setsrc = 1; - } - } - else if (family == AF_INET6) - { - if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) - { - src.ipv6 = nexthop->rmap_src.ipv6; - setsrc = 1; - } - else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) - { - src.ipv6 = nexthop->src.ipv6; - setsrc = 1; - } - } - } - continue; - } - - if ((cmd == RTM_NEWROUTE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - || (cmd == RTM_DELROUTE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))) - { - routedesc = nexthop->rparent ? "recursive, multihop" : "multihop"; - nexthop_num++; - - _netlink_route_debug(cmd, p, nexthop, - routedesc, family, zvrf); - _netlink_route_build_multipath(routedesc, bytelen, - nexthop, rta, rtnh, &req.r, &src1); - rtnh = RTNH_NEXT (rtnh); - - if (!setsrc && src1) - { - if (family == AF_INET) - src.ipv4 = src1->ipv4; - else if (family == AF_INET6) - src.ipv6 = src1->ipv6; - setsrc = 1; - } - } - } - if (setsrc && (cmd == RTM_NEWROUTE)) - { - if (family == AF_INET) - addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen); - else if (family == AF_INET6) - addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen); - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("Setting source"); + addattr_l(&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen); + if (src_p) + addattr_l(&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, + bytelen); + + /* Metric. */ + /* Hardcode the metric for all routes coming from zebra. Metric isn't + * used + * either by the kernel or by zebra. Its purely for calculating best + * path(s) + * by the routing protocol and for communicating with protocol peers. + */ + addattr32(&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC); + + /* Table corresponding to this route. */ + if (re->table < 256) + req.r.rtm_table = re->table; + else { + req.r.rtm_table = RT_TABLE_UNSPEC; + addattr32(&req.n, sizeof req, RTA_TABLE, re->table); } - if (rta->rta_len > RTA_LENGTH (0)) - addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta), - RTA_PAYLOAD (rta)); - } + if (re->mtu || re->nexthop_mtu) { + char buf[NL_PKT_BUF_SIZE]; + struct rtattr *rta = (void *)buf; + u_int32_t mtu = re->mtu; + if (!mtu || (re->nexthop_mtu && re->nexthop_mtu < mtu)) + mtu = re->nexthop_mtu; + rta->rta_type = RTA_METRICS; + rta->rta_len = RTA_LENGTH(0); + rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu); + addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA(rta), + RTA_PAYLOAD(rta)); + } + + if (discard) { + if (cmd == RTM_NEWROUTE) + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + /* We shouldn't encounter recursive nexthops on + * discard routes, + * but it is probably better to handle that case + * correctly anyway. + */ + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_RECURSIVE)) + continue; + } + goto skip; + } + + /* Count overall nexthops so we can decide whether to use singlepath + * or multipath case. */ + nexthop_num = 0; + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + if (cmd == RTM_NEWROUTE + && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + continue; + if (cmd == RTM_DELROUTE + && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) + continue; + + nexthop_num++; + } + + /* Singlepath case. */ + if (nexthop_num == 1 || multipath_num == 1) { + nexthop_num = 0; + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_RECURSIVE)) { + if (!setsrc) { + if (family == AF_INET) { + if (nexthop->rmap_src.ipv4 + .s_addr + != 0) { + src.ipv4 = + nexthop->rmap_src + .ipv4; + setsrc = 1; + } else if (nexthop->src.ipv4 + .s_addr + != 0) { + src.ipv4 = + nexthop->src + .ipv4; + setsrc = 1; + } + } else if (family == AF_INET6) { + if (!IN6_IS_ADDR_UNSPECIFIED( + &nexthop->rmap_src + .ipv6)) { + src.ipv6 = + nexthop->rmap_src + .ipv6; + setsrc = 1; + } else if ( + !IN6_IS_ADDR_UNSPECIFIED( + &nexthop->src + .ipv6)) { + src.ipv6 = + nexthop->src + .ipv6; + setsrc = 1; + } + } + } + continue; + } + + if ((cmd == RTM_NEWROUTE + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + || (cmd == RTM_DELROUTE + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB))) { + routedesc = nexthop->rparent + ? "recursive, 1 hop" + : "single hop"; + + _netlink_route_debug(cmd, p, nexthop, routedesc, + family, zvrf); + _netlink_route_build_singlepath( + routedesc, bytelen, nexthop, &req.n, + &req.r, sizeof req, cmd); + nexthop_num++; + break; + } + } + if (setsrc && (cmd == RTM_NEWROUTE)) { + if (family == AF_INET) + addattr_l(&req.n, sizeof req, RTA_PREFSRC, + &src.ipv4, bytelen); + else if (family == AF_INET6) + addattr_l(&req.n, sizeof req, RTA_PREFSRC, + &src.ipv6, bytelen); + } + } else { + char buf[NL_PKT_BUF_SIZE]; + struct rtattr *rta = (void *)buf; + struct rtnexthop *rtnh; + union g_addr *src1 = NULL; + + rta->rta_type = RTA_MULTIPATH; + rta->rta_len = RTA_LENGTH(0); + rtnh = RTA_DATA(rta); + + nexthop_num = 0; + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (nexthop_num >= multipath_num) + break; + + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_RECURSIVE)) { + /* This only works for IPv4 now */ + if (!setsrc) { + if (family == AF_INET) { + if (nexthop->rmap_src.ipv4 + .s_addr + != 0) { + src.ipv4 = + nexthop->rmap_src + .ipv4; + setsrc = 1; + } else if (nexthop->src.ipv4 + .s_addr + != 0) { + src.ipv4 = + nexthop->src + .ipv4; + setsrc = 1; + } + } else if (family == AF_INET6) { + if (!IN6_IS_ADDR_UNSPECIFIED( + &nexthop->rmap_src + .ipv6)) { + src.ipv6 = + nexthop->rmap_src + .ipv6; + setsrc = 1; + } else if ( + !IN6_IS_ADDR_UNSPECIFIED( + &nexthop->src + .ipv6)) { + src.ipv6 = + nexthop->src + .ipv6; + setsrc = 1; + } + } + } + continue; + } + + if ((cmd == RTM_NEWROUTE + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + || (cmd == RTM_DELROUTE + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB))) { + routedesc = nexthop->rparent + ? "recursive, multihop" + : "multihop"; + nexthop_num++; + + _netlink_route_debug(cmd, p, nexthop, routedesc, + family, zvrf); + _netlink_route_build_multipath( + routedesc, bytelen, nexthop, rta, rtnh, + &req.r, &src1); + rtnh = RTNH_NEXT(rtnh); + + if (!setsrc && src1) { + if (family == AF_INET) + src.ipv4 = src1->ipv4; + else if (family == AF_INET6) + src.ipv6 = src1->ipv6; + + setsrc = 1; + } + } + } + if (setsrc && (cmd == RTM_NEWROUTE)) { + if (family == AF_INET) + addattr_l(&req.n, sizeof req, RTA_PREFSRC, + &src.ipv4, bytelen); + else if (family == AF_INET6) + addattr_l(&req.n, sizeof req, RTA_PREFSRC, + &src.ipv6, bytelen); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Setting source"); + } + + if (rta->rta_len > RTA_LENGTH(0)) + addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, + RTA_DATA(rta), RTA_PAYLOAD(rta)); + } - /* If there is no useful nexthop then return. */ - if (nexthop_num == 0) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("netlink_route_multipath(): No useful nexthop."); - return 0; - } + /* If there is no useful nexthop then return. */ + if (nexthop_num == 0) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath(): No useful nexthop."); + return 0; + } skip: - /* Destination netlink address. */ - memset (&snl, 0, sizeof snl); - snl.nl_family = AF_NETLINK; + /* Destination netlink address. */ + memset(&snl, 0, sizeof snl); + snl.nl_family = AF_NETLINK; - /* Talk to netlink socket. */ - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + /* Talk to netlink socket. */ + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } -int -kernel_get_ipmr_sg_stats (void *in) +int kernel_get_ipmr_sg_stats(void *in) { - int suc = 0; - struct mcast_route_data *mr = (struct mcast_route_data *)in; - struct { - struct nlmsghdr n; - struct ndmsg ndm; - char buf[256]; - } req; + int suc = 0; + struct mcast_route_data *mr = (struct mcast_route_data *)in; + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; - mroute = mr; - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); + mroute = mr; + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); - memset(&req.n, 0, sizeof(req.n)); - memset(&req.ndm, 0, sizeof(req.ndm)); + memset(&req.n, 0, sizeof(req.n)); + memset(&req.ndm, 0, sizeof(req.ndm)); - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; - req.ndm.ndm_family = AF_INET; - req.n.nlmsg_type = RTM_GETROUTE; + req.ndm.ndm_family = AF_INET; + req.n.nlmsg_type = RTM_GETROUTE; - addattr_l (&req.n, sizeof (req), RTA_IIF, &mroute->ifindex, 4); - addattr_l (&req.n, sizeof (req), RTA_OIF, &mroute->ifindex, 4); - addattr_l (&req.n, sizeof (req), RTA_SRC, &mroute->sg.src.s_addr, 4); - addattr_l (&req.n, sizeof (req), RTA_DST, &mroute->sg.grp.s_addr, 4); + addattr_l(&req.n, sizeof(req), RTA_IIF, &mroute->ifindex, 4); + addattr_l(&req.n, sizeof(req), RTA_OIF, &mroute->ifindex, 4); + addattr_l(&req.n, sizeof(req), RTA_SRC, &mroute->sg.src.s_addr, 4); + addattr_l(&req.n, sizeof(req), RTA_DST, &mroute->sg.grp.s_addr, 4); - suc = netlink_talk (netlink_route_change_read_multicast, &req.n, &zns->netlink_cmd, zns, 0); + suc = netlink_talk(netlink_route_change_read_multicast, &req.n, + &zns->netlink_cmd, zns, 0); - mroute = NULL; - return suc; + mroute = NULL; + return suc; } -int -kernel_route_rib (struct prefix *p, struct prefix *src_p, - struct route_entry *old, struct route_entry *new) +int kernel_route_rib(struct prefix *p, struct prefix *src_p, + struct route_entry *old, struct route_entry *new) { - if (!old && new) - return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 0); - if (old && !new) - return netlink_route_multipath (RTM_DELROUTE, p, src_p, old, 0); + if (!old && new) + return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 0); + if (old && !new) + return netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0); - return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 1); + return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 1); } -int -kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen) +int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, + int llalen) { - return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex, addr, - lla, llalen); + return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex, + addr, lla, llalen); } /* * Add remote VTEP to the flood list for this VxLAN interface (VNI). This * is done by adding an FDB entry with a MAC of 00:00:00:00:00:00. */ -static int -netlink_vxlan_flood_list_update (struct interface *ifp, - struct in_addr *vtep_ip, - int cmd) +static int netlink_vxlan_flood_list_update(struct interface *ifp, + struct in_addr *vtep_ip, int cmd) { - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - struct - { - struct nlmsghdr n; - struct ndmsg ndm; - char buf[256]; - } req; - u_char dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; - - memset(&req.n, 0, sizeof(req.n)); - memset(&req.ndm, 0, sizeof(req.ndm)); - - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - if (cmd == RTM_NEWNEIGH) - req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_APPEND); - req.n.nlmsg_type = cmd; - req.ndm.ndm_family = PF_BRIDGE; - req.ndm.ndm_state = NUD_NOARP | NUD_PERMANENT; - req.ndm.ndm_flags |= NTF_SELF; // Handle by "self", not "master" - - - addattr_l (&req.n, sizeof (req), NDA_LLADDR, &dst_mac, 6); - req.ndm.ndm_ifindex = ifp->ifindex; - addattr_l (&req.n, sizeof (req), NDA_DST, &vtep_ip->s_addr, 4); - - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; + u_char dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + + memset(&req.n, 0, sizeof(req.n)); + memset(&req.ndm, 0, sizeof(req.ndm)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + if (cmd == RTM_NEWNEIGH) + req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_APPEND); + req.n.nlmsg_type = cmd; + req.ndm.ndm_family = PF_BRIDGE; + req.ndm.ndm_state = NUD_NOARP | NUD_PERMANENT; + req.ndm.ndm_flags |= NTF_SELF; // Handle by "self", not "master" + + + addattr_l(&req.n, sizeof(req), NDA_LLADDR, &dst_mac, 6); + req.ndm.ndm_ifindex = ifp->ifindex; + addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip->s_addr, 4); + + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } /* - * Add remote VTEP for this VxLAN interface (VNI). In Linux, this involves adding + * Add remote VTEP for this VxLAN interface (VNI). In Linux, this involves + * adding * a "flood" MAC FDB entry. */ -int -kernel_add_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) +int kernel_add_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("Install %s into flood list for VNI %u intf %s(%u)", - inet_ntoa (*vtep_ip), vni, ifp->name, ifp->ifindex); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("Install %s into flood list for VNI %u intf %s(%u)", + inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex); - return netlink_vxlan_flood_list_update (ifp, vtep_ip, RTM_NEWNEIGH); + return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_NEWNEIGH); } /* * Remove remote VTEP for this VxLAN interface (VNI). In Linux, this involves * deleting the "flood" MAC FDB entry. */ -int -kernel_del_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) +int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("Uninstall %s from flood list for VNI %u intf %s(%u)", - inet_ntoa (*vtep_ip), vni, ifp->name, ifp->ifindex); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "Uninstall %s from flood list for VNI %u intf %s(%u)", + inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex); - return netlink_vxlan_flood_list_update (ifp, vtep_ip, RTM_DELNEIGH); + return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_DELNEIGH); } #ifndef NDA_RTA -#define NDA_RTA(r) \ - ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) +#define NDA_RTA(r) \ + ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) #endif -static int -netlink_macfdb_change (struct sockaddr_nl *snl, struct nlmsghdr *h, int len) +static int netlink_macfdb_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + int len) { - struct ndmsg *ndm; - struct interface *ifp; - struct zebra_if *zif; - struct zebra_vrf *zvrf; - struct rtattr *tb[NDA_MAX + 1]; - struct interface *br_if; - struct ethaddr mac; - vlanid_t vid = 0; - struct prefix vtep_ip; - int vid_present = 0, dst_present = 0; - char buf[ETHER_ADDR_STRLEN]; - char vid_buf[20]; - char dst_buf[30]; - u_char sticky = 0; - - ndm = NLMSG_DATA (h); - - /* The interface should exist. */ - ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ndm->ndm_ifindex); - if (!ifp) - return 0; - - /* Locate VRF corresponding to interface. We only process MAC notifications - * if EVPN is enabled on this VRF. - */ - zvrf = vrf_info_lookup(ifp->vrf_id); - if (!zvrf || !EVPN_ENABLED(zvrf)) - return 0; - if (!ifp->info) - return 0; - - /* The interface should be something we're interested in. */ - if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) - return 0; - - /* Drop "permanent" entries. */ - if (ndm->ndm_state & NUD_PERMANENT) - return 0; - - zif = (struct zebra_if *)ifp->info; - if ((br_if = zif->brslave_info.br_if) == NULL) - { - zlog_warn ("%s family %s IF %s(%u) brIF %u - no bridge master", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - zif->brslave_info.bridge_ifindex); - return 0; - } - - /* Parse attributes and extract fields of interest. */ - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, NDA_MAX, NDA_RTA (ndm), len); - - if (!tb[NDA_LLADDR]) - { - zlog_warn ("%s family %s IF %s(%u) brIF %u - no LLADDR", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - zif->brslave_info.bridge_ifindex); - return 0; - } - - if (RTA_PAYLOAD (tb[NDA_LLADDR]) != ETHER_ADDR_LEN) - { - zlog_warn ("%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %ld", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - zif->brslave_info.bridge_ifindex, - RTA_PAYLOAD (tb[NDA_LLADDR])); - return 0; - } - - memcpy (&mac, RTA_DATA (tb[NDA_LLADDR]), ETHER_ADDR_LEN); - - if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN]) - { - vid_present = 1; - vid = *(u_int16_t *) RTA_DATA(tb[NDA_VLAN]); - sprintf (vid_buf, " VLAN %u", vid); - } - - if (tb[NDA_DST]) - { - /* TODO: Only IPv4 supported now. */ - dst_present = 1; - vtep_ip.family = AF_INET; - vtep_ip.prefixlen = IPV4_MAX_BITLEN; - memcpy (&(vtep_ip.u.prefix4.s_addr), RTA_DATA (tb[NDA_DST]), IPV4_MAX_BYTELEN); - sprintf (dst_buf, " dst %s", inet_ntoa (vtep_ip.u.prefix4)); - } - - sticky = (ndm->ndm_state & NUD_NOARP) ? 1 : 0; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Rx %s family %s IF %s(%u)%s %sMAC %s%s", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - vid_present ? vid_buf : "", - sticky ? "sticky " : "", - prefix_mac2str (&mac, buf, sizeof (buf)), - dst_present ? dst_buf: ""); - - if (filter_vlan && vid != filter_vlan) - return 0; - - /* If add or update, do accordingly if learnt on a "local" interface; if - * the notification is over VxLAN, this has to be related to multi-homing, - * so perform an implicit delete of any local entry (if it exists). - */ - if (h->nlmsg_type == RTM_NEWNEIGH) - { - /* Drop "permanent" entries. */ - if (ndm->ndm_state & NUD_PERMANENT) - return 0; - - if (IS_ZEBRA_IF_VXLAN(ifp)) - return zebra_vxlan_check_del_local_mac (ifp, br_if, &mac, vid); - - return zebra_vxlan_local_mac_add_update (ifp, br_if, &mac, vid, sticky); - } - - /* This is a delete notification. - * 1. For a MAC over VxLan, check if it needs to be refreshed(readded) - * 2. For a MAC over "local" interface, delete the mac - * Note: We will get notifications from both bridge driver and VxLAN driver. - * Ignore the notification from VxLan driver as it is also generated - * when mac moves from remote to local. - */ - if (dst_present) - return 0; - - if (IS_ZEBRA_IF_VXLAN(ifp)) - return zebra_vxlan_check_readd_remote_mac (ifp, br_if, &mac, vid); - - return zebra_vxlan_local_mac_del (ifp, br_if, &mac, vid); + struct ndmsg *ndm; + struct interface *ifp; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + struct rtattr *tb[NDA_MAX + 1]; + struct interface *br_if; + struct ethaddr mac; + vlanid_t vid = 0; + struct prefix vtep_ip; + int vid_present = 0, dst_present = 0; + char buf[ETHER_ADDR_STRLEN]; + char vid_buf[20]; + char dst_buf[30]; + u_char sticky = 0; + + ndm = NLMSG_DATA(h); + + /* The interface should exist. */ + ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), + ndm->ndm_ifindex); + if (!ifp) + return 0; + + /* Locate VRF corresponding to interface. We only process MAC + * notifications + * if EVPN is enabled on this VRF. + */ + zvrf = vrf_info_lookup(ifp->vrf_id); + if (!zvrf || !EVPN_ENABLED(zvrf)) + return 0; + if (!ifp->info) + return 0; + + /* The interface should be something we're interested in. */ + if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) + return 0; + + /* Drop "permanent" entries. */ + if (ndm->ndm_state & NUD_PERMANENT) + return 0; + + zif = (struct zebra_if *)ifp->info; + if ((br_if = zif->brslave_info.br_if) == NULL) { + zlog_warn("%s family %s IF %s(%u) brIF %u - no bridge master", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex); + return 0; + } + + /* Parse attributes and extract fields of interest. */ + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len); + + if (!tb[NDA_LLADDR]) { + zlog_warn("%s family %s IF %s(%u) brIF %u - no LLADDR", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex); + return 0; + } + + if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETHER_ADDR_LEN) { + zlog_warn( + "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %ld", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex, + RTA_PAYLOAD(tb[NDA_LLADDR])); + return 0; + } + + memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETHER_ADDR_LEN); + + if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN]) { + vid_present = 1; + vid = *(u_int16_t *)RTA_DATA(tb[NDA_VLAN]); + sprintf(vid_buf, " VLAN %u", vid); + } + + if (tb[NDA_DST]) { + /* TODO: Only IPv4 supported now. */ + dst_present = 1; + vtep_ip.family = AF_INET; + vtep_ip.prefixlen = IPV4_MAX_BITLEN; + memcpy(&(vtep_ip.u.prefix4.s_addr), RTA_DATA(tb[NDA_DST]), + IPV4_MAX_BYTELEN); + sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip.u.prefix4)); + } + + sticky = (ndm->ndm_state & NUD_NOARP) ? 1 : 0; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Rx %s family %s IF %s(%u)%s %sMAC %s%s", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex, vid_present ? vid_buf : "", + sticky ? "sticky " : "", + prefix_mac2str(&mac, buf, sizeof(buf)), + dst_present ? dst_buf : ""); + + if (filter_vlan && vid != filter_vlan) + return 0; + + /* If add or update, do accordingly if learnt on a "local" interface; if + * the notification is over VxLAN, this has to be related to + * multi-homing, + * so perform an implicit delete of any local entry (if it exists). + */ + if (h->nlmsg_type == RTM_NEWNEIGH) { + /* Drop "permanent" entries. */ + if (ndm->ndm_state & NUD_PERMANENT) + return 0; + + if (IS_ZEBRA_IF_VXLAN(ifp)) + return zebra_vxlan_check_del_local_mac(ifp, br_if, &mac, + vid); + + return zebra_vxlan_local_mac_add_update(ifp, br_if, &mac, vid, + sticky); + } + + /* This is a delete notification. + * 1. For a MAC over VxLan, check if it needs to be refreshed(readded) + * 2. For a MAC over "local" interface, delete the mac + * Note: We will get notifications from both bridge driver and VxLAN + * driver. + * Ignore the notification from VxLan driver as it is also generated + * when mac moves from remote to local. + */ + if (dst_present) + return 0; + + if (IS_ZEBRA_IF_VXLAN(ifp)) + return zebra_vxlan_check_readd_remote_mac(ifp, br_if, &mac, + vid); + + return zebra_vxlan_local_mac_del(ifp, br_if, &mac, vid); } -static int -netlink_macfdb_table (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +static int netlink_macfdb_table(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct ndmsg *ndm; + int len; + struct ndmsg *ndm; - if (h->nlmsg_type != RTM_NEWNEIGH) - return 0; + if (h->nlmsg_type != RTM_NEWNEIGH) + return 0; - /* Length validity. */ - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg)); - if (len < 0) - return -1; + /* Length validity. */ + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg)); + if (len < 0) + return -1; - /* We are interested only in AF_BRIDGE notifications. */ - ndm = NLMSG_DATA (h); - if (ndm->ndm_family != AF_BRIDGE) - return 0; + /* We are interested only in AF_BRIDGE notifications. */ + ndm = NLMSG_DATA(h); + if (ndm->ndm_family != AF_BRIDGE) + return 0; - return netlink_macfdb_change (snl, h, len); + return netlink_macfdb_change(snl, h, len); } /* Request for MAC FDB information from the kernel */ -static int -netlink_request_macs (struct zebra_ns *zns, int family, int type, - ifindex_t master_ifindex) +static int netlink_request_macs(struct zebra_ns *zns, int family, int type, + ifindex_t master_ifindex) { - struct - { - struct nlmsghdr n; - struct ifinfomsg ifm; - char buf[256]; - } req; - - /* Form the request, specifying filter (rtattr) if needed. */ - memset (&req, 0, sizeof (req)); - req.n.nlmsg_type = type; - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); - req.ifm.ifi_family = family; - if (master_ifindex) - addattr32 (&req.n, sizeof(req), IFLA_MASTER, master_ifindex); - - return netlink_request (&zns->netlink_cmd, &req.n); + struct { + struct nlmsghdr n; + struct ifinfomsg ifm; + char buf[256]; + } req; + + /* Form the request, specifying filter (rtattr) if needed. */ + memset(&req, 0, sizeof(req)); + req.n.nlmsg_type = type; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.ifm.ifi_family = family; + if (master_ifindex) + addattr32(&req.n, sizeof(req), IFLA_MASTER, master_ifindex); + + return netlink_request(&zns->netlink_cmd, &req.n); } /* * MAC forwarding database read using netlink interface. This is invoked * at startup. */ -int -netlink_macfdb_read (struct zebra_ns *zns) +int netlink_macfdb_read(struct zebra_ns *zns) { - int ret; - - /* Get bridge FDB table. */ - ret = netlink_request_macs (zns, AF_BRIDGE, RTM_GETNEIGH, 0); - if (ret < 0) - return ret; - /* We are reading entire table. */ - filter_vlan = 0; - ret = netlink_parse_info (netlink_macfdb_table, &zns->netlink_cmd, zns, 0, 1); - - return ret; + int ret; + + /* Get bridge FDB table. */ + ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH, 0); + if (ret < 0) + return ret; + /* We are reading entire table. */ + filter_vlan = 0; + ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns, + 0, 1); + + return ret; } /* * MAC forwarding database read using netlink interface. This is for a * specific bridge and matching specific access VLAN (if VLAN-aware bridge). */ -int -netlink_macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp, - struct interface *br_if) +int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, + struct interface *br_if) { - struct zebra_if *br_zif; - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - int ret = 0; - - - /* Save VLAN we're filtering on, if needed. */ - br_zif = (struct zebra_if *) br_if->info; - zif = (struct zebra_if *) ifp->info; - vxl = &zif->l2info.vxl; - if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif)) - filter_vlan = vxl->access_vlan; - - /* Get bridge FDB table for specific bridge - we do the VLAN filtering. */ - ret = netlink_request_macs (zns, AF_BRIDGE, RTM_GETNEIGH, br_if->ifindex); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_macfdb_table, &zns->netlink_cmd, zns, 0, 0); - - /* Reset VLAN filter. */ - filter_vlan = 0; - return ret; + struct zebra_if *br_zif; + struct zebra_if *zif; + struct zebra_l2info_vxlan *vxl; + int ret = 0; + + + /* Save VLAN we're filtering on, if needed. */ + br_zif = (struct zebra_if *)br_if->info; + zif = (struct zebra_if *)ifp->info; + vxl = &zif->l2info.vxl; + if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif)) + filter_vlan = vxl->access_vlan; + + /* Get bridge FDB table for specific bridge - we do the VLAN filtering. + */ + ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH, + br_if->ifindex); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns, + 0, 0); + + /* Reset VLAN filter. */ + filter_vlan = 0; + return ret; } -static int -netlink_macfdb_update (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, - struct in_addr vtep_ip, - int local, int cmd, - u_char sticky) +static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid, + struct ethaddr *mac, struct in_addr vtep_ip, + int local, int cmd, u_char sticky) { - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - struct - { - struct nlmsghdr n; - struct ndmsg ndm; - char buf[256]; - } req; - int dst_alen; - struct zebra_if *zif; - struct interface *br_if; - struct zebra_if *br_zif; - char buf[ETHER_ADDR_STRLEN]; - int vid_present = 0, dst_present = 0; - char vid_buf[20]; - char dst_buf[30]; - - zif = ifp->info; - if ((br_if = zif->brslave_info.br_if) == NULL) - { - zlog_warn ("MAC %s on IF %s(%u) - no mapping to bridge", - (cmd == RTM_NEWNEIGH) ? "add" : "del", - ifp->name, ifp->ifindex); - return -1; - } - - memset(&req.n, 0, sizeof(req.n)); - memset(&req.ndm, 0, sizeof(req.ndm)); - - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - if (cmd == RTM_NEWNEIGH) - req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); - req.n.nlmsg_type = cmd; - req.ndm.ndm_family = AF_BRIDGE; - req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER; - req.ndm.ndm_state = NUD_REACHABLE; - - if (sticky) - req.ndm.ndm_state |= NUD_NOARP; - else - req.ndm.ndm_flags |= NTF_EXT_LEARNED; - - addattr_l (&req.n, sizeof (req), NDA_LLADDR, mac, 6); - req.ndm.ndm_ifindex = ifp->ifindex; - if (!local) - { - dst_alen = 4; // TODO: hardcoded - addattr_l (&req.n, sizeof (req), NDA_DST, &vtep_ip, dst_alen); - dst_present = 1; - sprintf (dst_buf, " dst %s", inet_ntoa (vtep_ip)); - } - br_zif = (struct zebra_if *) br_if->info; - if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) - { - addattr16 (&req.n, sizeof (req), NDA_VLAN, vid); - vid_present = 1; - sprintf (vid_buf, " VLAN %u", vid); - } - addattr32 (&req.n, sizeof (req), NDA_MASTER, br_if->ifindex); - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Tx %s family %s IF %s(%u)%s %sMAC %s%s", - nl_msg_type_to_str (cmd), - nl_family_to_str (req.ndm.ndm_family), - ifp->name, ifp->ifindex, - vid_present ? vid_buf : "", - sticky ? "sticky " : "", - prefix_mac2str (mac, buf, sizeof (buf)), - dst_present ? dst_buf : ""); - - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; + int dst_alen; + struct zebra_if *zif; + struct interface *br_if; + struct zebra_if *br_zif; + char buf[ETHER_ADDR_STRLEN]; + int vid_present = 0, dst_present = 0; + char vid_buf[20]; + char dst_buf[30]; + + zif = ifp->info; + if ((br_if = zif->brslave_info.br_if) == NULL) { + zlog_warn("MAC %s on IF %s(%u) - no mapping to bridge", + (cmd == RTM_NEWNEIGH) ? "add" : "del", ifp->name, + ifp->ifindex); + return -1; + } + + memset(&req.n, 0, sizeof(req.n)); + memset(&req.ndm, 0, sizeof(req.ndm)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + if (cmd == RTM_NEWNEIGH) + req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); + req.n.nlmsg_type = cmd; + req.ndm.ndm_family = AF_BRIDGE; + req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER; + req.ndm.ndm_state = NUD_REACHABLE; + + if (sticky) + req.ndm.ndm_state |= NUD_NOARP; + else + req.ndm.ndm_flags |= NTF_EXT_LEARNED; + + addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6); + req.ndm.ndm_ifindex = ifp->ifindex; + if (!local) { + dst_alen = 4; // TODO: hardcoded + addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen); + dst_present = 1; + sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip)); + } + br_zif = (struct zebra_if *)br_if->info; + if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) { + addattr16(&req.n, sizeof(req), NDA_VLAN, vid); + vid_present = 1; + sprintf(vid_buf, " VLAN %u", vid); + } + addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s", + nl_msg_type_to_str(cmd), + nl_family_to_str(req.ndm.ndm_family), ifp->name, + ifp->ifindex, vid_present ? vid_buf : "", + sticky ? "sticky " : "", + prefix_mac2str(mac, buf, sizeof(buf)), + dst_present ? dst_buf : ""); + + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } -#define NUD_VALID (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | \ - NUD_PROBE | NUD_STALE | NUD_DELAY) +#define NUD_VALID \ + (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE \ + | NUD_DELAY) -static int -netlink_ipneigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h, int len) +static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + int len) { - struct ndmsg *ndm; - struct interface *ifp; - struct zebra_if *zif; - struct zebra_vrf *zvrf; - struct rtattr *tb[NDA_MAX + 1]; - struct interface *link_if; - struct ethaddr mac; - struct ipaddr ip; - char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - int mac_present = 0; - u_char ext_learned; - - ndm = NLMSG_DATA (h); - - /* The interface should exist. */ - ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ndm->ndm_ifindex); - if (!ifp) - return 0; - - /* Locate VRF corresponding to interface. We only process neigh notifications - * if EVPN is enabled on this VRF. - */ - zvrf = vrf_info_lookup(ifp->vrf_id); - if (!zvrf || !EVPN_ENABLED(zvrf)) - return 0; - if (!ifp->info) - return 0; - - /* Drop "permanent" entries. */ - if (ndm->ndm_state & NUD_PERMANENT) - return 0; - - zif = (struct zebra_if *)ifp->info; - /* The neighbor is present on an SVI. From this, we locate the underlying - * bridge because we're only interested in neighbors on a VxLAN bridge. - * The bridge is located based on the nature of the SVI: - * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface - * and is linked to the bridge - * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface - * itself - */ - if (IS_ZEBRA_IF_VLAN(ifp)) - { - link_if = zif->link; - if (!link_if) - return 0; - } - else if (IS_ZEBRA_IF_BRIDGE(ifp)) - link_if = ifp; - else - return 0; - - /* Parse attributes and extract fields of interest. */ - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, NDA_MAX, NDA_RTA (ndm), len); - - if (!tb[NDA_DST]) - { - zlog_warn ("%s family %s IF %s(%u) - no DST", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex); - return 0; - } - memset (&mac, 0, sizeof (struct ethaddr)); - memset (&ip, 0, sizeof (struct ipaddr)); - ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6; - memcpy (&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST])); - - if (h->nlmsg_type == RTM_NEWNEIGH) - { - if (tb[NDA_LLADDR]) - { - if (RTA_PAYLOAD (tb[NDA_LLADDR]) != ETHER_ADDR_LEN) - { - zlog_warn ("%s family %s IF %s(%u) - LLADDR is not MAC, len %ld", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - RTA_PAYLOAD (tb[NDA_LLADDR])); - return 0; - } - - mac_present = 1; - memcpy (&mac, RTA_DATA (tb[NDA_LLADDR]), ETHER_ADDR_LEN); - } - - ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - ipaddr2str (&ip, buf2, sizeof(buf2)), - mac_present ? prefix_mac2str (&mac, buf, sizeof (buf)) : "", - ndm->ndm_state, ndm->ndm_flags); - - /* If the neighbor state is valid for use, process as an add or update - * else process as a delete. Note that the delete handling may result - * in re-adding the neighbor if it is a valid "remote" neighbor. - */ - if (ndm->ndm_state & NUD_VALID) - return zebra_vxlan_local_neigh_add_update (ifp, link_if, - &ip, &mac, - ndm->ndm_state, ext_learned); - - return zebra_vxlan_local_neigh_del (ifp, link_if, &ip); - } - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Rx %s family %s IF %s(%u) IP %s", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - ipaddr2str (&ip, buf2, sizeof(buf2))); - - /* Process the delete - it may result in re-adding the neighbor if it is - * a valid "remote" neighbor. - */ - return zebra_vxlan_local_neigh_del (ifp, link_if, &ip); + struct ndmsg *ndm; + struct interface *ifp; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + struct rtattr *tb[NDA_MAX + 1]; + struct interface *link_if; + struct ethaddr mac; + struct ipaddr ip; + char buf[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + int mac_present = 0; + u_char ext_learned; + + ndm = NLMSG_DATA(h); + + /* The interface should exist. */ + ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), + ndm->ndm_ifindex); + if (!ifp) + return 0; + + /* Locate VRF corresponding to interface. We only process neigh + * notifications + * if EVPN is enabled on this VRF. + */ + zvrf = vrf_info_lookup(ifp->vrf_id); + if (!zvrf || !EVPN_ENABLED(zvrf)) + return 0; + if (!ifp->info) + return 0; + + /* Drop "permanent" entries. */ + if (ndm->ndm_state & NUD_PERMANENT) + return 0; + + zif = (struct zebra_if *)ifp->info; + /* The neighbor is present on an SVI. From this, we locate the + * underlying + * bridge because we're only interested in neighbors on a VxLAN bridge. + * The bridge is located based on the nature of the SVI: + * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN + * interface + * and is linked to the bridge + * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge + * inteface + * itself + */ + if (IS_ZEBRA_IF_VLAN(ifp)) { + link_if = zif->link; + if (!link_if) + return 0; + } else if (IS_ZEBRA_IF_BRIDGE(ifp)) + link_if = ifp; + else + return 0; + + /* Parse attributes and extract fields of interest. */ + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len); + + if (!tb[NDA_DST]) { + zlog_warn("%s family %s IF %s(%u) - no DST", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex); + return 0; + } + memset(&mac, 0, sizeof(struct ethaddr)); + memset(&ip, 0, sizeof(struct ipaddr)); + ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6; + memcpy(&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST])); + + if (h->nlmsg_type == RTM_NEWNEIGH) { + if (tb[NDA_LLADDR]) { + if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETHER_ADDR_LEN) { + zlog_warn( + "%s family %s IF %s(%u) - LLADDR is not MAC, len %ld", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), + ifp->name, ndm->ndm_ifindex, + RTA_PAYLOAD(tb[NDA_LLADDR])); + return 0; + } + + mac_present = 1; + memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETHER_ADDR_LEN); + } + + ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex, + ipaddr2str(&ip, buf2, sizeof(buf2)), + mac_present + ? prefix_mac2str(&mac, buf, sizeof(buf)) + : "", + ndm->ndm_state, ndm->ndm_flags); + + /* If the neighbor state is valid for use, process as an add or + * update + * else process as a delete. Note that the delete handling may + * result + * in re-adding the neighbor if it is a valid "remote" neighbor. + */ + if (ndm->ndm_state & NUD_VALID) + return zebra_vxlan_local_neigh_add_update( + ifp, link_if, &ip, &mac, ndm->ndm_state, + ext_learned); + + return zebra_vxlan_local_neigh_del(ifp, link_if, &ip); + } + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Rx %s family %s IF %s(%u) IP %s", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex, + ipaddr2str(&ip, buf2, sizeof(buf2))); + + /* Process the delete - it may result in re-adding the neighbor if it is + * a valid "remote" neighbor. + */ + return zebra_vxlan_local_neigh_del(ifp, link_if, &ip); } -static int -netlink_neigh_table (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +static int netlink_neigh_table(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct ndmsg *ndm; + int len; + struct ndmsg *ndm; - if (h->nlmsg_type != RTM_NEWNEIGH) - return 0; + if (h->nlmsg_type != RTM_NEWNEIGH) + return 0; - /* Length validity. */ - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg)); - if (len < 0) - return -1; + /* Length validity. */ + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg)); + if (len < 0) + return -1; - /* We are interested only in AF_INET or AF_INET6 notifications. */ - ndm = NLMSG_DATA (h); - if (ndm->ndm_family != AF_INET && ndm->ndm_family != AF_INET6) - return 0; + /* We are interested only in AF_INET or AF_INET6 notifications. */ + ndm = NLMSG_DATA(h); + if (ndm->ndm_family != AF_INET && ndm->ndm_family != AF_INET6) + return 0; - return netlink_neigh_change (snl, h, len); + return netlink_neigh_change(snl, h, len); } /* Request for IP neighbor information from the kernel */ -static int -netlink_request_neigh (struct zebra_ns *zns, int family, int type, - ifindex_t ifindex) +static int netlink_request_neigh(struct zebra_ns *zns, int family, int type, + ifindex_t ifindex) { - struct - { - struct nlmsghdr n; - struct ndmsg ndm; - char buf[256]; - } req; - - /* Form the request, specifying filter (rtattr) if needed. */ - memset (&req, 0, sizeof (req)); - req.n.nlmsg_type = type; - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); - req.ndm.ndm_family = family; - if (ifindex) - addattr32 (&req.n, sizeof(req), NDA_IFINDEX, ifindex); - - return netlink_request (&zns->netlink_cmd, &req.n); + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; + + /* Form the request, specifying filter (rtattr) if needed. */ + memset(&req, 0, sizeof(req)); + req.n.nlmsg_type = type; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.ndm.ndm_family = family; + if (ifindex) + addattr32(&req.n, sizeof(req), NDA_IFINDEX, ifindex); + + return netlink_request(&zns->netlink_cmd, &req.n); } /* * IP Neighbor table read using netlink interface. This is invoked * at startup. */ -int -netlink_neigh_read (struct zebra_ns *zns) +int netlink_neigh_read(struct zebra_ns *zns) { - int ret; + int ret; - /* Get IP neighbor table. */ - ret = netlink_request_neigh (zns, AF_UNSPEC, RTM_GETNEIGH, 0); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_neigh_table, &zns->netlink_cmd, zns, 0, 1); + /* Get IP neighbor table. */ + ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH, 0); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0, + 1); - return ret; + return ret; } /* * IP Neighbor table read using netlink interface. This is for a specific * VLAN device. */ -int -netlink_neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if) +int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) { - int ret = 0; + int ret = 0; - ret = netlink_request_neigh (zns, AF_UNSPEC, RTM_GETNEIGH, vlan_if->ifindex); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_neigh_table, &zns->netlink_cmd, zns, 0, 0); + ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH, + vlan_if->ifindex); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0, + 0); - return ret; + return ret; } -int -netlink_neigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) +int netlink_neigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id) { - int len; - struct ndmsg *ndm; + int len; + struct ndmsg *ndm; - if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH)) - return 0; + if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH)) + return 0; - /* Length validity. */ - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg)); - if (len < 0) - return -1; + /* Length validity. */ + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg)); + if (len < 0) + return -1; - /* Is this a notification for the MAC FDB or IP neighbor table? */ - ndm = NLMSG_DATA (h); - if (ndm->ndm_family == AF_BRIDGE) - return netlink_macfdb_change (snl, h, len); + /* Is this a notification for the MAC FDB or IP neighbor table? */ + ndm = NLMSG_DATA(h); + if (ndm->ndm_family == AF_BRIDGE) + return netlink_macfdb_change(snl, h, len); - if (ndm->ndm_type != RTN_UNICAST) - return 0; + if (ndm->ndm_type != RTN_UNICAST) + return 0; - if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6) - return netlink_ipneigh_change (snl, h, len); + if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6) + return netlink_ipneigh_change(snl, h, len); - return 0; + return 0; } -static int -netlink_neigh_update2 (struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac, u_int32_t flags, int cmd) +static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip, + struct ethaddr *mac, u_int32_t flags, int cmd) { - struct { - struct nlmsghdr n; - struct ndmsg ndm; - char buf[256]; - } req; - int ipa_len; - - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - char buf[INET6_ADDRSTRLEN]; - char buf2[ETHER_ADDR_STRLEN]; - - memset(&req.n, 0, sizeof(req.n)); - memset(&req.ndm, 0, sizeof(req.ndm)); - - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - if (cmd == RTM_NEWNEIGH) - req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); - req.n.nlmsg_type = cmd; //RTM_NEWNEIGH or RTM_DELNEIGH - req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6; - req.ndm.ndm_state = flags; - req.ndm.ndm_ifindex = ifp->ifindex; - req.ndm.ndm_type = RTN_UNICAST; - req.ndm.ndm_flags = NTF_EXT_LEARNED; - - - ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN; - addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len); - if (mac) - addattr_l (&req.n, sizeof (req), NDA_LLADDR, mac, 6); - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Tx %s family %s IF %s(%u) Neigh %s MAC %s", - nl_msg_type_to_str (cmd), - nl_family_to_str (req.ndm.ndm_family), - ifp->name, ifp->ifindex, - ipaddr2str (ip, buf, sizeof(buf)), - mac ? prefix_mac2str (mac, buf2, sizeof (buf2)) : "null"); - - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; + int ipa_len; + + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + char buf[INET6_ADDRSTRLEN]; + char buf2[ETHER_ADDR_STRLEN]; + + memset(&req.n, 0, sizeof(req.n)); + memset(&req.ndm, 0, sizeof(req.ndm)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + if (cmd == RTM_NEWNEIGH) + req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); + req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH + req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6; + req.ndm.ndm_state = flags; + req.ndm.ndm_ifindex = ifp->ifindex; + req.ndm.ndm_type = RTN_UNICAST; + req.ndm.ndm_flags = NTF_EXT_LEARNED; + + + ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN; + addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len); + if (mac) + addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s", + nl_msg_type_to_str(cmd), + nl_family_to_str(req.ndm.ndm_family), ifp->name, + ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)), + mac ? prefix_mac2str(mac, buf2, sizeof(buf2)) + : "null"); + + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } -int -kernel_add_mac (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, - u_char sticky) +int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, + struct in_addr vtep_ip, u_char sticky) { - return netlink_macfdb_update (ifp, vid, mac, vtep_ip, 0, RTM_NEWNEIGH, sticky); + return netlink_macfdb_update(ifp, vid, mac, vtep_ip, 0, RTM_NEWNEIGH, + sticky); } -int -kernel_del_mac (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, int local) +int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, + struct in_addr vtep_ip, int local) { - return netlink_macfdb_update (ifp, vid, mac, vtep_ip, local, RTM_DELNEIGH, 0); + return netlink_macfdb_update(ifp, vid, mac, vtep_ip, local, + RTM_DELNEIGH, 0); } -int kernel_add_neigh (struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac) +int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, + struct ethaddr *mac) { - return netlink_neigh_update2 (ifp, ip, mac, NUD_REACHABLE, - RTM_NEWNEIGH); + return netlink_neigh_update2(ifp, ip, mac, NUD_REACHABLE, RTM_NEWNEIGH); } -int kernel_del_neigh (struct interface *ifp, struct ipaddr *ip) +int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip) { - return netlink_neigh_update2 (ifp, ip, NULL, 0, RTM_DELNEIGH); + return netlink_neigh_update2(ifp, ip, NULL, 0, RTM_DELNEIGH); } /* * MPLS label forwarding table change via netlink interface. */ -int -netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp) +int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) { - mpls_lse_t lse; - zebra_nhlfe_t *nhlfe; - struct nexthop *nexthop = NULL; - unsigned int nexthop_num; - const char *routedesc; - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - - struct - { - struct nlmsghdr n; - struct rtmsg r; - char buf[NL_PKT_BUF_SIZE]; - } req; - - memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); - - - /* - * Count # nexthops so we can decide whether to use singlepath - * or multipath case. - */ - nexthop_num = 0; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - nexthop = nhlfe->nexthop; - if (!nexthop) - continue; - if (cmd == RTM_NEWROUTE) - { - /* Count all selected NHLFEs */ - if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - nexthop_num++; - } - else /* DEL */ - { - /* Count all installed NHLFEs */ - if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - nexthop_num++; - } - } - - if (nexthop_num == 0) // unexpected - return 0; - - req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); - req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; - req.n.nlmsg_type = cmd; - req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; - - req.r.rtm_family = AF_MPLS; - req.r.rtm_table = RT_TABLE_MAIN; - req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS; - req.r.rtm_protocol = RTPROT_ZEBRA; - req.r.rtm_scope = RT_SCOPE_UNIVERSE; - req.r.rtm_type = RTN_UNICAST; - - if (cmd == RTM_NEWROUTE) - /* We do a replace to handle update. */ - req.n.nlmsg_flags |= NLM_F_REPLACE; - - /* Fill destination */ - lse = mpls_lse_encode (lsp->ile.in_label, 0, 0, 1); - addattr_l (&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t)); - - /* Fill nexthops (paths) based on single-path or multipath. The paths - * chosen depend on the operation. - */ - if (nexthop_num == 1 || multipath_num == 1) - { - routedesc = "single hop"; - _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); - - nexthop_num = 0; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - nexthop = nhlfe->nexthop; - if (!nexthop) - continue; - - if ((cmd == RTM_NEWROUTE && - (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) || - (cmd == RTM_DELROUTE && - (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))) - { - /* Add the gateway */ - _netlink_mpls_build_singlepath(routedesc, nhlfe, - &req.n, &req.r, sizeof req, cmd); - if (cmd == RTM_NEWROUTE) - { - SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - else - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - nexthop_num++; - break; - } - } - } - else /* Multipath case */ - { - char buf[NL_PKT_BUF_SIZE]; - struct rtattr *rta = (void *) buf; - struct rtnexthop *rtnh; - union g_addr *src1 = NULL; - - rta->rta_type = RTA_MULTIPATH; - rta->rta_len = RTA_LENGTH (0); - rtnh = RTA_DATA (rta); - - routedesc = "multihop"; - _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); - - nexthop_num = 0; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - nexthop = nhlfe->nexthop; - if (!nexthop) - continue; - - if (nexthop_num >= multipath_num) - break; - - if ((cmd == RTM_NEWROUTE && - (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) || - (cmd == RTM_DELROUTE && - (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))) - { - nexthop_num++; - - /* Build the multipath */ - _netlink_mpls_build_multipath(routedesc, nhlfe, rta, - rtnh, &req.r, &src1); - rtnh = RTNH_NEXT (rtnh); - - if (cmd == RTM_NEWROUTE) - { - SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - else - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - - } - } - - /* Add the multipath */ - if (rta->rta_len > RTA_LENGTH (0)) - addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta), - RTA_PAYLOAD (rta)); - } - - /* Talk to netlink socket. */ - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + mpls_lse_t lse; + zebra_nhlfe_t *nhlfe; + struct nexthop *nexthop = NULL; + unsigned int nexthop_num; + const char *routedesc; + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + + struct { + struct nlmsghdr n; + struct rtmsg r; + char buf[NL_PKT_BUF_SIZE]; + } req; + + memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); + + + /* + * Count # nexthops so we can decide whether to use singlepath + * or multipath case. + */ + nexthop_num = 0; + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + nexthop = nhlfe->nexthop; + if (!nexthop) + continue; + if (cmd == RTM_NEWROUTE) { + /* Count all selected NHLFEs */ + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + nexthop_num++; + } else /* DEL */ + { + /* Count all installed NHLFEs */ + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) + nexthop_num++; + } + } + + if (nexthop_num == 0) // unexpected + return 0; + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; + req.n.nlmsg_type = cmd; + req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; + + req.r.rtm_family = AF_MPLS; + req.r.rtm_table = RT_TABLE_MAIN; + req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS; + req.r.rtm_protocol = RTPROT_ZEBRA; + req.r.rtm_scope = RT_SCOPE_UNIVERSE; + req.r.rtm_type = RTN_UNICAST; + + if (cmd == RTM_NEWROUTE) + /* We do a replace to handle update. */ + req.n.nlmsg_flags |= NLM_F_REPLACE; + + /* Fill destination */ + lse = mpls_lse_encode(lsp->ile.in_label, 0, 0, 1); + addattr_l(&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t)); + + /* Fill nexthops (paths) based on single-path or multipath. The paths + * chosen depend on the operation. + */ + if (nexthop_num == 1 || multipath_num == 1) { + routedesc = "single hop"; + _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); + + nexthop_num = 0; + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + nexthop = nhlfe->nexthop; + if (!nexthop) + continue; + + if ((cmd == RTM_NEWROUTE + && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_ACTIVE))) + || (cmd == RTM_DELROUTE + && (CHECK_FLAG(nhlfe->flags, + NHLFE_FLAG_INSTALLED) + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB)))) { + /* Add the gateway */ + _netlink_mpls_build_singlepath(routedesc, nhlfe, + &req.n, &req.r, + sizeof req, cmd); + if (cmd == RTM_NEWROUTE) { + SET_FLAG(nhlfe->flags, + NHLFE_FLAG_INSTALLED); + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + } else { + UNSET_FLAG(nhlfe->flags, + NHLFE_FLAG_INSTALLED); + UNSET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + } + nexthop_num++; + break; + } + } + } else /* Multipath case */ + { + char buf[NL_PKT_BUF_SIZE]; + struct rtattr *rta = (void *)buf; + struct rtnexthop *rtnh; + union g_addr *src1 = NULL; + + rta->rta_type = RTA_MULTIPATH; + rta->rta_len = RTA_LENGTH(0); + rtnh = RTA_DATA(rta); + + routedesc = "multihop"; + _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); + + nexthop_num = 0; + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + nexthop = nhlfe->nexthop; + if (!nexthop) + continue; + + if (nexthop_num >= multipath_num) + break; + + if ((cmd == RTM_NEWROUTE + && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_ACTIVE))) + || (cmd == RTM_DELROUTE + && (CHECK_FLAG(nhlfe->flags, + NHLFE_FLAG_INSTALLED) + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB)))) { + nexthop_num++; + + /* Build the multipath */ + _netlink_mpls_build_multipath(routedesc, nhlfe, + rta, rtnh, &req.r, + &src1); + rtnh = RTNH_NEXT(rtnh); + + if (cmd == RTM_NEWROUTE) { + SET_FLAG(nhlfe->flags, + NHLFE_FLAG_INSTALLED); + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + } else { + UNSET_FLAG(nhlfe->flags, + NHLFE_FLAG_INSTALLED); + UNSET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + } + } + } + + /* Add the multipath */ + if (rta->rta_len > RTA_LENGTH(0)) + addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, + RTA_DATA(rta), RTA_PAYLOAD(rta)); + } + + /* Talk to netlink socket. */ + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } /* * Handle failure in LSP install, clear flags for NHLFE. */ -void -clear_nhlfe_installed (zebra_lsp_t *lsp) +void clear_nhlfe_installed(zebra_lsp_t *lsp) { - zebra_nhlfe_t *nhlfe; - struct nexthop *nexthop; - - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - nexthop = nhlfe->nexthop; - if (!nexthop) - continue; - - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } + zebra_nhlfe_t *nhlfe; + struct nexthop *nexthop; + + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + nexthop = nhlfe->nexthop; + if (!nexthop) + continue; + + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } } diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 8b061fc2e..e607dda6f 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -40,25 +40,24 @@ #define RTPROT_EIGRP 192 #define RTPROT_LDP 193 -void rt_netlink_init (void); +void rt_netlink_init(void); -extern void -clear_nhlfe_installed (zebra_lsp_t *lsp); -extern int -netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp); +extern void clear_nhlfe_installed(zebra_lsp_t *lsp); +extern int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp); -extern int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup); -extern int netlink_route_read (struct zebra_ns *zns); +extern int netlink_route_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup); +extern int netlink_route_read(struct zebra_ns *zns); -extern int netlink_neigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id); -extern int netlink_macfdb_read (struct zebra_ns *zns); -extern int netlink_macfdb_read_for_bridge (struct zebra_ns *zns, - struct interface *ifp, struct interface *br_if); -extern int netlink_neigh_read (struct zebra_ns *zns); -extern int netlink_neigh_read_for_vlan (struct zebra_ns *zns, - struct interface *vlan_if); +extern int netlink_neigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id); +extern int netlink_macfdb_read(struct zebra_ns *zns); +extern int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, + struct interface *ifp, + struct interface *br_if); +extern int netlink_neigh_read(struct zebra_ns *zns); +extern int netlink_neigh_read_for_vlan(struct zebra_ns *zns, + struct interface *vlan_if); #endif /* HAVE_NETLINK */ diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index fd8010ca0..827d39870 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -40,316 +40,305 @@ extern struct zebra_privs_t zserv_privs; /* kernel socket export */ -extern int rtm_write (int message, union sockunion *dest, - union sockunion *mask, union sockunion *gate, - union sockunion *mpls, unsigned int index, - int zebra_flags, int metric); +extern int rtm_write(int message, union sockunion *dest, union sockunion *mask, + union sockunion *gate, union sockunion *mpls, + unsigned int index, int zebra_flags, int metric); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN /* Adjust netmask socket length. Return value is a adjusted sin_len value. */ -static int -sin_masklen (struct in_addr mask) +static int sin_masklen(struct in_addr mask) { - char *p, *lim; - int len; - struct sockaddr_in sin; + char *p, *lim; + int len; + struct sockaddr_in sin; - if (mask.s_addr == 0) - return sizeof (long); + if (mask.s_addr == 0) + return sizeof(long); - sin.sin_addr = mask; - len = sizeof (struct sockaddr_in); + sin.sin_addr = mask; + len = sizeof(struct sockaddr_in); - lim = (char *) &sin.sin_addr; - p = lim + sizeof (sin.sin_addr); + lim = (char *)&sin.sin_addr; + p = lim + sizeof(sin.sin_addr); - while (*--p == 0 && p >= lim) - len--; - return len; + while (*--p == 0 && p >= lim) + len--; + return len; } #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ /* Interface between zebra message and rtm message. */ -static int -kernel_rtm_ipv4 (int cmd, struct prefix *p, struct route_entry *re) +static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re) { - struct sockaddr_in *mask = NULL; - struct sockaddr_in sin_dest, sin_mask, sin_gate; + struct sockaddr_in *mask = NULL; + struct sockaddr_in sin_dest, sin_mask, sin_gate; #ifdef __OpenBSD__ - struct sockaddr_mpls smpls; + struct sockaddr_mpls smpls; #endif - union sockunion *smplsp = NULL; - struct nexthop *nexthop; - int nexthop_num = 0; - ifindex_t ifindex = 0; - int gate = 0; - int error; - char prefix_buf[PREFIX_STRLEN]; - - if (IS_ZEBRA_DEBUG_RIB) - prefix2str (p, prefix_buf, sizeof(prefix_buf)); - memset (&sin_dest, 0, sizeof (struct sockaddr_in)); - sin_dest.sin_family = AF_INET; + union sockunion *smplsp = NULL; + struct nexthop *nexthop; + int nexthop_num = 0; + ifindex_t ifindex = 0; + int gate = 0; + int error; + char prefix_buf[PREFIX_STRLEN]; + + if (IS_ZEBRA_DEBUG_RIB) + prefix2str(p, prefix_buf, sizeof(prefix_buf)); + memset(&sin_dest, 0, sizeof(struct sockaddr_in)); + sin_dest.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_dest.sin_len = sizeof (struct sockaddr_in); + sin_dest.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - sin_dest.sin_addr = p->u.prefix4; + sin_dest.sin_addr = p->u.prefix4; - memset (&sin_mask, 0, sizeof (struct sockaddr_in)); + memset(&sin_mask, 0, sizeof(struct sockaddr_in)); - memset (&sin_gate, 0, sizeof (struct sockaddr_in)); - sin_gate.sin_family = AF_INET; + memset(&sin_gate, 0, sizeof(struct sockaddr_in)); + sin_gate.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_gate.sin_len = sizeof (struct sockaddr_in); + sin_gate.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - /* Make gateway. */ - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - - gate = 0; - char gate_buf[INET_ADDRSTRLEN] = "NULL"; - - /* - * XXX We need to refrain from kernel operations in some cases, - * but this if statement seems overly cautious - what about - * other than ADD and DELETE? - */ - if ((cmd == RTM_ADD - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - || (cmd == RTM_DELETE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) - )) - { - if (nexthop->type == NEXTHOP_TYPE_IPV4 || - nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - sin_gate.sin_addr = nexthop->gate.ipv4; - gate = 1; - } - if (nexthop->type == NEXTHOP_TYPE_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - ifindex = nexthop->ifindex; - if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) - { - struct in_addr loopback; - loopback.s_addr = htonl (INADDR_LOOPBACK); - sin_gate.sin_addr = loopback; - gate = 1; - } - - if (gate && p->prefixlen == 32) - mask = NULL; - else - { - masklen2ip (p->prefixlen, &sin_mask.sin_addr); - sin_mask.sin_family = AF_INET; + /* Make gateway. */ + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + + gate = 0; + char gate_buf[INET_ADDRSTRLEN] = "NULL"; + + /* + * XXX We need to refrain from kernel operations in some cases, + * but this if statement seems overly cautious - what about + * other than ADD and DELETE? + */ + if ((cmd == RTM_ADD + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + || (cmd == RTM_DELETE + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))) { + if (nexthop->type == NEXTHOP_TYPE_IPV4 + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + sin_gate.sin_addr = nexthop->gate.ipv4; + gate = 1; + } + if (nexthop->type == NEXTHOP_TYPE_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) + ifindex = nexthop->ifindex; + if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) { + struct in_addr loopback; + loopback.s_addr = htonl(INADDR_LOOPBACK); + sin_gate.sin_addr = loopback; + gate = 1; + } + + if (gate && p->prefixlen == 32) + mask = NULL; + else { + masklen2ip(p->prefixlen, &sin_mask.sin_addr); + sin_mask.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_mask.sin_len = sin_masklen (sin_mask.sin_addr); + sin_mask.sin_len = + sin_masklen(sin_mask.sin_addr); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - mask = &sin_mask; - } + mask = &sin_mask; + } #ifdef __OpenBSD__ - if (nexthop->nh_label) - { - memset (&smpls, 0, sizeof (smpls)); - smpls.smpls_len = sizeof (smpls); - smpls.smpls_family = AF_MPLS; - smpls.smpls_label = - htonl (nexthop->nh_label->label[0] << MPLS_LABEL_OFFSET); - smplsp = (union sockunion *)&smpls; - } + if (nexthop->nh_label) { + memset(&smpls, 0, sizeof(smpls)); + smpls.smpls_len = sizeof(smpls); + smpls.smpls_family = AF_MPLS; + smpls.smpls_label = + htonl(nexthop->nh_label->label[0] + << MPLS_LABEL_OFFSET); + smplsp = (union sockunion *)&smpls; + } #endif - error = rtm_write (cmd, - (union sockunion *)&sin_dest, - (union sockunion *)mask, - gate ? (union sockunion *)&sin_gate : NULL, - smplsp, - ifindex, - re->flags, - re->metric); - - if (IS_ZEBRA_DEBUG_RIB) - { - if (!gate) - { - zlog_debug ("%s: %s: attention! gate not found for re %p", - __func__, prefix_buf, re); - route_entry_dump (p, NULL, re); - } - else - inet_ntop (AF_INET, &sin_gate.sin_addr, gate_buf, INET_ADDRSTRLEN); - } - - switch (error) - { - /* We only flag nexthops as being in FIB if rtm_write() did its work. */ - case ZEBRA_ERR_NOERROR: - nexthop_num++; - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%s: %s: successfully did NH %s", - __func__, prefix_buf, gate_buf); - if (cmd == RTM_ADD) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - break; - - /* The only valid case for this error is kernel's failure to install - * a multipath route, which is common for FreeBSD. This should be - * ignored silently, but logged as an error otherwise. - */ - case ZEBRA_ERR_RTEXIST: - if (cmd != RTM_ADD) - zlog_err ("%s: rtm_write() returned %d for command %d", - __func__, error, cmd); - continue; - break; - - /* Given that our NEXTHOP_FLAG_FIB matches real kernel FIB, it isn't - * normal to get any other messages in ANY case. - */ - case ZEBRA_ERR_RTNOEXIST: - case ZEBRA_ERR_RTUNREACH: - default: - zlog_err ("%s: %s: rtm_write() unexpectedly returned %d for command %s", - __func__, prefix2str(p, prefix_buf, sizeof(prefix_buf)), - error, lookup_msg(rtm_type_str, cmd, NULL)); - break; - } - } /* if (cmd and flags make sense) */ - else - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%s: odd command %s for flags %d", - __func__, lookup_msg(rtm_type_str, cmd, NULL), nexthop->flags); - } /* for (ALL_NEXTHOPS(...))*/ - - /* If there was no useful nexthop, then complain. */ - if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: No useful nexthops were found in RIB entry %p", __func__, re); - - return 0; /*XXX*/ + error = rtm_write( + cmd, (union sockunion *)&sin_dest, + (union sockunion *)mask, + gate ? (union sockunion *)&sin_gate : NULL, + smplsp, ifindex, re->flags, re->metric); + + if (IS_ZEBRA_DEBUG_RIB) { + if (!gate) { + zlog_debug( + "%s: %s: attention! gate not found for re %p", + __func__, prefix_buf, re); + route_entry_dump(p, NULL, re); + } else + inet_ntop(AF_INET, &sin_gate.sin_addr, + gate_buf, INET_ADDRSTRLEN); + } + + switch (error) { + /* We only flag nexthops as being in FIB if rtm_write() + * did its work. */ + case ZEBRA_ERR_NOERROR: + nexthop_num++; + if (IS_ZEBRA_DEBUG_RIB) + zlog_debug( + "%s: %s: successfully did NH %s", + __func__, prefix_buf, gate_buf); + if (cmd == RTM_ADD) + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + break; + + /* The only valid case for this error is kernel's + * failure to install + * a multipath route, which is common for FreeBSD. This + * should be + * ignored silently, but logged as an error otherwise. + */ + case ZEBRA_ERR_RTEXIST: + if (cmd != RTM_ADD) + zlog_err( + "%s: rtm_write() returned %d for command %d", + __func__, error, cmd); + continue; + break; + + /* Given that our NEXTHOP_FLAG_FIB matches real kernel + * FIB, it isn't + * normal to get any other messages in ANY case. + */ + case ZEBRA_ERR_RTNOEXIST: + case ZEBRA_ERR_RTUNREACH: + default: + zlog_err( + "%s: %s: rtm_write() unexpectedly returned %d for command %s", + __func__, + prefix2str(p, prefix_buf, + sizeof(prefix_buf)), + error, + lookup_msg(rtm_type_str, cmd, NULL)); + break; + } + } /* if (cmd and flags make sense) */ + else if (IS_ZEBRA_DEBUG_RIB) + zlog_debug("%s: odd command %s for flags %d", __func__, + lookup_msg(rtm_type_str, cmd, NULL), + nexthop->flags); + } /* for (ALL_NEXTHOPS(...))*/ + + /* If there was no useful nexthop, then complain. */ + if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: No useful nexthops were found in RIB entry %p", + __func__, re); + + return 0; /*XXX*/ } #ifdef SIN6_LEN /* Calculate sin6_len value for netmask socket value. */ -static int -sin6_masklen (struct in6_addr mask) +static int sin6_masklen(struct in6_addr mask) { - struct sockaddr_in6 sin6; - char *p, *lim; - int len; + struct sockaddr_in6 sin6; + char *p, *lim; + int len; - if (IN6_IS_ADDR_UNSPECIFIED (&mask)) - return sizeof (long); + if (IN6_IS_ADDR_UNSPECIFIED(&mask)) + return sizeof(long); - sin6.sin6_addr = mask; - len = sizeof (struct sockaddr_in6); + sin6.sin6_addr = mask; + len = sizeof(struct sockaddr_in6); - lim = (char *) & sin6.sin6_addr; - p = lim + sizeof (sin6.sin6_addr); + lim = (char *)&sin6.sin6_addr; + p = lim + sizeof(sin6.sin6_addr); - while (*--p == 0 && p >= lim) - len--; + while (*--p == 0 && p >= lim) + len--; - return len; + return len; } #endif /* SIN6_LEN */ /* Interface between zebra message and rtm message. */ -static int -kernel_rtm_ipv6 (int cmd, struct prefix *p, struct route_entry *re) +static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re) { - struct sockaddr_in6 *mask; - struct sockaddr_in6 sin_dest, sin_mask, sin_gate; - struct nexthop *nexthop; - int nexthop_num = 0; - ifindex_t ifindex = 0; - int gate = 0; - int error; - - memset (&sin_dest, 0, sizeof (struct sockaddr_in6)); - sin_dest.sin6_family = AF_INET6; + struct sockaddr_in6 *mask; + struct sockaddr_in6 sin_dest, sin_mask, sin_gate; + struct nexthop *nexthop; + int nexthop_num = 0; + ifindex_t ifindex = 0; + int gate = 0; + int error; + + memset(&sin_dest, 0, sizeof(struct sockaddr_in6)); + sin_dest.sin6_family = AF_INET6; #ifdef SIN6_LEN - sin_dest.sin6_len = sizeof (struct sockaddr_in6); + sin_dest.sin6_len = sizeof(struct sockaddr_in6); #endif /* SIN6_LEN */ - sin_dest.sin6_addr = p->u.prefix6; + sin_dest.sin6_addr = p->u.prefix6; - memset (&sin_mask, 0, sizeof (struct sockaddr_in6)); + memset(&sin_mask, 0, sizeof(struct sockaddr_in6)); - memset (&sin_gate, 0, sizeof (struct sockaddr_in6)); - sin_gate.sin6_family = AF_INET6; + memset(&sin_gate, 0, sizeof(struct sockaddr_in6)); + sin_gate.sin6_family = AF_INET6; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_gate.sin6_len = sizeof (struct sockaddr_in6); + sin_gate.sin6_len = sizeof(struct sockaddr_in6); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - /* Make gateway. */ - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; + /* Make gateway. */ + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; - gate = 0; + gate = 0; - if ((cmd == RTM_ADD - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - || (cmd == RTM_DELETE + if ((cmd == RTM_ADD + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + || (cmd == RTM_DELETE #if 0 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) #endif - )) - { - if (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - sin_gate.sin6_addr = nexthop->gate.ipv6; - gate = 1; - } - if (nexthop->type == NEXTHOP_TYPE_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - ifindex = nexthop->ifindex; - - if (cmd == RTM_ADD) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - - /* Under kame set interface index to link local address. */ + )) { + if (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + sin_gate.sin6_addr = nexthop->gate.ipv6; + gate = 1; + } + if (nexthop->type == NEXTHOP_TYPE_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) + ifindex = nexthop->ifindex; + + if (cmd == RTM_ADD) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } + +/* Under kame set interface index to link local address. */ #ifdef KAME -#define SET_IN6_LINKLOCAL_IFINDEX(a, i) \ - do { \ - (a).s6_addr[2] = ((i) >> 8) & 0xff; \ - (a).s6_addr[3] = (i) & 0xff; \ - } while (0) +#define SET_IN6_LINKLOCAL_IFINDEX(a, i) \ + do { \ + (a).s6_addr[2] = ((i) >> 8) & 0xff; \ + (a).s6_addr[3] = (i)&0xff; \ + } while (0) - if (gate && IN6_IS_ADDR_LINKLOCAL(&sin_gate.sin6_addr)) - SET_IN6_LINKLOCAL_IFINDEX (sin_gate.sin6_addr, ifindex); + if (gate && IN6_IS_ADDR_LINKLOCAL(&sin_gate.sin6_addr)) + SET_IN6_LINKLOCAL_IFINDEX(sin_gate.sin6_addr, ifindex); #endif /* KAME */ - if (gate && p->prefixlen == 128) - mask = NULL; - else - { - masklen2ip6 (p->prefixlen, &sin_mask.sin6_addr); - sin_mask.sin6_family = AF_INET6; + if (gate && p->prefixlen == 128) + mask = NULL; + else { + masklen2ip6(p->prefixlen, &sin_mask.sin6_addr); + sin_mask.sin6_family = AF_INET6; #ifdef SIN6_LEN - sin_mask.sin6_len = sin6_masklen (sin_mask.sin6_addr); + sin_mask.sin6_len = sin6_masklen(sin_mask.sin6_addr); #endif /* SIN6_LEN */ - mask = &sin_mask; - } + mask = &sin_mask; + } - error = rtm_write (cmd, - (union sockunion *) &sin_dest, - (union sockunion *) mask, - gate ? (union sockunion *)&sin_gate : NULL, - NULL, - ifindex, - re->flags, - re->metric); + error = rtm_write(cmd, (union sockunion *)&sin_dest, + (union sockunion *)mask, + gate ? (union sockunion *)&sin_gate : NULL, + NULL, ifindex, re->flags, re->metric); #if 0 if (error) @@ -358,110 +347,99 @@ kernel_rtm_ipv6 (int cmd, struct prefix *p, struct route_entry *re) nexthop_num, error); } #else - (void)error; + (void)error; #endif - nexthop_num++; - } + nexthop_num++; + } - /* If there is no useful nexthop then return. */ - if (nexthop_num == 0) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("kernel_rtm_ipv6(): No useful nexthop."); - return 0; - } + /* If there is no useful nexthop then return. */ + if (nexthop_num == 0) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("kernel_rtm_ipv6(): No useful nexthop."); + return 0; + } - return 0; /*XXX*/ + return 0; /*XXX*/ } -static int -kernel_rtm (int cmd, struct prefix *p, struct route_entry *re) +static int kernel_rtm(int cmd, struct prefix *p, struct route_entry *re) { - switch (PREFIX_FAMILY(p)) - { - case AF_INET: - return kernel_rtm_ipv4 (cmd, p, re); - case AF_INET6: - return kernel_rtm_ipv6 (cmd, p, re); - } - return 0; + switch (PREFIX_FAMILY(p)) { + case AF_INET: + return kernel_rtm_ipv4(cmd, p, re); + case AF_INET6: + return kernel_rtm_ipv6(cmd, p, re); + } + return 0; } -int -kernel_route_rib (struct prefix *p, struct prefix *src_p, - struct route_entry *old, struct route_entry *new) +int kernel_route_rib(struct prefix *p, struct prefix *src_p, + struct route_entry *old, struct route_entry *new) { - int route = 0; + int route = 0; - if (src_p && src_p->prefixlen) - { - zlog_err ("route add: IPv6 sourcedest routes unsupported!"); - return 1; - } + if (src_p && src_p->prefixlen) { + zlog_err("route add: IPv6 sourcedest routes unsupported!"); + return 1; + } - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); - if (old) - route |= kernel_rtm (RTM_DELETE, p, old); + if (old) + route |= kernel_rtm(RTM_DELETE, p, old); - if (new) - route |= kernel_rtm (RTM_ADD, p, new); + if (new) + route |= kernel_rtm(RTM_ADD, p, new); - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); - return route; + return route; } -int -kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen) +int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, + int llalen) { - /* TODO */ - return 0; + /* TODO */ + return 0; } -extern int -kernel_get_ipmr_sg_stats (void *mroute) +extern int kernel_get_ipmr_sg_stats(void *mroute) { - return 0; + return 0; } -int -kernel_add_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) +int kernel_add_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) { - return 0; + return 0; } -int -kernel_del_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) +int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) { - return 0; + return 0; } -int -kernel_add_mac (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, - u_char sticky) +int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, + struct in_addr vtep_ip, u_char sticky) { - return 0; + return 0; } -int -kernel_del_mac (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, int local) +int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, + struct in_addr vtep_ip, int local) { - return 0; + return 0; } -int kernel_add_neigh (struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac) +int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, + struct ethaddr *mac) { - return 0; + return 0; } -int kernel_del_neigh (struct interface *ifp, struct ipaddr *ip) +int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip) { - return 0; + return 0; } diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 589ecc949..b8cf2d490 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -45,7 +45,7 @@ extern struct zebra_privs_t zserv_privs; -#if defined (HAVE_RTADV) +#if defined(HAVE_RTADV) #ifdef OPEN_BSD #include <netinet/icmp6.h> @@ -62,743 +62,722 @@ extern struct zebra_privs_t zserv_privs; #define ALLNODE "ff02::1" #define ALLROUTER "ff02::2" -enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER, - RTADV_TIMER_MSEC, RTADV_READ}; +enum rtadv_event { + RTADV_START, + RTADV_STOP, + RTADV_TIMER, + RTADV_TIMER_MSEC, + RTADV_READ +}; -static void rtadv_event (struct zebra_ns *, enum rtadv_event, int); +static void rtadv_event(struct zebra_ns *, enum rtadv_event, int); -static int if_join_all_router (int, struct interface *); -static int if_leave_all_router (int, struct interface *); +static int if_join_all_router(int, struct interface *); +static int if_leave_all_router(int, struct interface *); -static int -rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex) +static int rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex) { - int ret = -1; - struct interface *iface; - struct zebra_if *zif; - - iface = if_lookup_by_index_per_ns (zns, *ifindex); - if (iface && iface->info) - { - zif = iface->info; - zif->ra_rcvd++; - ret = 0; - } - return ret; + int ret = -1; + struct interface *iface; + struct zebra_if *zif; + + iface = if_lookup_by_index_per_ns(zns, *ifindex); + if (iface && iface->info) { + zif = iface->info; + zif->ra_rcvd++; + ret = 0; + } + return ret; } -static int -rtadv_recv_packet (struct zebra_ns *zns, int sock, u_char *buf, int buflen, - struct sockaddr_in6 *from, ifindex_t *ifindex, - int *hoplimit) +static int rtadv_recv_packet(struct zebra_ns *zns, int sock, u_char *buf, + int buflen, struct sockaddr_in6 *from, + ifindex_t *ifindex, int *hoplimit) { - int ret; - struct msghdr msg; - struct iovec iov; - struct cmsghdr *cmsgptr; - struct in6_addr dst; - - char adata[1024]; - - /* Fill in message and iovec. */ - msg.msg_name = (void *) from; - msg.msg_namelen = sizeof (struct sockaddr_in6); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = (void *) adata; - msg.msg_controllen = sizeof adata; - iov.iov_base = buf; - iov.iov_len = buflen; - - /* If recvmsg fail return minus value. */ - ret = recvmsg (sock, &msg, 0); - if (ret < 0) - return ret; - - for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL; - cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) - { - /* I want interface index which this packet comes from. */ - if (cmsgptr->cmsg_level == IPPROTO_IPV6 && - cmsgptr->cmsg_type == IPV6_PKTINFO) - { - struct in6_pktinfo *ptr; - - ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr); - *ifindex = ptr->ipi6_ifindex; - memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr)); - } - - /* Incoming packet's hop limit. */ - if (cmsgptr->cmsg_level == IPPROTO_IPV6 && - cmsgptr->cmsg_type == IPV6_HOPLIMIT) - { - int *hoptr = (int *) CMSG_DATA (cmsgptr); - *hoplimit = *hoptr; + int ret; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsgptr; + struct in6_addr dst; + + char adata[1024]; + + /* Fill in message and iovec. */ + msg.msg_name = (void *)from; + msg.msg_namelen = sizeof(struct sockaddr_in6); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (void *)adata; + msg.msg_controllen = sizeof adata; + iov.iov_base = buf; + iov.iov_len = buflen; + + /* If recvmsg fail return minus value. */ + ret = recvmsg(sock, &msg, 0); + if (ret < 0) + return ret; + + for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL; + cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { + /* I want interface index which this packet comes from. */ + if (cmsgptr->cmsg_level == IPPROTO_IPV6 + && cmsgptr->cmsg_type == IPV6_PKTINFO) { + struct in6_pktinfo *ptr; + + ptr = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + *ifindex = ptr->ipi6_ifindex; + memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr)); + } + + /* Incoming packet's hop limit. */ + if (cmsgptr->cmsg_level == IPPROTO_IPV6 + && cmsgptr->cmsg_type == IPV6_HOPLIMIT) { + int *hoptr = (int *)CMSG_DATA(cmsgptr); + *hoplimit = *hoptr; + } } - } - rtadv_increment_received(zns, ifindex); - return ret; + rtadv_increment_received(zns, ifindex); + return ret; } #define RTADV_MSG_SIZE 4096 /* Send router advertisement packet. */ -static void -rtadv_send_packet (int sock, struct interface *ifp) +static void rtadv_send_packet(int sock, struct interface *ifp) { - struct msghdr msg; - struct iovec iov; - struct cmsghdr *cmsgptr; - struct in6_pktinfo *pkt; - struct sockaddr_in6 addr; - static void *adata = NULL; - unsigned char buf[RTADV_MSG_SIZE]; - struct nd_router_advert *rtadv; - int ret; - int len = 0; - struct zebra_if *zif; - struct rtadv_prefix *rprefix; - u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; - struct listnode *node; - u_int16_t pkt_RouterLifetime; - - /* - * Allocate control message bufffer. This is dynamic because - * CMSG_SPACE is not guaranteed not to call a function. Note that - * the size will be different on different architectures due to - * differing alignment rules. - */ - if (adata == NULL) - { - /* XXX Free on shutdown. */ - adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo))); - - if (adata == NULL) - zlog_err("rtadv_send_packet: can't malloc control data"); - } - - /* Logging of packet. */ - if (IS_ZEBRA_DEBUG_PACKET) - zlog_debug ("%s(%u): Tx RA, socket %u", - ifp->name, ifp->ifindex, sock); - - /* Fill in sockaddr_in6. */ - memset (&addr, 0, sizeof (struct sockaddr_in6)); - addr.sin6_family = AF_INET6; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsgptr; + struct in6_pktinfo *pkt; + struct sockaddr_in6 addr; + static void *adata = NULL; + unsigned char buf[RTADV_MSG_SIZE]; + struct nd_router_advert *rtadv; + int ret; + int len = 0; + struct zebra_if *zif; + struct rtadv_prefix *rprefix; + u_char all_nodes_addr[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1}; + struct listnode *node; + u_int16_t pkt_RouterLifetime; + + /* + * Allocate control message bufffer. This is dynamic because + * CMSG_SPACE is not guaranteed not to call a function. Note that + * the size will be different on different architectures due to + * differing alignment rules. + */ + if (adata == NULL) { + /* XXX Free on shutdown. */ + adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo))); + + if (adata == NULL) + zlog_err( + "rtadv_send_packet: can't malloc control data"); + } + + /* Logging of packet. */ + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug("%s(%u): Tx RA, socket %u", ifp->name, ifp->ifindex, + sock); + + /* Fill in sockaddr_in6. */ + memset(&addr, 0, sizeof(struct sockaddr_in6)); + addr.sin6_family = AF_INET6; #ifdef SIN6_LEN - addr.sin6_len = sizeof (struct sockaddr_in6); + addr.sin6_len = sizeof(struct sockaddr_in6); #endif /* SIN6_LEN */ - addr.sin6_port = htons (IPPROTO_ICMPV6); - IPV6_ADDR_COPY (&addr.sin6_addr, all_nodes_addr); - - /* Fetch interface information. */ - zif = ifp->info; - - /* Make router advertisement message. */ - rtadv = (struct nd_router_advert *) buf; - - rtadv->nd_ra_type = ND_ROUTER_ADVERT; - rtadv->nd_ra_code = 0; - rtadv->nd_ra_cksum = 0; - - rtadv->nd_ra_curhoplimit = 64; - - /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */ - rtadv->nd_ra_flags_reserved = - zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference; - rtadv->nd_ra_flags_reserved <<= 3; - - if (zif->rtadv.AdvManagedFlag) - rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED; - if (zif->rtadv.AdvOtherConfigFlag) - rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER; - if (zif->rtadv.AdvHomeAgentFlag) - rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT; - /* Note that according to Neighbor Discovery (RFC 4861 [18]), - * AdvDefaultLifetime is by default based on the value of - * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime - * field of Router Advertisements. Given that this field is expressed - * in seconds, a small MaxRtrAdvInterval value can result in a zero - * value for this field. To prevent this, routers SHOULD keep - * AdvDefaultLifetime in at least one second, even if the use of - * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */ - pkt_RouterLifetime = zif->rtadv.AdvDefaultLifetime != -1 ? - zif->rtadv.AdvDefaultLifetime : - MAX (1, 0.003 * zif->rtadv.MaxRtrAdvInterval); - rtadv->nd_ra_router_lifetime = htons (pkt_RouterLifetime); - rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime); - rtadv->nd_ra_retransmit = htonl (0); - - len = sizeof (struct nd_router_advert); - - /* If both the Home Agent Preference and Home Agent Lifetime are set to - * their default values specified above, this option SHOULD NOT be - * included in the Router Advertisement messages sent by this home - * agent. -- RFC6275, 7.4 */ - if - ( - zif->rtadv.AdvHomeAgentFlag && - (zif->rtadv.HomeAgentPreference || zif->rtadv.HomeAgentLifetime != -1) - ) - { - struct nd_opt_homeagent_info *ndopt_hai = - (struct nd_opt_homeagent_info *)(buf + len); - ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION; - ndopt_hai->nd_opt_hai_len = 1; - ndopt_hai->nd_opt_hai_reserved = 0; - ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference); - /* 16-bit unsigned integer. The lifetime associated with the home - * agent in units of seconds. The default value is the same as the - * Router Lifetime, as specified in the main body of the Router - * Advertisement. The maximum value corresponds to 18.2 hours. A - * value of 0 MUST NOT be used. -- RFC6275, 7.5 */ - ndopt_hai->nd_opt_hai_lifetime = htons - ( - zif->rtadv.HomeAgentLifetime != -1 ? - zif->rtadv.HomeAgentLifetime : - MAX (1, pkt_RouterLifetime) /* 0 is OK for RL, but not for HAL*/ - ); - len += sizeof(struct nd_opt_homeagent_info); - } - - if (zif->rtadv.AdvIntervalOption) - { - struct nd_opt_adv_interval *ndopt_adv = - (struct nd_opt_adv_interval *)(buf + len); - ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL; - ndopt_adv->nd_opt_ai_len = 1; - ndopt_adv->nd_opt_ai_reserved = 0; - ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval); - len += sizeof(struct nd_opt_adv_interval); - } - - /* Fill in prefix. */ - for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix)) - { - struct nd_opt_prefix_info *pinfo; - - pinfo = (struct nd_opt_prefix_info *) (buf + len); - - pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; - pinfo->nd_opt_pi_len = 4; - pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen; - - pinfo->nd_opt_pi_flags_reserved = 0; - if (rprefix->AdvOnLinkFlag) - pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK; - if (rprefix->AdvAutonomousFlag) - pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO; - if (rprefix->AdvRouterAddressFlag) - pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR; - - pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime); - pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime); - pinfo->nd_opt_pi_reserved2 = 0; - - IPV6_ADDR_COPY (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.prefix); + addr.sin6_port = htons(IPPROTO_ICMPV6); + IPV6_ADDR_COPY(&addr.sin6_addr, all_nodes_addr); + + /* Fetch interface information. */ + zif = ifp->info; + + /* Make router advertisement message. */ + rtadv = (struct nd_router_advert *)buf; + + rtadv->nd_ra_type = ND_ROUTER_ADVERT; + rtadv->nd_ra_code = 0; + rtadv->nd_ra_cksum = 0; + + rtadv->nd_ra_curhoplimit = 64; + + /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */ + rtadv->nd_ra_flags_reserved = zif->rtadv.AdvDefaultLifetime == 0 + ? 0 + : zif->rtadv.DefaultPreference; + rtadv->nd_ra_flags_reserved <<= 3; + + if (zif->rtadv.AdvManagedFlag) + rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED; + if (zif->rtadv.AdvOtherConfigFlag) + rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER; + if (zif->rtadv.AdvHomeAgentFlag) + rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT; + /* Note that according to Neighbor Discovery (RFC 4861 [18]), + * AdvDefaultLifetime is by default based on the value of + * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime + * field of Router Advertisements. Given that this field is expressed + * in seconds, a small MaxRtrAdvInterval value can result in a zero + * value for this field. To prevent this, routers SHOULD keep + * AdvDefaultLifetime in at least one second, even if the use of + * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */ + pkt_RouterLifetime = + zif->rtadv.AdvDefaultLifetime != -1 + ? zif->rtadv.AdvDefaultLifetime + : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval); + rtadv->nd_ra_router_lifetime = htons(pkt_RouterLifetime); + rtadv->nd_ra_reachable = htonl(zif->rtadv.AdvReachableTime); + rtadv->nd_ra_retransmit = htonl(0); + + len = sizeof(struct nd_router_advert); + + /* If both the Home Agent Preference and Home Agent Lifetime are set to + * their default values specified above, this option SHOULD NOT be + * included in the Router Advertisement messages sent by this home + * agent. -- RFC6275, 7.4 */ + if (zif->rtadv.AdvHomeAgentFlag + && (zif->rtadv.HomeAgentPreference + || zif->rtadv.HomeAgentLifetime != -1)) { + struct nd_opt_homeagent_info *ndopt_hai = + (struct nd_opt_homeagent_info *)(buf + len); + ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION; + ndopt_hai->nd_opt_hai_len = 1; + ndopt_hai->nd_opt_hai_reserved = 0; + ndopt_hai->nd_opt_hai_preference = + htons(zif->rtadv.HomeAgentPreference); + /* 16-bit unsigned integer. The lifetime associated with the + * home + * agent in units of seconds. The default value is the same as + * the + * Router Lifetime, as specified in the main body of the Router + * Advertisement. The maximum value corresponds to 18.2 hours. + * A + * value of 0 MUST NOT be used. -- RFC6275, 7.5 */ + ndopt_hai->nd_opt_hai_lifetime = + htons(zif->rtadv.HomeAgentLifetime != -1 + ? zif->rtadv.HomeAgentLifetime + : MAX(1, pkt_RouterLifetime) /* 0 is OK + for RL, + but not + for HAL*/ + ); + len += sizeof(struct nd_opt_homeagent_info); + } -#ifdef DEBUG - { - u_char buf[INET6_ADDRSTRLEN]; + if (zif->rtadv.AdvIntervalOption) { + struct nd_opt_adv_interval *ndopt_adv = + (struct nd_opt_adv_interval *)(buf + len); + ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL; + ndopt_adv->nd_opt_ai_len = 1; + ndopt_adv->nd_opt_ai_reserved = 0; + ndopt_adv->nd_opt_ai_interval = + htonl(zif->rtadv.MaxRtrAdvInterval); + len += sizeof(struct nd_opt_adv_interval); + } + + /* Fill in prefix. */ + for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvPrefixList, node, rprefix)) { + struct nd_opt_prefix_info *pinfo; - zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix, - buf, INET6_ADDRSTRLEN)); + pinfo = (struct nd_opt_prefix_info *)(buf + len); - } + pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; + pinfo->nd_opt_pi_len = 4; + pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen; + + pinfo->nd_opt_pi_flags_reserved = 0; + if (rprefix->AdvOnLinkFlag) + pinfo->nd_opt_pi_flags_reserved |= + ND_OPT_PI_FLAG_ONLINK; + if (rprefix->AdvAutonomousFlag) + pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO; + if (rprefix->AdvRouterAddressFlag) + pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR; + + pinfo->nd_opt_pi_valid_time = htonl(rprefix->AdvValidLifetime); + pinfo->nd_opt_pi_preferred_time = + htonl(rprefix->AdvPreferredLifetime); + pinfo->nd_opt_pi_reserved2 = 0; + + IPV6_ADDR_COPY(&pinfo->nd_opt_pi_prefix, + &rprefix->prefix.prefix); + +#ifdef DEBUG + { + u_char buf[INET6_ADDRSTRLEN]; + + zlog_debug("DEBUG %s", + inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix, + buf, INET6_ADDRSTRLEN)); + } #endif /* DEBUG */ - len += sizeof (struct nd_opt_prefix_info); - } - - /* Hardware address. */ - if (ifp->hw_addr_len != 0) - { - buf[len++] = ND_OPT_SOURCE_LINKADDR; - - /* Option length should be rounded up to next octet if - the link address does not end on an octet boundary. */ - buf[len++] = (ifp->hw_addr_len + 9) >> 3; - - memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len); - len += ifp->hw_addr_len; - - /* Pad option to end on an octet boundary. */ - memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7); - len += -(ifp->hw_addr_len + 2) & 0x7; - } - - /* MTU */ - if (zif->rtadv.AdvLinkMTU) - { - struct nd_opt_mtu * opt = (struct nd_opt_mtu *) (buf + len); - opt->nd_opt_mtu_type = ND_OPT_MTU; - opt->nd_opt_mtu_len = 1; - opt->nd_opt_mtu_reserved = 0; - opt->nd_opt_mtu_mtu = htonl (zif->rtadv.AdvLinkMTU); - len += sizeof (struct nd_opt_mtu); - } - - msg.msg_name = (void *) &addr; - msg.msg_namelen = sizeof (struct sockaddr_in6); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = (void *) adata; - msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); - msg.msg_flags = 0; - iov.iov_base = buf; - iov.iov_len = len; - - cmsgptr = ZCMSG_FIRSTHDR(&msg); - cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); - cmsgptr->cmsg_level = IPPROTO_IPV6; - cmsgptr->cmsg_type = IPV6_PKTINFO; - - pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr); - memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr)); - pkt->ipi6_ifindex = ifp->ifindex; - - ret = sendmsg (sock, &msg, 0); - if (ret < 0) - { - zlog_err ("%s(%u): Tx RA failed, socket %u error %d (%s)", - ifp->name, ifp->ifindex, sock, errno, safe_strerror(errno)); - } - else - zif->ra_sent++; + len += sizeof(struct nd_opt_prefix_info); + } + + /* Hardware address. */ + if (ifp->hw_addr_len != 0) { + buf[len++] = ND_OPT_SOURCE_LINKADDR; + + /* Option length should be rounded up to next octet if + the link address does not end on an octet boundary. */ + buf[len++] = (ifp->hw_addr_len + 9) >> 3; + + memcpy(buf + len, ifp->hw_addr, ifp->hw_addr_len); + len += ifp->hw_addr_len; + + /* Pad option to end on an octet boundary. */ + memset(buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7); + len += -(ifp->hw_addr_len + 2) & 0x7; + } + + /* MTU */ + if (zif->rtadv.AdvLinkMTU) { + struct nd_opt_mtu *opt = (struct nd_opt_mtu *)(buf + len); + opt->nd_opt_mtu_type = ND_OPT_MTU; + opt->nd_opt_mtu_len = 1; + opt->nd_opt_mtu_reserved = 0; + opt->nd_opt_mtu_mtu = htonl(zif->rtadv.AdvLinkMTU); + len += sizeof(struct nd_opt_mtu); + } + + msg.msg_name = (void *)&addr; + msg.msg_namelen = sizeof(struct sockaddr_in6); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (void *)adata; + msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); + msg.msg_flags = 0; + iov.iov_base = buf; + iov.iov_len = len; + + cmsgptr = ZCMSG_FIRSTHDR(&msg); + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_PKTINFO; + + pkt = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr)); + pkt->ipi6_ifindex = ifp->ifindex; + + ret = sendmsg(sock, &msg, 0); + if (ret < 0) { + zlog_err("%s(%u): Tx RA failed, socket %u error %d (%s)", + ifp->name, ifp->ifindex, sock, errno, + safe_strerror(errno)); + } else + zif->ra_sent++; } -static int -rtadv_timer (struct thread *thread) +static int rtadv_timer(struct thread *thread) { - struct zebra_ns *zns = THREAD_ARG (thread); - struct vrf *vrf; - struct listnode *node, *nnode; - struct interface *ifp; - struct zebra_if *zif; - int period; - - zns->rtadv.ra_timer = NULL; - if (zns->rtadv.adv_msec_if_count == 0) - { - period = 1000; /* 1 s */ - rtadv_event (zns, RTADV_TIMER, 1 /* 1 s */); - } - else - { - period = 10; /* 10 ms */ - rtadv_event (zns, RTADV_TIMER_MSEC, 10 /* 10 ms */); - } - - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - for (ALL_LIST_ELEMENTS (vrf->iflist, node, nnode, ifp)) - { - if (if_is_loopback (ifp) || - CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK) || - ! if_is_operative (ifp)) - continue; - - zif = ifp->info; - - if (zif->rtadv.AdvSendAdvertisements) - { - if (zif->rtadv.inFastRexmit) - { - /* We assume we fast rexmit every sec so no additional vars */ - if (--zif->rtadv.NumFastReXmitsRemain <= 0) - zif->rtadv.inFastRexmit = 0; - - if (IS_ZEBRA_DEBUG_SEND) - zlog_debug("Fast RA Rexmit on interface %s", ifp->name); - - rtadv_send_packet (zns->rtadv.sock, ifp); - } - else - { - zif->rtadv.AdvIntervalTimer -= period; - if (zif->rtadv.AdvIntervalTimer <= 0) - { - /* FIXME: using MaxRtrAdvInterval each time isn't what section - 6.2.4 of RFC4861 tells to do. */ - zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval; - rtadv_send_packet (zns->rtadv.sock, ifp); - } - } - } - } - - return 0; + struct zebra_ns *zns = THREAD_ARG(thread); + struct vrf *vrf; + struct listnode *node, *nnode; + struct interface *ifp; + struct zebra_if *zif; + int period; + + zns->rtadv.ra_timer = NULL; + if (zns->rtadv.adv_msec_if_count == 0) { + period = 1000; /* 1 s */ + rtadv_event(zns, RTADV_TIMER, 1 /* 1 s */); + } else { + period = 10; /* 10 ms */ + rtadv_event(zns, RTADV_TIMER_MSEC, 10 /* 10 ms */); + } + + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + for (ALL_LIST_ELEMENTS(vrf->iflist, node, nnode, ifp)) { + if (if_is_loopback(ifp) + || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK) + || !if_is_operative(ifp)) + continue; + + zif = ifp->info; + + if (zif->rtadv.AdvSendAdvertisements) { + if (zif->rtadv.inFastRexmit) { + /* We assume we fast rexmit every sec so no + * additional vars */ + if (--zif->rtadv.NumFastReXmitsRemain <= 0) + zif->rtadv.inFastRexmit = 0; + + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug( + "Fast RA Rexmit on interface %s", + ifp->name); + + rtadv_send_packet(zns->rtadv.sock, ifp); + } else { + zif->rtadv.AdvIntervalTimer -= period; + if (zif->rtadv.AdvIntervalTimer <= 0) { + /* FIXME: using MaxRtrAdvInterval each + time isn't what section + 6.2.4 of RFC4861 tells to do. */ + zif->rtadv.AdvIntervalTimer = + zif->rtadv.MaxRtrAdvInterval; + rtadv_send_packet(zns->rtadv.sock, ifp); + } + } + } + } + + return 0; } -static void -rtadv_process_solicit (struct interface *ifp) +static void rtadv_process_solicit(struct interface *ifp) { - struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id); - struct zebra_ns *zns = zvrf->zns; + struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); + struct zebra_ns *zns = zvrf->zns; - assert (zns); - rtadv_send_packet (zns->rtadv.sock, ifp); + assert(zns); + rtadv_send_packet(zns->rtadv.sock, ifp); } -static void -rtadv_process_advert (u_char *msg, unsigned int len, struct interface *ifp, - struct sockaddr_in6 *addr) +static void rtadv_process_advert(u_char *msg, unsigned int len, + struct interface *ifp, + struct sockaddr_in6 *addr) { - struct nd_router_advert *radvert; - char addr_str[INET6_ADDRSTRLEN]; - struct zebra_if *zif; - struct prefix p; - - zif = ifp->info; - - inet_ntop (AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN); - - if (len < sizeof(struct nd_router_advert)) { - zlog_warn("%s(%u): Rx RA with invalid length %d from %s", - ifp->name, ifp->ifindex, len, addr_str); - return; - } - if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { - zlog_warn("%s(%u): Rx RA with non-linklocal source address from %s", - ifp->name, ifp->ifindex, addr_str); - return; - } - - radvert = (struct nd_router_advert *) msg; - - if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) && - (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit)) - { - zlog_warn("%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s", - ifp->name, ifp->ifindex, addr_str); - } - - if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) && - !zif->rtadv.AdvManagedFlag) - { - zlog_warn("%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s", - ifp->name, ifp->ifindex, addr_str); - } - - if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) && - !zif->rtadv.AdvOtherConfigFlag) - { - zlog_warn("%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s", - ifp->name, ifp->ifindex, addr_str); - } - - if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) && - (ntohl(radvert->nd_ra_reachable) != zif->rtadv.AdvReachableTime)) - { - zlog_warn("%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s", - ifp->name, ifp->ifindex, addr_str); - } - - if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer) && - (ntohl(radvert->nd_ra_retransmit) != (unsigned int)zif->rtadv.AdvRetransTimer)) - { - zlog_warn("%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s", - ifp->name, ifp->ifindex, addr_str); - } - - /* Create entry for neighbor if not known. */ - p.family = AF_INET6; - IPV6_ADDR_COPY (&p.u.prefix, &addr->sin6_addr); - p.prefixlen = IPV6_MAX_PREFIXLEN; - - if (!nbr_connected_check(ifp, &p)) - nbr_connected_add_ipv6 (ifp, &addr->sin6_addr); -} + struct nd_router_advert *radvert; + char addr_str[INET6_ADDRSTRLEN]; + struct zebra_if *zif; + struct prefix p; + zif = ifp->info; -static void -rtadv_process_packet (u_char *buf, unsigned int len, ifindex_t ifindex, int hoplimit, - struct sockaddr_in6 *from, struct zebra_ns *zns) -{ - struct icmp6_hdr *icmph; - struct interface *ifp; - struct zebra_if *zif; - char addr_str[INET6_ADDRSTRLEN]; - - inet_ntop (AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN); - - /* Interface search. */ - ifp = if_lookup_by_index_per_ns (zns, ifindex); - if (ifp == NULL) - { - zlog_warn ("RA/RS received on unknown IF %u from %s", - ifindex, addr_str); - return; - } - - if (IS_ZEBRA_DEBUG_PACKET) - zlog_debug ("%s(%u): Rx RA/RS len %d from %s", - ifp->name, ifp->ifindex, len, addr_str); - - if (if_is_loopback (ifp) || - CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) - return; - - /* Check interface configuration. */ - zif = ifp->info; - if (! zif->rtadv.AdvSendAdvertisements) - return; - - /* ICMP message length check. */ - if (len < sizeof (struct icmp6_hdr)) - { - zlog_warn ("%s(%u): Rx RA with Invalid ICMPV6 packet length %d", - ifp->name, ifp->ifindex, len); - return; - } - - icmph = (struct icmp6_hdr *) buf; - - /* ICMP message type check. */ - if (icmph->icmp6_type != ND_ROUTER_SOLICIT && - icmph->icmp6_type != ND_ROUTER_ADVERT) - { - zlog_warn ("%s(%u): Rx RA - Unwanted ICMPV6 message type %d", - ifp->name, ifp->ifindex, icmph->icmp6_type); - return; - } - - /* Hoplimit check. */ - if (hoplimit >= 0 && hoplimit != 255) - { - zlog_warn ("%s(%u): Rx RA - Invalid hoplimit %d", - ifp->name, ifp->ifindex, hoplimit); - return; - } - - /* Check ICMP message type. */ - if (icmph->icmp6_type == ND_ROUTER_SOLICIT) - rtadv_process_solicit (ifp); - else if (icmph->icmp6_type == ND_ROUTER_ADVERT) - rtadv_process_advert (buf, len, ifp, from); - - return; + inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN); + + if (len < sizeof(struct nd_router_advert)) { + zlog_warn("%s(%u): Rx RA with invalid length %d from %s", + ifp->name, ifp->ifindex, len, addr_str); + return; + } + if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { + zlog_warn( + "%s(%u): Rx RA with non-linklocal source address from %s", + ifp->name, ifp->ifindex, addr_str); + return; + } + + radvert = (struct nd_router_advert *)msg; + + if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) + && (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit)) { + zlog_warn( + "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s", + ifp->name, ifp->ifindex, addr_str); + } + + if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) + && !zif->rtadv.AdvManagedFlag) { + zlog_warn( + "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s", + ifp->name, ifp->ifindex, addr_str); + } + + if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) + && !zif->rtadv.AdvOtherConfigFlag) { + zlog_warn( + "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s", + ifp->name, ifp->ifindex, addr_str); + } + + if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) + && (ntohl(radvert->nd_ra_reachable) + != zif->rtadv.AdvReachableTime)) { + zlog_warn( + "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s", + ifp->name, ifp->ifindex, addr_str); + } + + if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer) + && (ntohl(radvert->nd_ra_retransmit) + != (unsigned int)zif->rtadv.AdvRetransTimer)) { + zlog_warn( + "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s", + ifp->name, ifp->ifindex, addr_str); + } + + /* Create entry for neighbor if not known. */ + p.family = AF_INET6; + IPV6_ADDR_COPY(&p.u.prefix, &addr->sin6_addr); + p.prefixlen = IPV6_MAX_PREFIXLEN; + + if (!nbr_connected_check(ifp, &p)) + nbr_connected_add_ipv6(ifp, &addr->sin6_addr); } -static int -rtadv_read (struct thread *thread) + +static void rtadv_process_packet(u_char *buf, unsigned int len, + ifindex_t ifindex, int hoplimit, + struct sockaddr_in6 *from, + struct zebra_ns *zns) { - int sock; - int len; - u_char buf[RTADV_MSG_SIZE]; - struct sockaddr_in6 from; - ifindex_t ifindex = 0; - int hoplimit = -1; - struct zebra_ns *zns = THREAD_ARG (thread); + struct icmp6_hdr *icmph; + struct interface *ifp; + struct zebra_if *zif; + char addr_str[INET6_ADDRSTRLEN]; + + inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN); + + /* Interface search. */ + ifp = if_lookup_by_index_per_ns(zns, ifindex); + if (ifp == NULL) { + zlog_warn("RA/RS received on unknown IF %u from %s", ifindex, + addr_str); + return; + } + + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp->name, + ifp->ifindex, len, addr_str); + + if (if_is_loopback(ifp) + || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) + return; - sock = THREAD_FD (thread); - zns->rtadv.ra_read = NULL; + /* Check interface configuration. */ + zif = ifp->info; + if (!zif->rtadv.AdvSendAdvertisements) + return; - /* Register myself. */ - rtadv_event (zns, RTADV_READ, sock); + /* ICMP message length check. */ + if (len < sizeof(struct icmp6_hdr)) { + zlog_warn("%s(%u): Rx RA with Invalid ICMPV6 packet length %d", + ifp->name, ifp->ifindex, len); + return; + } + + icmph = (struct icmp6_hdr *)buf; - len = rtadv_recv_packet (zns, sock, buf, sizeof (buf), &from, &ifindex, &hoplimit); + /* ICMP message type check. */ + if (icmph->icmp6_type != ND_ROUTER_SOLICIT + && icmph->icmp6_type != ND_ROUTER_ADVERT) { + zlog_warn("%s(%u): Rx RA - Unwanted ICMPV6 message type %d", + ifp->name, ifp->ifindex, icmph->icmp6_type); + return; + } - if (len < 0) - { - zlog_warn ("RA/RS recv failed, socket %u error %s", - sock, safe_strerror (errno)); - return len; - } + /* Hoplimit check. */ + if (hoplimit >= 0 && hoplimit != 255) { + zlog_warn("%s(%u): Rx RA - Invalid hoplimit %d", ifp->name, + ifp->ifindex, hoplimit); + return; + } - rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit, &from, zns); + /* Check ICMP message type. */ + if (icmph->icmp6_type == ND_ROUTER_SOLICIT) + rtadv_process_solicit(ifp); + else if (icmph->icmp6_type == ND_ROUTER_ADVERT) + rtadv_process_advert(buf, len, ifp, from); - return 0; + return; } -static int -rtadv_make_socket (void) +static int rtadv_read(struct thread *thread) { - int sock; - int ret = 0; - struct icmp6_filter filter; - - if ( zserv_privs.change (ZPRIVS_RAISE) ) - zlog_err ("rtadv_make_socket: could not raise privs, %s", - safe_strerror (errno) ); - - sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); - - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("rtadv_make_socket: could not lower privs, %s", - safe_strerror (errno) ); - - if (sock < 0) - { - close (sock); - return -1; - } - - ret = setsockopt_ipv6_pktinfo (sock, 1); - if (ret < 0) - { - close (sock); - return ret; - } - ret = setsockopt_ipv6_multicast_loop (sock, 0); - if (ret < 0) - { - close (sock); - return ret; - } - ret = setsockopt_ipv6_unicast_hops (sock, 255); - if (ret < 0) - { - close (sock); - return ret; - } - ret = setsockopt_ipv6_multicast_hops (sock, 255); - if (ret < 0) - { - close (sock); - return ret; - } - ret = setsockopt_ipv6_hoplimit (sock, 1); - if (ret < 0) - { - close (sock); - return ret; - } - - ICMP6_FILTER_SETBLOCKALL(&filter); - ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter); - ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter); - - ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, - sizeof (struct icmp6_filter)); - if (ret < 0) - { - zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno)); - return ret; - } - - return sock; + int sock; + int len; + u_char buf[RTADV_MSG_SIZE]; + struct sockaddr_in6 from; + ifindex_t ifindex = 0; + int hoplimit = -1; + struct zebra_ns *zns = THREAD_ARG(thread); + + sock = THREAD_FD(thread); + zns->rtadv.ra_read = NULL; + + /* Register myself. */ + rtadv_event(zns, RTADV_READ, sock); + + len = rtadv_recv_packet(zns, sock, buf, sizeof(buf), &from, &ifindex, + &hoplimit); + + if (len < 0) { + zlog_warn("RA/RS recv failed, socket %u error %s", sock, + safe_strerror(errno)); + return len; + } + + rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zns); + + return 0; } -static struct rtadv_prefix * -rtadv_prefix_new (void) +static int rtadv_make_socket(void) { - return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix)); + int sock; + int ret = 0; + struct icmp6_filter filter; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("rtadv_make_socket: could not raise privs, %s", + safe_strerror(errno)); + + sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("rtadv_make_socket: could not lower privs, %s", + safe_strerror(errno)); + + if (sock < 0) { + close(sock); + return -1; + } + + ret = setsockopt_ipv6_pktinfo(sock, 1); + if (ret < 0) { + close(sock); + return ret; + } + ret = setsockopt_ipv6_multicast_loop(sock, 0); + if (ret < 0) { + close(sock); + return ret; + } + ret = setsockopt_ipv6_unicast_hops(sock, 255); + if (ret < 0) { + close(sock); + return ret; + } + ret = setsockopt_ipv6_multicast_hops(sock, 255); + if (ret < 0) { + close(sock); + return ret; + } + ret = setsockopt_ipv6_hoplimit(sock, 1); + if (ret < 0) { + close(sock); + return ret; + } + + ICMP6_FILTER_SETBLOCKALL(&filter); + ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter); + ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter); + + ret = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, + sizeof(struct icmp6_filter)); + if (ret < 0) { + zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno)); + return ret; + } + + return sock; } -static void -rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix) +static struct rtadv_prefix *rtadv_prefix_new(void) { - XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix); + return XCALLOC(MTYPE_RTADV_PREFIX, sizeof(struct rtadv_prefix)); } -static struct rtadv_prefix * -rtadv_prefix_lookup (struct list *rplist, struct prefix_ipv6 *p) +static void rtadv_prefix_free(struct rtadv_prefix *rtadv_prefix) { - struct listnode *node; - struct rtadv_prefix *rprefix; + XFREE(MTYPE_RTADV_PREFIX, rtadv_prefix); +} - for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix)) - if (prefix_same ((struct prefix *) &rprefix->prefix, (struct prefix *) p)) - return rprefix; - return NULL; +static struct rtadv_prefix *rtadv_prefix_lookup(struct list *rplist, + struct prefix_ipv6 *p) +{ + struct listnode *node; + struct rtadv_prefix *rprefix; + + for (ALL_LIST_ELEMENTS_RO(rplist, node, rprefix)) + if (prefix_same((struct prefix *)&rprefix->prefix, + (struct prefix *)p)) + return rprefix; + return NULL; } -static struct rtadv_prefix * -rtadv_prefix_get (struct list *rplist, struct prefix_ipv6 *p) +static struct rtadv_prefix *rtadv_prefix_get(struct list *rplist, + struct prefix_ipv6 *p) { - struct rtadv_prefix *rprefix; - - rprefix = rtadv_prefix_lookup (rplist, p); - if (rprefix) - return rprefix; + struct rtadv_prefix *rprefix; + + rprefix = rtadv_prefix_lookup(rplist, p); + if (rprefix) + return rprefix; - rprefix = rtadv_prefix_new (); - memcpy (&rprefix->prefix, p, sizeof (struct prefix_ipv6)); - listnode_add (rplist, rprefix); + rprefix = rtadv_prefix_new(); + memcpy(&rprefix->prefix, p, sizeof(struct prefix_ipv6)); + listnode_add(rplist, rprefix); - return rprefix; + return rprefix; } -static void -rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp) +static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp) { - struct rtadv_prefix *rprefix; - - rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix); - - /* Set parameters. */ - rprefix->AdvValidLifetime = rp->AdvValidLifetime; - rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime; - rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag; - rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag; - rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag; + struct rtadv_prefix *rprefix; + + rprefix = rtadv_prefix_get(zif->rtadv.AdvPrefixList, &rp->prefix); + + /* Set parameters. */ + rprefix->AdvValidLifetime = rp->AdvValidLifetime; + rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime; + rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag; + rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag; + rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag; } -static int -rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp) +static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp) { - struct rtadv_prefix *rprefix; - - rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix); - if (rprefix != NULL) - { - listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix); - rtadv_prefix_free (rprefix); - return 1; - } - else - return 0; + struct rtadv_prefix *rprefix; + + rprefix = rtadv_prefix_lookup(zif->rtadv.AdvPrefixList, &rp->prefix); + if (rprefix != NULL) { + listnode_delete(zif->rtadv.AdvPrefixList, (void *)rprefix); + rtadv_prefix_free(rprefix); + return 1; + } else + return 0; } -static void -ipv6_nd_suppress_ra_set (struct interface *ifp, ipv6_nd_suppress_ra_status status) +static void ipv6_nd_suppress_ra_set(struct interface *ifp, + ipv6_nd_suppress_ra_status status) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - struct zebra_ns *zns; - - zif = ifp->info; - zvrf = vrf_info_lookup (ifp->vrf_id); - zns = zvrf->zns; - - if (status == RA_SUPPRESS) - { - /* RA is currently enabled */ - if (zif->rtadv.AdvSendAdvertisements) - { - zif->rtadv.AdvSendAdvertisements = 0; - zif->rtadv.AdvIntervalTimer = 0; - zns->rtadv.adv_if_count--; - - if_leave_all_router (zns->rtadv.sock, ifp); - - if (zns->rtadv.adv_if_count == 0) - rtadv_event (zns, RTADV_STOP, 0); - } - } - else - { - if (! zif->rtadv.AdvSendAdvertisements) - { - zif->rtadv.AdvSendAdvertisements = 1; - zif->rtadv.AdvIntervalTimer = 0; - zns->rtadv.adv_if_count++; - - if (zif->rtadv.MaxRtrAdvInterval >= 1000) - { - /* Enable Fast RA only when RA interval is in secs */ - zif->rtadv.inFastRexmit = 1; - zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS; - } - - if_join_all_router (zns->rtadv.sock, ifp); - - if (zns->rtadv.adv_if_count == 1) - rtadv_event (zns, RTADV_START, zns->rtadv.sock); - } - } + struct zebra_if *zif; + struct zebra_vrf *zvrf; + struct zebra_ns *zns; + + zif = ifp->info; + zvrf = vrf_info_lookup(ifp->vrf_id); + zns = zvrf->zns; + + if (status == RA_SUPPRESS) { + /* RA is currently enabled */ + if (zif->rtadv.AdvSendAdvertisements) { + zif->rtadv.AdvSendAdvertisements = 0; + zif->rtadv.AdvIntervalTimer = 0; + zns->rtadv.adv_if_count--; + + if_leave_all_router(zns->rtadv.sock, ifp); + + if (zns->rtadv.adv_if_count == 0) + rtadv_event(zns, RTADV_STOP, 0); + } + } else { + if (!zif->rtadv.AdvSendAdvertisements) { + zif->rtadv.AdvSendAdvertisements = 1; + zif->rtadv.AdvIntervalTimer = 0; + zns->rtadv.adv_if_count++; + + if (zif->rtadv.MaxRtrAdvInterval >= 1000) { + /* Enable Fast RA only when RA interval is in + * secs */ + zif->rtadv.inFastRexmit = 1; + zif->rtadv.NumFastReXmitsRemain = + RTADV_NUM_FAST_REXMITS; + } + + if_join_all_router(zns->rtadv.sock, ifp); + + if (zns->rtadv.adv_if_count == 1) + rtadv_event(zns, RTADV_START, zns->rtadv.sock); + } + } } /* @@ -808,60 +787,55 @@ ipv6_nd_suppress_ra_set (struct interface *ifp, ipv6_nd_suppress_ra_status statu * if the operator has explicitly enabled RA. The enable request can also * specify a RA interval (in seconds). */ -void -zebra_interface_radv_set (struct zserv *client, int sock, u_short length, - struct zebra_vrf *zvrf, int enable) +void zebra_interface_radv_set(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf, int enable) { - struct stream *s; - unsigned int ifindex; - struct interface *ifp; - struct zebra_if *zif; - int ra_interval; - - s = client->ibuf; - - /* Get interface index and RA interval. */ - ifindex = stream_getl (s); - ra_interval = stream_getl (s); - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%u: IF %u RA %s from client %s, interval %ds", - zvrf_id (zvrf), ifindex, enable ? "enable" : "disable", - zebra_route_string(client->proto), ra_interval); - - /* Locate interface and check VRF match. */ - ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ifindex); - if (!ifp) - { - zlog_warn("%u: IF %u RA %s client %s - interface unknown", - zvrf_id (zvrf), ifindex, enable ? "enable" : "disable", - zebra_route_string(client->proto)); - return; - } - if (ifp->vrf_id != zvrf_id (zvrf)) - { - zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u", - zvrf_id (zvrf), ifindex, enable ? "enable" : "disable", - zebra_route_string(client->proto), ifp->vrf_id); - return; - } - - zif = ifp->info; - if (enable) - { - ipv6_nd_suppress_ra_set (ifp, RA_ENABLE); - if (ra_interval && - (ra_interval * 1000) < zif->rtadv.MaxRtrAdvInterval) - zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000; - } - else - { - if (!zif->rtadv.configured) - { - zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL; - ipv6_nd_suppress_ra_set (ifp, RA_SUPPRESS); - } - } + struct stream *s; + unsigned int ifindex; + struct interface *ifp; + struct zebra_if *zif; + int ra_interval; + + s = client->ibuf; + + /* Get interface index and RA interval. */ + ifindex = stream_getl(s); + ra_interval = stream_getl(s); + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%u: IF %u RA %s from client %s, interval %ds", + zvrf_id(zvrf), ifindex, + enable ? "enable" : "disable", + zebra_route_string(client->proto), ra_interval); + + /* Locate interface and check VRF match. */ + ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex); + if (!ifp) { + zlog_warn("%u: IF %u RA %s client %s - interface unknown", + zvrf_id(zvrf), ifindex, enable ? "enable" : "disable", + zebra_route_string(client->proto)); + return; + } + if (ifp->vrf_id != zvrf_id(zvrf)) { + zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u", + zvrf_id(zvrf), ifindex, enable ? "enable" : "disable", + zebra_route_string(client->proto), ifp->vrf_id); + return; + } + + zif = ifp->info; + if (enable) { + ipv6_nd_suppress_ra_set(ifp, RA_ENABLE); + if (ra_interval + && (ra_interval * 1000) < zif->rtadv.MaxRtrAdvInterval) + zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000; + } else { + if (!zif->rtadv.configured) { + zif->rtadv.MaxRtrAdvInterval = + RTADV_MAX_RTR_ADV_INTERVAL; + ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS); + } + } } DEFUN (ipv6_nd_suppress_ra, @@ -871,20 +845,19 @@ DEFUN (ipv6_nd_suppress_ra, "Neighbor discovery\n" "Suppress Router Advertisement\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - - if (if_is_loopback (ifp) || - CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) - { - vty_out (vty, - "Cannot configure IPv6 Router Advertisements on this interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ipv6_nd_suppress_ra_set (ifp, RA_SUPPRESS); - zif->rtadv.configured = 0; - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + + if (if_is_loopback(ifp) + || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + vty_out(vty, + "Cannot configure IPv6 Router Advertisements on this interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS); + zif->rtadv.configured = 0; + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_suppress_ra, @@ -895,20 +868,19 @@ DEFUN (no_ipv6_nd_suppress_ra, "Neighbor discovery\n" "Suppress Router Advertisement\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - - if (if_is_loopback (ifp) || - CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) - { - vty_out (vty, - "Cannot configure IPv6 Router Advertisements on this interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ipv6_nd_suppress_ra_set (ifp, RA_ENABLE); - zif->rtadv.configured = 1; - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + + if (if_is_loopback(ifp) + || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + vty_out(vty, + "Cannot configure IPv6 Router Advertisements on this interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ipv6_nd_suppress_ra_set(ifp, RA_ENABLE); + zif->rtadv.configured = 1; + return CMD_SUCCESS; } DEFUN (ipv6_nd_ra_interval_msec, @@ -920,33 +892,33 @@ DEFUN (ipv6_nd_ra_interval_msec, "Router Advertisement interval in milliseconds\n" "Router Advertisement interval in milliseconds\n") { - int idx_number = 4; - VTY_DECLVAR_CONTEXT (interface, ifp); - unsigned interval; - struct zebra_if *zif = ifp->info; - struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id); - struct zebra_ns *zns; - - zns = zvrf->zns; - interval = strtoul(argv[idx_number]->arg, NULL, 10); - if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) - { - vty_out (vty, - "This ra-interval would conflict with configured ra-lifetime!\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (zif->rtadv.MaxRtrAdvInterval % 1000) - zns->rtadv.adv_msec_if_count--; - - if (interval % 1000) - zns->rtadv.adv_msec_if_count++; - - zif->rtadv.MaxRtrAdvInterval = interval; - zif->rtadv.MinRtrAdvInterval = 0.33 * interval; - zif->rtadv.AdvIntervalTimer = 0; - - return CMD_SUCCESS; + int idx_number = 4; + VTY_DECLVAR_CONTEXT(interface, ifp); + unsigned interval; + struct zebra_if *zif = ifp->info; + struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); + struct zebra_ns *zns; + + zns = zvrf->zns; + interval = strtoul(argv[idx_number]->arg, NULL, 10); + if ((zif->rtadv.AdvDefaultLifetime != -1 + && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) { + vty_out(vty, + "This ra-interval would conflict with configured ra-lifetime!\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (zif->rtadv.MaxRtrAdvInterval % 1000) + zns->rtadv.adv_msec_if_count--; + + if (interval % 1000) + zns->rtadv.adv_msec_if_count++; + + zif->rtadv.MaxRtrAdvInterval = interval; + zif->rtadv.MinRtrAdvInterval = 0.33 * interval; + zif->rtadv.AdvIntervalTimer = 0; + + return CMD_SUCCESS; } DEFUN (ipv6_nd_ra_interval, @@ -957,33 +929,33 @@ DEFUN (ipv6_nd_ra_interval, "Router Advertisement interval\n" "Router Advertisement interval in seconds\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - unsigned interval; - struct zebra_if *zif = ifp->info; - struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id); - struct zebra_ns *zns; - - zns = zvrf->zns; - interval = strtoul(argv[idx_number]->arg, NULL, 10); - if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) - { - vty_out (vty, - "This ra-interval would conflict with configured ra-lifetime!\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (zif->rtadv.MaxRtrAdvInterval % 1000) - zns->rtadv.adv_msec_if_count--; - - /* convert to milliseconds */ - interval = interval * 1000; - - zif->rtadv.MaxRtrAdvInterval = interval; - zif->rtadv.MinRtrAdvInterval = 0.33 * interval; - zif->rtadv.AdvIntervalTimer = 0; - - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + unsigned interval; + struct zebra_if *zif = ifp->info; + struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); + struct zebra_ns *zns; + + zns = zvrf->zns; + interval = strtoul(argv[idx_number]->arg, NULL, 10); + if ((zif->rtadv.AdvDefaultLifetime != -1 + && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) { + vty_out(vty, + "This ra-interval would conflict with configured ra-lifetime!\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (zif->rtadv.MaxRtrAdvInterval % 1000) + zns->rtadv.adv_msec_if_count--; + + /* convert to milliseconds */ + interval = interval * 1000; + + zif->rtadv.MaxRtrAdvInterval = interval; + zif->rtadv.MinRtrAdvInterval = 0.33 * interval; + zif->rtadv.AdvIntervalTimer = 0; + + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_ra_interval, @@ -997,22 +969,22 @@ DEFUN (no_ipv6_nd_ra_interval, "Specify millisecond router advertisement interval\n" "Router Advertisement interval in milliseconds\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - struct zebra_vrf *zvrf; - struct zebra_ns *zns; - - zvrf = vrf_info_lookup (ifp->vrf_id); - zns = zvrf->zns; - - if (zif->rtadv.MaxRtrAdvInterval % 1000) - zns->rtadv.adv_msec_if_count--; - - zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL; - zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL; - zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval; - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + struct zebra_vrf *zvrf; + struct zebra_ns *zns; + + zvrf = vrf_info_lookup(ifp->vrf_id); + zns = zvrf->zns; + + if (zif->rtadv.MaxRtrAdvInterval % 1000) + zns->rtadv.adv_msec_if_count--; + + zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL; + zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL; + zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval; + + return CMD_SUCCESS; } DEFUN (ipv6_nd_ra_lifetime, @@ -1023,27 +995,26 @@ DEFUN (ipv6_nd_ra_lifetime, "Router lifetime\n" "Router lifetime in seconds (0 stands for a non-default gw)\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - int lifetime; - - lifetime = strtoul(argv[idx_number]->arg, NULL, 10); - - /* The value to be placed in the Router Lifetime field - * of Router Advertisements sent from the interface, - * in seconds. MUST be either zero or between - * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */ - if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)) - { - vty_out (vty, - "This ra-lifetime would conflict with configured ra-interval\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - zif->rtadv.AdvDefaultLifetime = lifetime; - - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + int lifetime; + + lifetime = strtoul(argv[idx_number]->arg, NULL, 10); + + /* The value to be placed in the Router Lifetime field + * of Router Advertisements sent from the interface, + * in seconds. MUST be either zero or between + * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */ + if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)) { + vty_out(vty, + "This ra-lifetime would conflict with configured ra-interval\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + zif->rtadv.AdvDefaultLifetime = lifetime; + + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_ra_lifetime, @@ -1055,12 +1026,12 @@ DEFUN (no_ipv6_nd_ra_lifetime, "Router lifetime\n" "Router lifetime in seconds (0 stands for a non-default gw)\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvDefaultLifetime = -1; + zif->rtadv.AdvDefaultLifetime = -1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_reachable_time, @@ -1071,11 +1042,11 @@ DEFUN (ipv6_nd_reachable_time, "Reachable time\n" "Reachable time in milliseconds\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - zif->rtadv.AdvReachableTime = strtoul(argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + zif->rtadv.AdvReachableTime = strtoul(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_reachable_time, @@ -1087,12 +1058,12 @@ DEFUN (no_ipv6_nd_reachable_time, "Reachable time\n" "Reachable time in milliseconds\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvReachableTime = 0; + zif->rtadv.AdvReachableTime = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_homeagent_preference, @@ -1103,11 +1074,12 @@ DEFUN (ipv6_nd_homeagent_preference, "Home Agent preference\n" "preference value (default is 0, least preferred)\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - zif->rtadv.HomeAgentPreference = strtoul(argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + zif->rtadv.HomeAgentPreference = + strtoul(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_homeagent_preference, @@ -1119,12 +1091,12 @@ DEFUN (no_ipv6_nd_homeagent_preference, "Home Agent preference\n" "preference value (default is 0, least preferred)\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.HomeAgentPreference = 0; + zif->rtadv.HomeAgentPreference = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_homeagent_lifetime, @@ -1135,11 +1107,11 @@ DEFUN (ipv6_nd_homeagent_lifetime, "Home Agent lifetime\n" "Home Agent lifetime in seconds (0 to track ra-lifetime)\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - zif->rtadv.HomeAgentLifetime = strtoul(argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + zif->rtadv.HomeAgentLifetime = strtoul(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_homeagent_lifetime, @@ -1151,12 +1123,12 @@ DEFUN (no_ipv6_nd_homeagent_lifetime, "Home Agent lifetime\n" "Home Agent lifetime in seconds (0 to track ra-lifetime)\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.HomeAgentLifetime = -1; + zif->rtadv.HomeAgentLifetime = -1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_managed_config_flag, @@ -1166,12 +1138,12 @@ DEFUN (ipv6_nd_managed_config_flag, "Neighbor discovery\n" "Managed address configuration flag\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvManagedFlag = 1; + zif->rtadv.AdvManagedFlag = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_managed_config_flag, @@ -1182,12 +1154,12 @@ DEFUN (no_ipv6_nd_managed_config_flag, "Neighbor discovery\n" "Managed address configuration flag\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvManagedFlag = 0; + zif->rtadv.AdvManagedFlag = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_homeagent_config_flag, @@ -1197,12 +1169,12 @@ DEFUN (ipv6_nd_homeagent_config_flag, "Neighbor discovery\n" "Home Agent configuration flag\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvHomeAgentFlag = 1; + zif->rtadv.AdvHomeAgentFlag = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_homeagent_config_flag, @@ -1213,12 +1185,12 @@ DEFUN (no_ipv6_nd_homeagent_config_flag, "Neighbor discovery\n" "Home Agent configuration flag\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvHomeAgentFlag = 0; + zif->rtadv.AdvHomeAgentFlag = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_adv_interval_config_option, @@ -1228,12 +1200,12 @@ DEFUN (ipv6_nd_adv_interval_config_option, "Neighbor discovery\n" "Advertisement Interval Option\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvIntervalOption = 1; + zif->rtadv.AdvIntervalOption = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_adv_interval_config_option, @@ -1244,12 +1216,12 @@ DEFUN (no_ipv6_nd_adv_interval_config_option, "Neighbor discovery\n" "Advertisement Interval Option\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvIntervalOption = 0; + zif->rtadv.AdvIntervalOption = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_other_config_flag, @@ -1259,12 +1231,12 @@ DEFUN (ipv6_nd_other_config_flag, "Neighbor discovery\n" "Other statefull configuration flag\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvOtherConfigFlag = 1; + zif->rtadv.AdvOtherConfigFlag = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_other_config_flag, @@ -1275,12 +1247,12 @@ DEFUN (no_ipv6_nd_other_config_flag, "Neighbor discovery\n" "Other statefull configuration flag\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvOtherConfigFlag = 0; + zif->rtadv.AdvOtherConfigFlag = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_prefix, @@ -1300,63 +1272,70 @@ DEFUN (ipv6_nd_prefix, "Do not use prefix for autoconfiguration\n" "Do not use prefix for onlink determination\n") { - /* prelude */ - char *prefix = argv[3]->arg; - int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN || strmatch (argv[4]->text, "infinite")); - int routeropts = lifetimes ? argc > 6 : argc > 4; - - int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0; - - char *lifetime = NULL, *preflifetime = NULL; - int routeraddr = 0, offlink = 0, noautoconf = 0; - if (lifetimes) - { - lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg : argv[4]->text; - preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg : argv[5]->text; - } - if (routeropts) - { - routeraddr = strmatch (argv[idx_routeropts]->text, "router-address"); - if (!routeraddr) - { - offlink = (argc > idx_routeropts + 1 || strmatch (argv[idx_routeropts]->text, "off-link")); - noautoconf = (argc > idx_routeropts + 1 || strmatch (argv[idx_routeropts]->text, "no-autoconfig")); - } - } - - /* business */ - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zebra_if = ifp->info; - int ret; - struct rtadv_prefix rp; - - ret = str2prefix_ipv6 (prefix, &rp.prefix); - if (!ret) - { - vty_out (vty, "Malformed IPv6 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */ - rp.AdvOnLinkFlag = !offlink; - rp.AdvAutonomousFlag = !noautoconf; - rp.AdvRouterAddressFlag = routeraddr; - rp.AdvValidLifetime = RTADV_VALID_LIFETIME; - rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME; - - if (lifetimes) - { - rp.AdvValidLifetime = strmatch (lifetime, "infinite") ? UINT32_MAX : strtoll (lifetime, NULL, 10); - rp.AdvPreferredLifetime = strmatch (preflifetime, "infinite") ? UINT32_MAX : strtoll (preflifetime, NULL, 10); - if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) - { - vty_out (vty, "Invalid preferred lifetime\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - rtadv_prefix_set (zebra_if, &rp); - - return CMD_SUCCESS; + /* prelude */ + char *prefix = argv[3]->arg; + int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN + || strmatch(argv[4]->text, "infinite")); + int routeropts = lifetimes ? argc > 6 : argc > 4; + + int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0; + + char *lifetime = NULL, *preflifetime = NULL; + int routeraddr = 0, offlink = 0, noautoconf = 0; + if (lifetimes) { + lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg + : argv[4]->text; + preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg + : argv[5]->text; + } + if (routeropts) { + routeraddr = + strmatch(argv[idx_routeropts]->text, "router-address"); + if (!routeraddr) { + offlink = (argc > idx_routeropts + 1 + || strmatch(argv[idx_routeropts]->text, + "off-link")); + noautoconf = (argc > idx_routeropts + 1 + || strmatch(argv[idx_routeropts]->text, + "no-autoconfig")); + } + } + + /* business */ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zebra_if = ifp->info; + int ret; + struct rtadv_prefix rp; + + ret = str2prefix_ipv6(prefix, &rp.prefix); + if (!ret) { + vty_out(vty, "Malformed IPv6 prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */ + rp.AdvOnLinkFlag = !offlink; + rp.AdvAutonomousFlag = !noautoconf; + rp.AdvRouterAddressFlag = routeraddr; + rp.AdvValidLifetime = RTADV_VALID_LIFETIME; + rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME; + + if (lifetimes) { + rp.AdvValidLifetime = strmatch(lifetime, "infinite") + ? UINT32_MAX + : strtoll(lifetime, NULL, 10); + rp.AdvPreferredLifetime = + strmatch(preflifetime, "infinite") + ? UINT32_MAX + : strtoll(preflifetime, NULL, 10); + if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) { + vty_out(vty, "Invalid preferred lifetime\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + rtadv_prefix_set(zebra_if, &rp); + + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_prefix, @@ -1377,28 +1356,26 @@ DEFUN (no_ipv6_nd_prefix, "Do not use prefix for autoconfiguration\n" "Do not use prefix for onlink determination\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zebra_if = ifp->info; - int ret; - struct rtadv_prefix rp; - char *prefix = argv[4]->arg; - - ret = str2prefix_ipv6 (prefix, &rp.prefix); - if (!ret) - { - vty_out (vty, "Malformed IPv6 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */ - - ret = rtadv_prefix_reset (zebra_if, &rp); - if (!ret) - { - vty_out (vty, "Non-existant IPv6 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zebra_if = ifp->info; + int ret; + struct rtadv_prefix rp; + char *prefix = argv[4]->arg; + + ret = str2prefix_ipv6(prefix, &rp.prefix); + if (!ret) { + vty_out(vty, "Malformed IPv6 prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */ + + ret = rtadv_prefix_reset(zebra_if, &rp); + if (!ret) { + vty_out(vty, "Non-existant IPv6 prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (ipv6_nd_router_preference, @@ -1411,22 +1388,22 @@ DEFUN (ipv6_nd_router_preference, "Medium default router preference (default)\n" "Low default router preference\n") { - int idx_high_medium_low = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - int i = 0; - - while (0 != rtadv_pref_strs[i]) - { - if (strncmp (argv[idx_high_medium_low]->arg, rtadv_pref_strs[i], 1) == 0) - { - zif->rtadv.DefaultPreference = i; - return CMD_SUCCESS; + int idx_high_medium_low = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + int i = 0; + + while (0 != rtadv_pref_strs[i]) { + if (strncmp(argv[idx_high_medium_low]->arg, rtadv_pref_strs[i], + 1) + == 0) { + zif->rtadv.DefaultPreference = i; + return CMD_SUCCESS; + } + i++; } - i++; - } - return CMD_ERR_NO_MATCH; + return CMD_ERR_NO_MATCH; } DEFUN (no_ipv6_nd_router_preference, @@ -1440,12 +1417,13 @@ DEFUN (no_ipv6_nd_router_preference, "Medium default router preference (default)\n" "Low default router preference\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */ + zif->rtadv.DefaultPreference = + RTADV_PREF_MEDIUM; /* Default per RFC4191. */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_mtu, @@ -1456,11 +1434,11 @@ DEFUN (ipv6_nd_mtu, "Advertised MTU\n" "MTU in bytes\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - zif->rtadv.AdvLinkMTU = strtoul(argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + zif->rtadv.AdvLinkMTU = strtoul(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_mtu, @@ -1472,253 +1450,246 @@ DEFUN (no_ipv6_nd_mtu, "Advertised MTU\n" "MTU in bytes\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - zif->rtadv.AdvLinkMTU = 0; - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + zif->rtadv.AdvLinkMTU = 0; + return CMD_SUCCESS; } /* Write configuration about router advertisement. */ -void -rtadv_config_write (struct vty *vty, struct interface *ifp) +void rtadv_config_write(struct vty *vty, struct interface *ifp) { - struct zebra_if *zif; - struct listnode *node; - struct rtadv_prefix *rprefix; - char buf[PREFIX_STRLEN]; - int interval; - - zif = ifp->info; - - if (!(if_is_loopback (ifp) || - CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))) - { - if (zif->rtadv.AdvSendAdvertisements) - vty_out (vty, " no ipv6 nd suppress-ra\n"); - } - - interval = zif->rtadv.MaxRtrAdvInterval; - if (interval % 1000) - vty_out (vty, " ipv6 nd ra-interval msec %d\n",interval); - else - if (interval != RTADV_MAX_RTR_ADV_INTERVAL) - vty_out (vty, " ipv6 nd ra-interval %d\n",interval / 1000); - - if (zif->rtadv.AdvIntervalOption) - vty_out (vty, " ipv6 nd adv-interval-option\n"); - - if (zif->rtadv.AdvDefaultLifetime != -1) - vty_out (vty, " ipv6 nd ra-lifetime %d\n",zif->rtadv.AdvDefaultLifetime); - - if (zif->rtadv.HomeAgentPreference) - vty_out (vty, " ipv6 nd home-agent-preference %u\n", - zif->rtadv.HomeAgentPreference); - - if (zif->rtadv.HomeAgentLifetime != -1) - vty_out (vty, " ipv6 nd home-agent-lifetime %u\n", - zif->rtadv.HomeAgentLifetime); - - if (zif->rtadv.AdvHomeAgentFlag) - vty_out (vty, " ipv6 nd home-agent-config-flag\n"); - - if (zif->rtadv.AdvReachableTime) - vty_out (vty, " ipv6 nd reachable-time %d\n", - zif->rtadv.AdvReachableTime); - - if (zif->rtadv.AdvManagedFlag) - vty_out (vty, " ipv6 nd managed-config-flag\n"); - - if (zif->rtadv.AdvOtherConfigFlag) - vty_out (vty, " ipv6 nd other-config-flag\n"); - - if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM) - vty_out (vty, " ipv6 nd router-preference %s\n", - rtadv_pref_strs[zif->rtadv.DefaultPreference]); - - if (zif->rtadv.AdvLinkMTU) - vty_out (vty, " ipv6 nd mtu %d\n", zif->rtadv.AdvLinkMTU); - - for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix)) - { - vty_out (vty, " ipv6 nd prefix %s", - prefix2str (&rprefix->prefix, buf, sizeof(buf))); - if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) || - (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME)) - { - if (rprefix->AdvValidLifetime == UINT32_MAX) - vty_out (vty, " infinite"); - else - vty_out (vty, " %u", rprefix->AdvValidLifetime); - if (rprefix->AdvPreferredLifetime == UINT32_MAX) - vty_out (vty, " infinite"); - else - vty_out (vty, " %u", rprefix->AdvPreferredLifetime); + struct zebra_if *zif; + struct listnode *node; + struct rtadv_prefix *rprefix; + char buf[PREFIX_STRLEN]; + int interval; + + zif = ifp->info; + + if (!(if_is_loopback(ifp) + || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))) { + if (zif->rtadv.AdvSendAdvertisements) + vty_out(vty, " no ipv6 nd suppress-ra\n"); + } + + interval = zif->rtadv.MaxRtrAdvInterval; + if (interval % 1000) + vty_out(vty, " ipv6 nd ra-interval msec %d\n", interval); + else if (interval != RTADV_MAX_RTR_ADV_INTERVAL) + vty_out(vty, " ipv6 nd ra-interval %d\n", interval / 1000); + + if (zif->rtadv.AdvIntervalOption) + vty_out(vty, " ipv6 nd adv-interval-option\n"); + + if (zif->rtadv.AdvDefaultLifetime != -1) + vty_out(vty, " ipv6 nd ra-lifetime %d\n", + zif->rtadv.AdvDefaultLifetime); + + if (zif->rtadv.HomeAgentPreference) + vty_out(vty, " ipv6 nd home-agent-preference %u\n", + zif->rtadv.HomeAgentPreference); + + if (zif->rtadv.HomeAgentLifetime != -1) + vty_out(vty, " ipv6 nd home-agent-lifetime %u\n", + zif->rtadv.HomeAgentLifetime); + + if (zif->rtadv.AdvHomeAgentFlag) + vty_out(vty, " ipv6 nd home-agent-config-flag\n"); + + if (zif->rtadv.AdvReachableTime) + vty_out(vty, " ipv6 nd reachable-time %d\n", + zif->rtadv.AdvReachableTime); + + if (zif->rtadv.AdvManagedFlag) + vty_out(vty, " ipv6 nd managed-config-flag\n"); + + if (zif->rtadv.AdvOtherConfigFlag) + vty_out(vty, " ipv6 nd other-config-flag\n"); + + if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM) + vty_out(vty, " ipv6 nd router-preference %s\n", + rtadv_pref_strs[zif->rtadv.DefaultPreference]); + + if (zif->rtadv.AdvLinkMTU) + vty_out(vty, " ipv6 nd mtu %d\n", zif->rtadv.AdvLinkMTU); + + for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvPrefixList, node, rprefix)) { + vty_out(vty, " ipv6 nd prefix %s", + prefix2str(&rprefix->prefix, buf, sizeof(buf))); + if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) + || (rprefix->AdvPreferredLifetime + != RTADV_PREFERRED_LIFETIME)) { + if (rprefix->AdvValidLifetime == UINT32_MAX) + vty_out(vty, " infinite"); + else + vty_out(vty, " %u", rprefix->AdvValidLifetime); + if (rprefix->AdvPreferredLifetime == UINT32_MAX) + vty_out(vty, " infinite"); + else + vty_out(vty, " %u", + rprefix->AdvPreferredLifetime); + } + if (!rprefix->AdvOnLinkFlag) + vty_out(vty, " off-link"); + if (!rprefix->AdvAutonomousFlag) + vty_out(vty, " no-autoconfig"); + if (rprefix->AdvRouterAddressFlag) + vty_out(vty, " router-address"); + vty_out(vty, "\n"); } - if (!rprefix->AdvOnLinkFlag) - vty_out (vty, " off-link"); - if (!rprefix->AdvAutonomousFlag) - vty_out (vty, " no-autoconfig"); - if (rprefix->AdvRouterAddressFlag) - vty_out (vty, " router-address"); - vty_out (vty, "\n"); - } } -static void -rtadv_event (struct zebra_ns *zns, enum rtadv_event event, int val) +static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val) { - struct rtadv *rtadv = &zns->rtadv; - - switch (event) - { - case RTADV_START: - thread_add_read(zebrad.master, rtadv_read, zns, val, &rtadv->ra_read); - thread_add_event(zebrad.master, rtadv_timer, zns, 0, &rtadv->ra_timer); - break; - case RTADV_STOP: - if (rtadv->ra_timer) - { - thread_cancel (rtadv->ra_timer); - rtadv->ra_timer = NULL; + struct rtadv *rtadv = &zns->rtadv; + + switch (event) { + case RTADV_START: + thread_add_read(zebrad.master, rtadv_read, zns, val, + &rtadv->ra_read); + thread_add_event(zebrad.master, rtadv_timer, zns, 0, + &rtadv->ra_timer); + break; + case RTADV_STOP: + if (rtadv->ra_timer) { + thread_cancel(rtadv->ra_timer); + rtadv->ra_timer = NULL; + } + if (rtadv->ra_read) { + thread_cancel(rtadv->ra_read); + rtadv->ra_read = NULL; + } + break; + case RTADV_TIMER: + thread_add_timer(zebrad.master, rtadv_timer, zns, val, + &rtadv->ra_timer); + break; + case RTADV_TIMER_MSEC: + thread_add_timer_msec(zebrad.master, rtadv_timer, zns, val, + &rtadv->ra_timer); + break; + case RTADV_READ: + thread_add_read(zebrad.master, rtadv_read, zns, val, + &rtadv->ra_read); + break; + default: + break; } - if (rtadv->ra_read) - { - thread_cancel (rtadv->ra_read); - rtadv->ra_read = NULL; - } - break; - case RTADV_TIMER: - thread_add_timer(zebrad.master, rtadv_timer, zns, val, &rtadv->ra_timer); - break; - case RTADV_TIMER_MSEC: - thread_add_timer_msec(zebrad.master, rtadv_timer, zns, val, - &rtadv->ra_timer); - break; - case RTADV_READ: - thread_add_read(zebrad.master, rtadv_read, zns, val, &rtadv->ra_read); - break; - default: - break; - } - return; + return; } -void -rtadv_init (struct zebra_ns *zns) +void rtadv_init(struct zebra_ns *zns) { - zns->rtadv.sock = rtadv_make_socket (); + zns->rtadv.sock = rtadv_make_socket(); } -void -rtadv_terminate (struct zebra_ns *zns) +void rtadv_terminate(struct zebra_ns *zns) { - rtadv_event (zns, RTADV_STOP, 0); - if (zns->rtadv.sock >= 0) - { - close (zns->rtadv.sock); - zns->rtadv.sock = -1; - } - - zns->rtadv.adv_if_count = 0; - zns->rtadv.adv_msec_if_count = 0; + rtadv_event(zns, RTADV_STOP, 0); + if (zns->rtadv.sock >= 0) { + close(zns->rtadv.sock); + zns->rtadv.sock = -1; + } + + zns->rtadv.adv_if_count = 0; + zns->rtadv.adv_msec_if_count = 0; } -void -rtadv_cmd_init (void) +void rtadv_cmd_init(void) { - install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_mtu_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_reachable_time_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd); + install_element(INTERFACE_NODE, + &ipv6_nd_adv_interval_config_option_cmd); + install_element(INTERFACE_NODE, + &no_ipv6_nd_adv_interval_config_option_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_prefix_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_prefix_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_router_preference_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_mtu_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_mtu_cmd); } -static int -if_join_all_router (int sock, struct interface *ifp) +static int if_join_all_router(int sock, struct interface *ifp) { - int ret; + int ret; - struct ipv6_mreq mreq; + struct ipv6_mreq mreq; - memset (&mreq, 0, sizeof (struct ipv6_mreq)); - inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr); - mreq.ipv6mr_interface = ifp->ifindex; + memset(&mreq, 0, sizeof(struct ipv6_mreq)); + inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr); + mreq.ipv6mr_interface = ifp->ifindex; - ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, - (char *) &mreq, sizeof mreq); - if (ret < 0) - zlog_warn ("%s(%u): Failed to join group, socket %u error %s", - ifp->name, ifp->ifindex, sock, safe_strerror (errno)); + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq, + sizeof mreq); + if (ret < 0) + zlog_warn("%s(%u): Failed to join group, socket %u error %s", + ifp->name, ifp->ifindex, sock, safe_strerror(errno)); - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("%s(%u): Join All-Routers multicast group, socket %u", - ifp->name, ifp->ifindex, sock); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s(%u): Join All-Routers multicast group, socket %u", + ifp->name, ifp->ifindex, sock); - return 0; + return 0; } -static int -if_leave_all_router (int sock, struct interface *ifp) +static int if_leave_all_router(int sock, struct interface *ifp) { - int ret; + int ret; - struct ipv6_mreq mreq; + struct ipv6_mreq mreq; - memset (&mreq, 0, sizeof (struct ipv6_mreq)); - inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr); - mreq.ipv6mr_interface = ifp->ifindex; + memset(&mreq, 0, sizeof(struct ipv6_mreq)); + inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr); + mreq.ipv6mr_interface = ifp->ifindex; - ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, - (char *) &mreq, sizeof mreq); - if (ret < 0) - zlog_warn ("%s(%u): Failed to leave group, socket %u error %s", - ifp->name, ifp->ifindex, sock,safe_strerror (errno)); + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq, + sizeof mreq); + if (ret < 0) + zlog_warn("%s(%u): Failed to leave group, socket %u error %s", + ifp->name, ifp->ifindex, sock, safe_strerror(errno)); - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("%s(%u): Leave All-Routers multicast group, socket %u", - ifp->name, ifp->ifindex, sock); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s(%u): Leave All-Routers multicast group, socket %u", + ifp->name, ifp->ifindex, sock); - return 0; + return 0; } #else -void -rtadv_init (struct zebra_ns *zns) +void rtadv_init(struct zebra_ns *zns) { - /* Empty.*/; + /* Empty.*/; } -void -rtadv_terminate (struct zebra_ns *zns) +void rtadv_terminate(struct zebra_ns *zns) { - /* Empty.*/; + /* Empty.*/; } -void -rtadv_cmd_init (void) +void rtadv_cmd_init(void) { - /* Empty.*/; + /* Empty.*/; } #endif /* HAVE_RTADV */ diff --git a/zebra/rtadv.h b/zebra/rtadv.h index 5f389b30a..029c97cdd 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -26,38 +26,36 @@ #include "zebra/interface.h" /* NB: RTADV is defined in zebra/interface.h above */ -#if defined (HAVE_RTADV) +#if defined(HAVE_RTADV) /* Router advertisement prefix. */ -struct rtadv_prefix -{ - /* Prefix to be advertised. */ - struct prefix_ipv6 prefix; - - /* The value to be placed in the Valid Lifetime in the Prefix */ - u_int32_t AdvValidLifetime; +struct rtadv_prefix { + /* Prefix to be advertised. */ + struct prefix_ipv6 prefix; + + /* The value to be placed in the Valid Lifetime in the Prefix */ + u_int32_t AdvValidLifetime; #define RTADV_VALID_LIFETIME 2592000 - /* The value to be placed in the on-link flag */ - int AdvOnLinkFlag; + /* The value to be placed in the on-link flag */ + int AdvOnLinkFlag; - /* The value to be placed in the Preferred Lifetime in the Prefix - Information option, in seconds.*/ - u_int32_t AdvPreferredLifetime; + /* The value to be placed in the Preferred Lifetime in the Prefix + Information option, in seconds.*/ + u_int32_t AdvPreferredLifetime; #define RTADV_PREFERRED_LIFETIME 604800 - /* The value to be placed in the Autonomous Flag. */ - int AdvAutonomousFlag; + /* The value to be placed in the Autonomous Flag. */ + int AdvAutonomousFlag; - /* The value to be placed in the Router Address Flag [RFC6275 7.2]. */ - int AdvRouterAddressFlag; + /* The value to be placed in the Router Address Flag [RFC6275 7.2]. */ + int AdvRouterAddressFlag; #ifndef ND_OPT_PI_FLAG_RADDR #define ND_OPT_PI_FLAG_RADDR 0x20 #endif - }; -extern void rtadv_config_write (struct vty *, struct interface *); +extern void rtadv_config_write(struct vty *, struct interface *); /* RFC4584 Extension to Sockets API for Mobile IPv6 */ @@ -69,11 +67,11 @@ extern void rtadv_config_write (struct vty *, struct interface *); #endif #ifndef HAVE_STRUCT_ND_OPT_ADV_INTERVAL -struct nd_opt_adv_interval { /* Advertisement interval option */ - uint8_t nd_opt_ai_type; - uint8_t nd_opt_ai_len; - uint16_t nd_opt_ai_reserved; - uint32_t nd_opt_ai_interval; +struct nd_opt_adv_interval { /* Advertisement interval option */ + uint8_t nd_opt_ai_type; + uint8_t nd_opt_ai_len; + uint16_t nd_opt_ai_reserved; + uint32_t nd_opt_ai_interval; } __attribute__((__packed__)); #else #ifndef HAVE_STRUCT_ND_OPT_ADV_INTERVAL_ND_OPT_AI_TYPE @@ -86,12 +84,12 @@ struct nd_opt_adv_interval { /* Advertisement interval option */ #endif #ifndef HAVE_STRUCT_ND_OPT_HOMEAGENT_INFO -struct nd_opt_homeagent_info { /* Home Agent info */ - u_int8_t nd_opt_hai_type; - u_int8_t nd_opt_hai_len; - u_int16_t nd_opt_hai_reserved; - u_int16_t nd_opt_hai_preference; - u_int16_t nd_opt_hai_lifetime; +struct nd_opt_homeagent_info { /* Home Agent info */ + u_int8_t nd_opt_hai_type; + u_int8_t nd_opt_hai_len; + u_int16_t nd_opt_hai_reserved; + u_int16_t nd_opt_hai_preference; + u_int16_t nd_opt_hai_lifetime; } __attribute__((__packed__)); #endif @@ -100,14 +98,15 @@ extern const char *rtadv_pref_strs[]; #endif /* HAVE_RTADV */ typedef enum { - RA_ENABLE = 0, - RA_SUPPRESS, + RA_ENABLE = 0, + RA_SUPPRESS, } ipv6_nd_suppress_ra_status; -extern void rtadv_init (struct zebra_ns *); -extern void rtadv_terminate (struct zebra_ns *); -extern void rtadv_cmd_init (void); -extern void zebra_interface_radv_set (struct zserv *client, int sock, u_short length, - struct zebra_vrf *zvrf, int enable); +extern void rtadv_init(struct zebra_ns *); +extern void rtadv_terminate(struct zebra_ns *); +extern void rtadv_cmd_init(void); +extern void zebra_interface_radv_set(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf, + int enable); #endif /* _ZEBRA_RTADV_H */ diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index b1bef571b..5384231f8 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -50,8 +50,7 @@ #define IRE_HOST_REDIRECT 0x0200 /* Host route entry from redirects */ #endif /* IRE_HOST_REDIRECT */ #ifndef IRE_CACHETABLE -#define IRE_CACHETABLE (IRE_CACHE | IRE_BROADCAST | IRE_LOCAL | \ - IRE_LOOPBACK) +#define IRE_CACHETABLE (IRE_CACHE | IRE_BROADCAST | IRE_LOCAL | IRE_LOOPBACK) #endif /* IRE_CACHETABLE */ #undef IPOPT_EOL #undef IPOPT_NOP @@ -71,123 +70,124 @@ #define RT_BUFSIZ 8192 -static void -handle_route_entry (mib2_ipRouteEntry_t *routeEntry) +static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry) { - struct prefix prefix; - struct in_addr tmpaddr, gateway; - union g_addr *ggateway; - u_char zebra_flags = 0; + struct prefix prefix; + struct in_addr tmpaddr, gateway; + union g_addr *ggateway; + u_char zebra_flags = 0; - if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE) - return; + if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE) + return; - if (routeEntry->ipRouteInfo.re_ire_type & IRE_HOST_REDIRECT) - zebra_flags |= ZEBRA_FLAG_SELFROUTE; + if (routeEntry->ipRouteInfo.re_ire_type & IRE_HOST_REDIRECT) + zebra_flags |= ZEBRA_FLAG_SELFROUTE; - prefix.family = AF_INET; + prefix.family = AF_INET; - tmpaddr.s_addr = routeEntry->ipRouteDest; - prefix.u.prefix4 = tmpaddr; + tmpaddr.s_addr = routeEntry->ipRouteDest; + prefix.u.prefix4 = tmpaddr; - tmpaddr.s_addr = routeEntry->ipRouteMask; - prefix.prefixlen = ip_masklen (tmpaddr); + tmpaddr.s_addr = routeEntry->ipRouteMask; + prefix.prefixlen = ip_masklen(tmpaddr); - gateway.s_addr = routeEntry->ipRouteNextHop; - ggateway = (union g_addr *)&gateway; + gateway.s_addr = routeEntry->ipRouteNextHop; + ggateway = (union g_addr *)&gateway; - rib_add (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, - zebra_flags, &prefix, NULL, ggateway, NULL, 0, 0, 0, 0, 0); + rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, + zebra_flags, &prefix, NULL, ggateway, NULL, 0, 0, 0, 0, 0); } -void -route_read (struct zebra_ns *zns) +void route_read(struct zebra_ns *zns) { - char storage[RT_BUFSIZ]; + char storage[RT_BUFSIZ]; - struct T_optmgmt_req *TLIreq = (struct T_optmgmt_req *) storage; - struct T_optmgmt_ack *TLIack = (struct T_optmgmt_ack *) storage; - struct T_error_ack *TLIerr = (struct T_error_ack *) storage; + struct T_optmgmt_req *TLIreq = (struct T_optmgmt_req *)storage; + struct T_optmgmt_ack *TLIack = (struct T_optmgmt_ack *)storage; + struct T_error_ack *TLIerr = (struct T_error_ack *)storage; - struct opthdr *MIB2hdr; + struct opthdr *MIB2hdr; - mib2_ipRouteEntry_t *routeEntry, *lastRouteEntry; + mib2_ipRouteEntry_t *routeEntry, *lastRouteEntry; - struct strbuf msgdata; - int flags, dev, retval, process; + struct strbuf msgdata; + int flags, dev, retval, process; - if ((dev = open (_PATH_GETMSG_ROUTE, O_RDWR)) == -1) { - zlog_warn ("can't open %s: %s", _PATH_GETMSG_ROUTE, - safe_strerror (errno)); + if ((dev = open(_PATH_GETMSG_ROUTE, O_RDWR)) == -1) { + zlog_warn("can't open %s: %s", _PATH_GETMSG_ROUTE, + safe_strerror(errno)); return; } TLIreq->PRIM_type = T_OPTMGMT_REQ; - TLIreq->OPT_offset = sizeof (struct T_optmgmt_req); - TLIreq->OPT_length = sizeof (struct opthdr); + TLIreq->OPT_offset = sizeof(struct T_optmgmt_req); + TLIreq->OPT_length = sizeof(struct opthdr); TLIreq->MGMT_flags = T_CURRENT; - MIB2hdr = (struct opthdr *) &TLIreq[1]; + MIB2hdr = (struct opthdr *)&TLIreq[1]; MIB2hdr->level = MIB2_IP; MIB2hdr->name = 0; MIB2hdr->len = 0; - + msgdata.buf = storage; - msgdata.len = sizeof (struct T_optmgmt_req) + sizeof (struct opthdr); + msgdata.len = sizeof(struct T_optmgmt_req) + sizeof(struct opthdr); flags = 0; - if (putmsg (dev, &msgdata, NULL, flags) == -1) { - zlog_warn ("putmsg failed: %s", safe_strerror (errno)); + if (putmsg(dev, &msgdata, NULL, flags) == -1) { + zlog_warn("putmsg failed: %s", safe_strerror(errno)); goto exit; } - MIB2hdr = (struct opthdr *) &TLIack[1]; - msgdata.maxlen = sizeof (storage); + MIB2hdr = (struct opthdr *)&TLIack[1]; + msgdata.maxlen = sizeof(storage); while (1) { flags = 0; - retval = getmsg (dev, &msgdata, NULL, &flags); + retval = getmsg(dev, &msgdata, NULL, &flags); if (retval == -1) { - zlog_warn ("getmsg(ctl) failed: %s", safe_strerror (errno)); + zlog_warn("getmsg(ctl) failed: %s", + safe_strerror(errno)); goto exit; } /* This is normal loop termination */ - if (retval == 0 && - (size_t)msgdata.len >= sizeof (struct T_optmgmt_ack) && - TLIack->PRIM_type == T_OPTMGMT_ACK && - TLIack->MGMT_flags == T_SUCCESS && - MIB2hdr->len == 0) + if (retval == 0 + && (size_t)msgdata.len >= sizeof(struct T_optmgmt_ack) + && TLIack->PRIM_type == T_OPTMGMT_ACK + && TLIack->MGMT_flags == T_SUCCESS && MIB2hdr->len == 0) break; - if ((size_t)msgdata.len >= sizeof (struct T_error_ack) && - TLIerr->PRIM_type == T_ERROR_ACK) { - zlog_warn ("getmsg(ctl) returned T_ERROR_ACK: %s", - safe_strerror ((TLIerr->TLI_error == TSYSERR) - ? TLIerr->UNIX_error : EPROTO)); + if ((size_t)msgdata.len >= sizeof(struct T_error_ack) + && TLIerr->PRIM_type == T_ERROR_ACK) { + zlog_warn("getmsg(ctl) returned T_ERROR_ACK: %s", + safe_strerror((TLIerr->TLI_error == TSYSERR) + ? TLIerr->UNIX_error + : EPROTO)); break; } /* should dump more debugging info to the log statement, like what GateD does in this instance, but not critical yet. */ - if (retval != MOREDATA || - (size_t)msgdata.len < sizeof (struct T_optmgmt_ack) || - TLIack->PRIM_type != T_OPTMGMT_ACK || - TLIack->MGMT_flags != T_SUCCESS) { + if (retval != MOREDATA + || (size_t)msgdata.len < sizeof(struct T_optmgmt_ack) + || TLIack->PRIM_type != T_OPTMGMT_ACK + || TLIack->MGMT_flags != T_SUCCESS) { errno = ENOMSG; - zlog_warn ("getmsg(ctl) returned bizarreness"); + zlog_warn("getmsg(ctl) returned bizarreness"); break; } /* MIB2_IP_21 is the the pseudo-MIB2 ipRouteTable entry, see <inet/mib2.h>. "This isn't the MIB data you're looking for." */ - process = (MIB2hdr->level == MIB2_IP && - MIB2hdr->name == MIB2_IP_21) ? 1 : 0; + process = (MIB2hdr->level == MIB2_IP + && MIB2hdr->name == MIB2_IP_21) + ? 1 + : 0; /* getmsg writes the data buffer out completely, not to the closest smaller multiple. Unless reassembling @@ -195,65 +195,66 @@ route_read (struct zebra_ns *zns) of a good time, set maxlen to the closest smaller multiple of the size of the datastructure you're retrieving. */ - msgdata.maxlen = sizeof (storage) - (sizeof (storage) - % sizeof (mib2_ipRouteEntry_t)); + msgdata.maxlen = + sizeof(storage) + - (sizeof(storage) % sizeof(mib2_ipRouteEntry_t)); msgdata.len = 0; flags = 0; do { - retval = getmsg (dev, NULL, &msgdata, &flags); + retval = getmsg(dev, NULL, &msgdata, &flags); if (retval == -1) { - zlog_warn ("getmsg(data) failed: %s", - safe_strerror (errno)); + zlog_warn("getmsg(data) failed: %s", + safe_strerror(errno)); goto exit; } if (!(retval == 0 || retval == MOREDATA)) { - zlog_warn ("getmsg(data) returned %d", retval); + zlog_warn("getmsg(data) returned %d", retval); goto exit; } if (process) { - if (msgdata.len % - sizeof (mib2_ipRouteEntry_t) != 0) { - zlog_warn ("getmsg(data) returned " -"msgdata.len = %d (%% sizeof (mib2_ipRouteEntry_t) != 0)", msgdata.len); + if (msgdata.len % sizeof(mib2_ipRouteEntry_t) + != 0) { + zlog_warn( + "getmsg(data) returned " + "msgdata.len = %d (%% sizeof (mib2_ipRouteEntry_t) != 0)", + msgdata.len); goto exit; } - routeEntry = (mib2_ipRouteEntry_t *) - msgdata.buf; - lastRouteEntry = (mib2_ipRouteEntry_t *) - (msgdata.buf + msgdata.len); + routeEntry = (mib2_ipRouteEntry_t *)msgdata.buf; + lastRouteEntry = + (mib2_ipRouteEntry_t *)(msgdata.buf + + msgdata.len); do { - handle_route_entry (routeEntry); + handle_route_entry(routeEntry); } while (++routeEntry < lastRouteEntry); } } while (retval == MOREDATA); } exit: - close (dev); + close(dev); } /* Only implemented for netlink method */ -void -macfdb_read (struct zebra_ns *zns) +void macfdb_read(struct zebra_ns *zns) { } -void macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp, - struct interface *br_if) +void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, + struct interface *br_if) { } -void -neigh_read (struct zebra_ns *zns) +void neigh_read(struct zebra_ns *zns) { } -void neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if) +void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) { } diff --git a/zebra/rtread_netlink.c b/zebra/rtread_netlink.c index d26aa59f8..304f44136 100644 --- a/zebra/rtread_netlink.c +++ b/zebra/rtread_netlink.c @@ -25,28 +25,28 @@ #include "zebra/zserv.h" #include "zebra/rt_netlink.h" -void route_read (struct zebra_ns *zns) +void route_read(struct zebra_ns *zns) { - netlink_route_read (zns); + netlink_route_read(zns); } -void macfdb_read (struct zebra_ns *zns) +void macfdb_read(struct zebra_ns *zns) { - netlink_macfdb_read (zns); + netlink_macfdb_read(zns); } -void macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp, - struct interface *br_if) +void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, + struct interface *br_if) { - netlink_macfdb_read_for_bridge (zns, ifp, br_if); + netlink_macfdb_read_for_bridge(zns, ifp, br_if); } -void neigh_read (struct zebra_ns *zns) +void neigh_read(struct zebra_ns *zns) { - netlink_neigh_read (zns); + netlink_neigh_read(zns); } -void neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if) +void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) { - netlink_neigh_read_for_vlan (zns, vlan_if); + netlink_neigh_read_for_vlan(zns, vlan_if); } diff --git a/zebra/rtread_sysctl.c b/zebra/rtread_sysctl.c index 30e593d87..d3e2eb6fa 100644 --- a/zebra/rtread_sysctl.c +++ b/zebra/rtread_sysctl.c @@ -31,75 +31,62 @@ #include "zebra/kernel_socket.h" /* Kernel routing table read up by sysctl function. */ -void -route_read (struct zebra_ns *zns) +void route_read(struct zebra_ns *zns) { - caddr_t buf, end, ref; - size_t bufsiz; - struct rt_msghdr *rtm; - + caddr_t buf, end, ref; + size_t bufsiz; + struct rt_msghdr *rtm; + #define MIBSIZ 6 - int mib[MIBSIZ] = - { - CTL_NET, - PF_ROUTE, - 0, - 0, - NET_RT_DUMP, - 0 - }; - - if (zns->ns_id != NS_DEFAULT) - return; - - /* Get buffer size. */ - if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) - { - zlog_warn ("sysctl fail: %s", safe_strerror (errno)); - return; - } - - /* Allocate buffer. */ - ref = buf = XMALLOC (MTYPE_TMP, bufsiz); - - /* Read routing table information by calling sysctl(). */ - if (sysctl (mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) - { - zlog_warn ("sysctl() fail by %s", safe_strerror (errno)); - XFREE(MTYPE_TMP, ref); - return; - } - - for (end = buf + bufsiz; buf < end; buf += rtm->rtm_msglen) - { - rtm = (struct rt_msghdr *) buf; - /* We must set RTF_DONE here, so rtm_read() doesn't ignore the message. */ - SET_FLAG (rtm->rtm_flags, RTF_DONE); - rtm_read (rtm); - } - - /* Free buffer. */ - XFREE (MTYPE_TMP, ref); - - return; + int mib[MIBSIZ] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_DUMP, 0}; + + if (zns->ns_id != NS_DEFAULT) + return; + + /* Get buffer size. */ + if (sysctl(mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) { + zlog_warn("sysctl fail: %s", safe_strerror(errno)); + return; + } + + /* Allocate buffer. */ + ref = buf = XMALLOC(MTYPE_TMP, bufsiz); + + /* Read routing table information by calling sysctl(). */ + if (sysctl(mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) { + zlog_warn("sysctl() fail by %s", safe_strerror(errno)); + XFREE(MTYPE_TMP, ref); + return; + } + + for (end = buf + bufsiz; buf < end; buf += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)buf; + /* We must set RTF_DONE here, so rtm_read() doesn't ignore the + * message. */ + SET_FLAG(rtm->rtm_flags, RTF_DONE); + rtm_read(rtm); + } + + /* Free buffer. */ + XFREE(MTYPE_TMP, ref); + + return; } /* Only implemented for the netlink method. */ -void -macfdb_read (struct zebra_ns *zns) +void macfdb_read(struct zebra_ns *zns) { } -void macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp, - struct interface *br_if) +void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, + struct interface *br_if) { } -void -neigh_read (struct zebra_ns *zns) +void neigh_read(struct zebra_ns *zns) { } -void neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if) +void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) { } diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index d04aff2d3..b88bce9e8 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -66,47 +66,46 @@ * Structure that holds state for iterating over all route_node * structures that are candidates for being communicated to the FPM. */ -typedef struct zfpm_rnodes_iter_t_ -{ - rib_tables_iter_t tables_iter; - route_table_iter_t iter; +typedef struct zfpm_rnodes_iter_t_ { + rib_tables_iter_t tables_iter; + route_table_iter_t iter; } zfpm_rnodes_iter_t; /* * Statistics. */ typedef struct zfpm_stats_t_ { - unsigned long connect_calls; - unsigned long connect_no_sock; + unsigned long connect_calls; + unsigned long connect_no_sock; - unsigned long read_cb_calls; + unsigned long read_cb_calls; - unsigned long write_cb_calls; - unsigned long write_calls; - unsigned long partial_writes; - unsigned long max_writes_hit; - unsigned long t_write_yields; + unsigned long write_cb_calls; + unsigned long write_calls; + unsigned long partial_writes; + unsigned long max_writes_hit; + unsigned long t_write_yields; - unsigned long nop_deletes_skipped; - unsigned long route_adds; - unsigned long route_dels; + unsigned long nop_deletes_skipped; + unsigned long route_adds; + unsigned long route_dels; - unsigned long updates_triggered; - unsigned long redundant_triggers; - unsigned long non_fpm_table_triggers; + unsigned long updates_triggered; + unsigned long redundant_triggers; + unsigned long non_fpm_table_triggers; - unsigned long dests_del_after_update; + unsigned long dests_del_after_update; - unsigned long t_conn_down_starts; - unsigned long t_conn_down_dests_processed; - unsigned long t_conn_down_yields; - unsigned long t_conn_down_finishes; + unsigned long t_conn_down_starts; + unsigned long t_conn_down_dests_processed; + unsigned long t_conn_down_yields; + unsigned long t_conn_down_finishes; - unsigned long t_conn_up_starts; - unsigned long t_conn_up_dests_processed; - unsigned long t_conn_up_yields; - unsigned long t_conn_up_aborts; - unsigned long t_conn_up_finishes; + unsigned long t_conn_up_starts; + unsigned long t_conn_up_dests_processed; + unsigned long t_conn_up_yields; + unsigned long t_conn_up_aborts; + unsigned long t_conn_up_finishes; } zfpm_stats_t; @@ -115,187 +114,182 @@ typedef struct zfpm_stats_t_ { */ typedef enum { - /* - * In this state we are not yet ready to connect to the FPM. This - * can happen when this module is disabled, or if we're cleaning up - * after a connection has gone down. - */ - ZFPM_STATE_IDLE, - - /* - * Ready to talk to the FPM and periodically trying to connect to - * it. - */ - ZFPM_STATE_ACTIVE, - - /* - * In the middle of bringing up a TCP connection. Specifically, - * waiting for a connect() call to complete asynchronously. - */ - ZFPM_STATE_CONNECTING, - - /* - * TCP connection to the FPM is up. - */ - ZFPM_STATE_ESTABLISHED + /* + * In this state we are not yet ready to connect to the FPM. This + * can happen when this module is disabled, or if we're cleaning up + * after a connection has gone down. + */ + ZFPM_STATE_IDLE, + + /* + * Ready to talk to the FPM and periodically trying to connect to + * it. + */ + ZFPM_STATE_ACTIVE, + + /* + * In the middle of bringing up a TCP connection. Specifically, + * waiting for a connect() call to complete asynchronously. + */ + ZFPM_STATE_CONNECTING, + + /* + * TCP connection to the FPM is up. + */ + ZFPM_STATE_ESTABLISHED } zfpm_state_t; /* * Message format to be used to communicate with the FPM. */ -typedef enum -{ - ZFPM_MSG_FORMAT_NONE, - ZFPM_MSG_FORMAT_NETLINK, - ZFPM_MSG_FORMAT_PROTOBUF, +typedef enum { + ZFPM_MSG_FORMAT_NONE, + ZFPM_MSG_FORMAT_NETLINK, + ZFPM_MSG_FORMAT_PROTOBUF, } zfpm_msg_format_e; /* * Globals. */ -typedef struct zfpm_glob_t_ -{ - - /* - * True if the FPM module has been enabled. - */ - int enabled; - - /* - * Message format to be used to communicate with the fpm. - */ - zfpm_msg_format_e message_format; - - struct thread_master *master; - - zfpm_state_t state; - - in_addr_t fpm_server; - /* - * Port on which the FPM is running. - */ - int fpm_port; - - /* - * List of rib_dest_t structures to be processed - */ - TAILQ_HEAD (zfpm_dest_q, rib_dest_t_) dest_q; - - /* - * Stream socket to the FPM. - */ - int sock; - - /* - * Buffers for messages to/from the FPM. - */ - struct stream *obuf; - struct stream *ibuf; - - /* - * Threads for I/O. - */ - struct thread *t_connect; - struct thread *t_write; - struct thread *t_read; - - /* - * Thread to clean up after the TCP connection to the FPM goes down - * and the state that belongs to it. - */ - struct thread *t_conn_down; - - struct { - zfpm_rnodes_iter_t iter; - } t_conn_down_state; - - /* - * Thread to take actions once the TCP conn to the FPM comes up, and - * the state that belongs to it. - */ - struct thread *t_conn_up; - - struct { - zfpm_rnodes_iter_t iter; - } t_conn_up_state; - - unsigned long connect_calls; - time_t last_connect_call_time; - - /* - * Stats from the start of the current statistics interval up to - * now. These are the counters we typically update in the code. - */ - zfpm_stats_t stats; - - /* - * Statistics that were gathered in the last collection interval. - */ - zfpm_stats_t last_ivl_stats; - - /* - * Cumulative stats from the last clear to the start of the current - * statistics interval. - */ - zfpm_stats_t cumulative_stats; - - /* - * Stats interval timer. - */ - struct thread *t_stats; - - /* - * If non-zero, the last time when statistics were cleared. - */ - time_t last_stats_clear_time; +typedef struct zfpm_glob_t_ { + + /* + * True if the FPM module has been enabled. + */ + int enabled; + + /* + * Message format to be used to communicate with the fpm. + */ + zfpm_msg_format_e message_format; + + struct thread_master *master; + + zfpm_state_t state; + + in_addr_t fpm_server; + /* + * Port on which the FPM is running. + */ + int fpm_port; + + /* + * List of rib_dest_t structures to be processed + */ + TAILQ_HEAD(zfpm_dest_q, rib_dest_t_) dest_q; + + /* + * Stream socket to the FPM. + */ + int sock; + + /* + * Buffers for messages to/from the FPM. + */ + struct stream *obuf; + struct stream *ibuf; + + /* + * Threads for I/O. + */ + struct thread *t_connect; + struct thread *t_write; + struct thread *t_read; + + /* + * Thread to clean up after the TCP connection to the FPM goes down + * and the state that belongs to it. + */ + struct thread *t_conn_down; + + struct { + zfpm_rnodes_iter_t iter; + } t_conn_down_state; + + /* + * Thread to take actions once the TCP conn to the FPM comes up, and + * the state that belongs to it. + */ + struct thread *t_conn_up; + + struct { + zfpm_rnodes_iter_t iter; + } t_conn_up_state; + + unsigned long connect_calls; + time_t last_connect_call_time; + + /* + * Stats from the start of the current statistics interval up to + * now. These are the counters we typically update in the code. + */ + zfpm_stats_t stats; + + /* + * Statistics that were gathered in the last collection interval. + */ + zfpm_stats_t last_ivl_stats; + + /* + * Cumulative stats from the last clear to the start of the current + * statistics interval. + */ + zfpm_stats_t cumulative_stats; + + /* + * Stats interval timer. + */ + struct thread *t_stats; + + /* + * If non-zero, the last time when statistics were cleared. + */ + time_t last_stats_clear_time; } zfpm_glob_t; static zfpm_glob_t zfpm_glob_space; static zfpm_glob_t *zfpm_g = &zfpm_glob_space; -static int zfpm_trigger_update (struct route_node *rn, const char *reason); +static int zfpm_trigger_update(struct route_node *rn, const char *reason); -static int zfpm_read_cb (struct thread *thread); -static int zfpm_write_cb (struct thread *thread); +static int zfpm_read_cb(struct thread *thread); +static int zfpm_write_cb(struct thread *thread); -static void zfpm_set_state (zfpm_state_t state, const char *reason); -static void zfpm_start_connect_timer (const char *reason); -static void zfpm_start_stats_timer (void); +static void zfpm_set_state(zfpm_state_t state, const char *reason); +static void zfpm_start_connect_timer(const char *reason); +static void zfpm_start_stats_timer(void); /* * zfpm_thread_should_yield */ -static inline int -zfpm_thread_should_yield (struct thread *t) +static inline int zfpm_thread_should_yield(struct thread *t) { - return thread_should_yield (t); + return thread_should_yield(t); } /* * zfpm_state_to_str */ -static const char * -zfpm_state_to_str (zfpm_state_t state) +static const char *zfpm_state_to_str(zfpm_state_t state) { - switch (state) - { + switch (state) { - case ZFPM_STATE_IDLE: - return "idle"; + case ZFPM_STATE_IDLE: + return "idle"; - case ZFPM_STATE_ACTIVE: - return "active"; + case ZFPM_STATE_ACTIVE: + return "active"; - case ZFPM_STATE_CONNECTING: - return "connecting"; + case ZFPM_STATE_CONNECTING: + return "connecting"; - case ZFPM_STATE_ESTABLISHED: - return "established"; + case ZFPM_STATE_ESTABLISHED: + return "established"; - default: - return "unknown"; - } + default: + return "unknown"; + } } /* @@ -303,20 +297,18 @@ zfpm_state_to_str (zfpm_state_t state) * * Returns the time elapsed (in seconds) since the given time. */ -static time_t -zfpm_get_elapsed_time (time_t reference) +static time_t zfpm_get_elapsed_time(time_t reference) { - time_t now; + time_t now; - now = monotime(NULL); + now = monotime(NULL); - if (now < reference) - { - assert (0); - return 0; - } + if (now < reference) { + assert(0); + return 0; + } - return now - reference; + return now - reference; } /* @@ -325,96 +317,89 @@ zfpm_get_elapsed_time (time_t reference) * Returns TRUE if the the given table is to be communicated to the * FPM. */ -static inline int -zfpm_is_table_for_fpm (struct route_table *table) +static inline int zfpm_is_table_for_fpm(struct route_table *table) { - rib_table_info_t *info; + rib_table_info_t *info; - info = rib_table_info (table); + info = rib_table_info(table); - /* - * We only send the unicast tables in the main instance to the FPM - * at this point. - */ - if (zvrf_id (info->zvrf) != 0) - return 0; + /* + * We only send the unicast tables in the main instance to the FPM + * at this point. + */ + if (zvrf_id(info->zvrf) != 0) + return 0; - if (info->safi != SAFI_UNICAST) - return 0; + if (info->safi != SAFI_UNICAST) + return 0; - return 1; + return 1; } /* * zfpm_rnodes_iter_init */ -static inline void -zfpm_rnodes_iter_init (zfpm_rnodes_iter_t *iter) +static inline void zfpm_rnodes_iter_init(zfpm_rnodes_iter_t *iter) { - memset (iter, 0, sizeof (*iter)); - rib_tables_iter_init (&iter->tables_iter); - - /* - * This is a hack, but it makes implementing 'next' easier by - * ensuring that route_table_iter_next() will return NULL the first - * time we call it. - */ - route_table_iter_init (&iter->iter, NULL); - route_table_iter_cleanup (&iter->iter); + memset(iter, 0, sizeof(*iter)); + rib_tables_iter_init(&iter->tables_iter); + + /* + * This is a hack, but it makes implementing 'next' easier by + * ensuring that route_table_iter_next() will return NULL the first + * time we call it. + */ + route_table_iter_init(&iter->iter, NULL); + route_table_iter_cleanup(&iter->iter); } /* * zfpm_rnodes_iter_next */ -static inline struct route_node * -zfpm_rnodes_iter_next (zfpm_rnodes_iter_t *iter) +static inline struct route_node *zfpm_rnodes_iter_next(zfpm_rnodes_iter_t *iter) { - struct route_node *rn; - struct route_table *table; + struct route_node *rn; + struct route_table *table; - while (1) - { - rn = route_table_iter_next (&iter->iter); - if (rn) - return rn; + while (1) { + rn = route_table_iter_next(&iter->iter); + if (rn) + return rn; - /* - * We've made our way through this table, go to the next one. - */ - route_table_iter_cleanup (&iter->iter); + /* + * We've made our way through this table, go to the next one. + */ + route_table_iter_cleanup(&iter->iter); - while ((table = rib_tables_iter_next (&iter->tables_iter))) - { - if (zfpm_is_table_for_fpm (table)) - break; - } + while ((table = rib_tables_iter_next(&iter->tables_iter))) { + if (zfpm_is_table_for_fpm(table)) + break; + } - if (!table) - return NULL; + if (!table) + return NULL; - route_table_iter_init (&iter->iter, table); - } + route_table_iter_init(&iter->iter, table); + } - return NULL; + return NULL; } /* * zfpm_rnodes_iter_pause */ -static inline void -zfpm_rnodes_iter_pause (zfpm_rnodes_iter_t *iter) +static inline void zfpm_rnodes_iter_pause(zfpm_rnodes_iter_t *iter) { - route_table_iter_pause (&iter->iter); + route_table_iter_pause(&iter->iter); } /* * zfpm_rnodes_iter_cleanup */ -static inline void -zfpm_rnodes_iter_cleanup (zfpm_rnodes_iter_t *iter) +static inline void zfpm_rnodes_iter_cleanup(zfpm_rnodes_iter_t *iter) { - route_table_iter_cleanup (&iter->iter); - rib_tables_iter_cleanup (&iter->tables_iter); + route_table_iter_cleanup(&iter->iter); + rib_tables_iter_cleanup(&iter->tables_iter); } /* @@ -422,28 +407,25 @@ zfpm_rnodes_iter_cleanup (zfpm_rnodes_iter_t *iter) * * Initialize a statistics block. */ -static inline void -zfpm_stats_init (zfpm_stats_t *stats) +static inline void zfpm_stats_init(zfpm_stats_t *stats) { - memset (stats, 0, sizeof (*stats)); + memset(stats, 0, sizeof(*stats)); } /* * zfpm_stats_reset */ -static inline void -zfpm_stats_reset (zfpm_stats_t *stats) +static inline void zfpm_stats_reset(zfpm_stats_t *stats) { - zfpm_stats_init (stats); + zfpm_stats_init(stats); } /* * zfpm_stats_copy */ -static inline void -zfpm_stats_copy (const zfpm_stats_t *src, zfpm_stats_t *dest) +static inline void zfpm_stats_copy(const zfpm_stats_t *src, zfpm_stats_t *dest) { - memcpy (dest, src, sizeof (*dest)); + memcpy(dest, src, sizeof(*dest)); } /* @@ -457,68 +439,62 @@ zfpm_stats_copy (const zfpm_stats_t *src, zfpm_stats_t *dest) * structure is composed entirely of counters. This can easily be * changed when necessary. */ -static void -zfpm_stats_compose (const zfpm_stats_t *s1, const zfpm_stats_t *s2, - zfpm_stats_t *result) +static void zfpm_stats_compose(const zfpm_stats_t *s1, const zfpm_stats_t *s2, + zfpm_stats_t *result) { - const unsigned long *p1, *p2; - unsigned long *result_p; - int i, num_counters; + const unsigned long *p1, *p2; + unsigned long *result_p; + int i, num_counters; - p1 = (const unsigned long *) s1; - p2 = (const unsigned long *) s2; - result_p = (unsigned long *) result; + p1 = (const unsigned long *)s1; + p2 = (const unsigned long *)s2; + result_p = (unsigned long *)result; - num_counters = (sizeof (zfpm_stats_t) / sizeof (unsigned long)); + num_counters = (sizeof(zfpm_stats_t) / sizeof(unsigned long)); - for (i = 0; i < num_counters; i++) - { - result_p[i] = p1[i] + p2[i]; - } + for (i = 0; i < num_counters; i++) { + result_p[i] = p1[i] + p2[i]; + } } /* * zfpm_read_on */ -static inline void -zfpm_read_on (void) +static inline void zfpm_read_on(void) { - assert (!zfpm_g->t_read); - assert (zfpm_g->sock >= 0); + assert(!zfpm_g->t_read); + assert(zfpm_g->sock >= 0); - thread_add_read(zfpm_g->master, zfpm_read_cb, 0, zfpm_g->sock, - &zfpm_g->t_read); + thread_add_read(zfpm_g->master, zfpm_read_cb, 0, zfpm_g->sock, + &zfpm_g->t_read); } /* * zfpm_write_on */ -static inline void -zfpm_write_on (void) +static inline void zfpm_write_on(void) { - assert (!zfpm_g->t_write); - assert (zfpm_g->sock >= 0); + assert(!zfpm_g->t_write); + assert(zfpm_g->sock >= 0); - thread_add_write(zfpm_g->master, zfpm_write_cb, 0, zfpm_g->sock, - &zfpm_g->t_write); + thread_add_write(zfpm_g->master, zfpm_write_cb, 0, zfpm_g->sock, + &zfpm_g->t_write); } /* * zfpm_read_off */ -static inline void -zfpm_read_off (void) +static inline void zfpm_read_off(void) { - THREAD_READ_OFF (zfpm_g->t_read); + THREAD_READ_OFF(zfpm_g->t_read); } /* * zfpm_write_off */ -static inline void -zfpm_write_off (void) +static inline void zfpm_write_off(void) { - THREAD_WRITE_OFF (zfpm_g->t_write); + THREAD_WRITE_OFF(zfpm_g->t_write); } /* @@ -527,53 +503,50 @@ zfpm_write_off (void) * Callback for actions to be taken when the connection to the FPM * comes up. */ -static int -zfpm_conn_up_thread_cb (struct thread *thread) +static int zfpm_conn_up_thread_cb(struct thread *thread) { - struct route_node *rnode; - zfpm_rnodes_iter_t *iter; - rib_dest_t *dest; + struct route_node *rnode; + zfpm_rnodes_iter_t *iter; + rib_dest_t *dest; - zfpm_g->t_conn_up = NULL; + zfpm_g->t_conn_up = NULL; - iter = &zfpm_g->t_conn_up_state.iter; + iter = &zfpm_g->t_conn_up_state.iter; - if (zfpm_g->state != ZFPM_STATE_ESTABLISHED) - { - zfpm_debug ("Connection not up anymore, conn_up thread aborting"); - zfpm_g->stats.t_conn_up_aborts++; - goto done; - } - - while ((rnode = zfpm_rnodes_iter_next (iter))) - { - dest = rib_dest_from_rnode (rnode); + if (zfpm_g->state != ZFPM_STATE_ESTABLISHED) { + zfpm_debug( + "Connection not up anymore, conn_up thread aborting"); + zfpm_g->stats.t_conn_up_aborts++; + goto done; + } - if (dest) - { - zfpm_g->stats.t_conn_up_dests_processed++; - zfpm_trigger_update (rnode, NULL); + while ((rnode = zfpm_rnodes_iter_next(iter))) { + dest = rib_dest_from_rnode(rnode); + + if (dest) { + zfpm_g->stats.t_conn_up_dests_processed++; + zfpm_trigger_update(rnode, NULL); + } + + /* + * Yield if need be. + */ + if (!zfpm_thread_should_yield(thread)) + continue; + + zfpm_g->stats.t_conn_up_yields++; + zfpm_rnodes_iter_pause(iter); + zfpm_g->t_conn_up = NULL; + thread_add_timer_msec(zfpm_g->master, zfpm_conn_up_thread_cb, + NULL, 0, &zfpm_g->t_conn_up); + return 0; } - /* - * Yield if need be. - */ - if (!zfpm_thread_should_yield (thread)) - continue; - - zfpm_g->stats.t_conn_up_yields++; - zfpm_rnodes_iter_pause (iter); - zfpm_g->t_conn_up = NULL; - thread_add_timer_msec (zfpm_g->master, zfpm_conn_up_thread_cb, NULL, 0, - &zfpm_g->t_conn_up); - return 0; - } - - zfpm_g->stats.t_conn_up_finishes++; - - done: - zfpm_rnodes_iter_cleanup (iter); - return 0; + zfpm_g->stats.t_conn_up_finishes++; + +done: + zfpm_rnodes_iter_cleanup(iter); + return 0; } /* @@ -581,26 +554,25 @@ zfpm_conn_up_thread_cb (struct thread *thread) * * Called when the connection to the FPM comes up. */ -static void -zfpm_connection_up (const char *detail) +static void zfpm_connection_up(const char *detail) { - assert (zfpm_g->sock >= 0); - zfpm_read_on (); - zfpm_write_on (); - zfpm_set_state (ZFPM_STATE_ESTABLISHED, detail); - - /* - * Start thread to push existing routes to the FPM. - */ - assert (!zfpm_g->t_conn_up); - - zfpm_rnodes_iter_init (&zfpm_g->t_conn_up_state.iter); - - zfpm_debug ("Starting conn_up thread"); - zfpm_g->t_conn_up = NULL; - thread_add_timer_msec(zfpm_g->master, zfpm_conn_up_thread_cb, NULL, 0, - &zfpm_g->t_conn_up); - zfpm_g->stats.t_conn_up_starts++; + assert(zfpm_g->sock >= 0); + zfpm_read_on(); + zfpm_write_on(); + zfpm_set_state(ZFPM_STATE_ESTABLISHED, detail); + + /* + * Start thread to push existing routes to the FPM. + */ + assert(!zfpm_g->t_conn_up); + + zfpm_rnodes_iter_init(&zfpm_g->t_conn_up_state.iter); + + zfpm_debug("Starting conn_up thread"); + zfpm_g->t_conn_up = NULL; + thread_add_timer_msec(zfpm_g->master, zfpm_conn_up_thread_cb, NULL, 0, + &zfpm_g->t_conn_up); + zfpm_g->stats.t_conn_up_starts++; } /* @@ -608,34 +580,32 @@ zfpm_connection_up (const char *detail) * * Check if an asynchronous connect() to the FPM is complete. */ -static void -zfpm_connect_check (void) +static void zfpm_connect_check(void) { - int status; - socklen_t slen; - int ret; - - zfpm_read_off (); - zfpm_write_off (); - - slen = sizeof (status); - ret = getsockopt (zfpm_g->sock, SOL_SOCKET, SO_ERROR, (void *) &status, - &slen); - - if (ret >= 0 && status == 0) - { - zfpm_connection_up ("async connect complete"); - return; - } - - /* - * getsockopt() failed or indicated an error on the socket. - */ - close (zfpm_g->sock); - zfpm_g->sock = -1; - - zfpm_start_connect_timer ("getsockopt() after async connect failed"); - return; + int status; + socklen_t slen; + int ret; + + zfpm_read_off(); + zfpm_write_off(); + + slen = sizeof(status); + ret = getsockopt(zfpm_g->sock, SOL_SOCKET, SO_ERROR, (void *)&status, + &slen); + + if (ret >= 0 && status == 0) { + zfpm_connection_up("async connect complete"); + return; + } + + /* + * getsockopt() failed or indicated an error on the socket. + */ + close(zfpm_g->sock); + zfpm_g->sock = -1; + + zfpm_start_connect_timer("getsockopt() after async connect failed"); + return; } /* @@ -644,63 +614,60 @@ zfpm_connect_check (void) * Callback that is invoked to clean up state after the TCP connection * to the FPM goes down. */ -static int -zfpm_conn_down_thread_cb (struct thread *thread) +static int zfpm_conn_down_thread_cb(struct thread *thread) { - struct route_node *rnode; - zfpm_rnodes_iter_t *iter; - rib_dest_t *dest; + struct route_node *rnode; + zfpm_rnodes_iter_t *iter; + rib_dest_t *dest; - assert (zfpm_g->state == ZFPM_STATE_IDLE); + assert(zfpm_g->state == ZFPM_STATE_IDLE); - zfpm_g->t_conn_down = NULL; + zfpm_g->t_conn_down = NULL; - iter = &zfpm_g->t_conn_down_state.iter; + iter = &zfpm_g->t_conn_down_state.iter; - while ((rnode = zfpm_rnodes_iter_next (iter))) - { - dest = rib_dest_from_rnode (rnode); + while ((rnode = zfpm_rnodes_iter_next(iter))) { + dest = rib_dest_from_rnode(rnode); - if (dest) - { - if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM)) - { - TAILQ_REMOVE (&zfpm_g->dest_q, dest, fpm_q_entries); - } + if (dest) { + if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM)) { + TAILQ_REMOVE(&zfpm_g->dest_q, dest, + fpm_q_entries); + } + + UNSET_FLAG(dest->flags, RIB_DEST_UPDATE_FPM); + UNSET_FLAG(dest->flags, RIB_DEST_SENT_TO_FPM); - UNSET_FLAG (dest->flags, RIB_DEST_UPDATE_FPM); - UNSET_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM); + zfpm_g->stats.t_conn_down_dests_processed++; - zfpm_g->stats.t_conn_down_dests_processed++; + /* + * Check if the dest should be deleted. + */ + rib_gc_dest(rnode); + } - /* - * Check if the dest should be deleted. - */ - rib_gc_dest(rnode); + /* + * Yield if need be. + */ + if (!zfpm_thread_should_yield(thread)) + continue; + + zfpm_g->stats.t_conn_down_yields++; + zfpm_rnodes_iter_pause(iter); + zfpm_g->t_conn_down = NULL; + thread_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb, + NULL, 0, &zfpm_g->t_conn_down); + return 0; } - /* - * Yield if need be. - */ - if (!zfpm_thread_should_yield (thread)) - continue; - - zfpm_g->stats.t_conn_down_yields++; - zfpm_rnodes_iter_pause (iter); - zfpm_g->t_conn_down = NULL; - thread_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb, NULL, 0, - &zfpm_g->t_conn_down); - return 0; - } - - zfpm_g->stats.t_conn_down_finishes++; - zfpm_rnodes_iter_cleanup (iter); - - /* - * Start the process of connecting to the FPM again. - */ - zfpm_start_connect_timer ("cleanup complete"); - return 0; + zfpm_g->stats.t_conn_down_finishes++; + zfpm_rnodes_iter_cleanup(iter); + + /* + * Start the process of connecting to the FPM again. + */ + zfpm_start_connect_timer("cleanup complete"); + return 0; } /* @@ -708,128 +675,121 @@ zfpm_conn_down_thread_cb (struct thread *thread) * * Called when the connection to the FPM has gone down. */ -static void -zfpm_connection_down (const char *detail) +static void zfpm_connection_down(const char *detail) { - if (!detail) - detail = "unknown"; + if (!detail) + detail = "unknown"; - assert (zfpm_g->state == ZFPM_STATE_ESTABLISHED); + assert(zfpm_g->state == ZFPM_STATE_ESTABLISHED); - zlog_info ("connection to the FPM has gone down: %s", detail); + zlog_info("connection to the FPM has gone down: %s", detail); - zfpm_read_off (); - zfpm_write_off (); + zfpm_read_off(); + zfpm_write_off(); - stream_reset (zfpm_g->ibuf); - stream_reset (zfpm_g->obuf); + stream_reset(zfpm_g->ibuf); + stream_reset(zfpm_g->obuf); - if (zfpm_g->sock >= 0) { - close (zfpm_g->sock); - zfpm_g->sock = -1; - } - - /* - * Start thread to clean up state after the connection goes down. - */ - assert (!zfpm_g->t_conn_down); - zfpm_debug ("Starting conn_down thread"); - zfpm_rnodes_iter_init (&zfpm_g->t_conn_down_state.iter); - zfpm_g->t_conn_down = NULL; - thread_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb, NULL, 0, - &zfpm_g->t_conn_down); - zfpm_g->stats.t_conn_down_starts++; + if (zfpm_g->sock >= 0) { + close(zfpm_g->sock); + zfpm_g->sock = -1; + } - zfpm_set_state (ZFPM_STATE_IDLE, detail); + /* + * Start thread to clean up state after the connection goes down. + */ + assert(!zfpm_g->t_conn_down); + zfpm_debug("Starting conn_down thread"); + zfpm_rnodes_iter_init(&zfpm_g->t_conn_down_state.iter); + zfpm_g->t_conn_down = NULL; + thread_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb, NULL, 0, + &zfpm_g->t_conn_down); + zfpm_g->stats.t_conn_down_starts++; + + zfpm_set_state(ZFPM_STATE_IDLE, detail); } /* * zfpm_read_cb */ -static int -zfpm_read_cb (struct thread *thread) +static int zfpm_read_cb(struct thread *thread) { - size_t already; - struct stream *ibuf; - uint16_t msg_len; - fpm_msg_hdr_t *hdr; - - zfpm_g->stats.read_cb_calls++; - zfpm_g->t_read = NULL; - - /* - * Check if async connect is now done. - */ - if (zfpm_g->state == ZFPM_STATE_CONNECTING) - { - zfpm_connect_check(); - return 0; - } - - assert (zfpm_g->state == ZFPM_STATE_ESTABLISHED); - assert (zfpm_g->sock >= 0); - - ibuf = zfpm_g->ibuf; - - already = stream_get_endp (ibuf); - if (already < FPM_MSG_HDR_LEN) - { - ssize_t nbyte; - - nbyte = stream_read_try (ibuf, zfpm_g->sock, FPM_MSG_HDR_LEN - already); - if (nbyte == 0 || nbyte == -1) - { - zfpm_connection_down ("closed socket in read"); - return 0; + size_t already; + struct stream *ibuf; + uint16_t msg_len; + fpm_msg_hdr_t *hdr; + + zfpm_g->stats.read_cb_calls++; + zfpm_g->t_read = NULL; + + /* + * Check if async connect is now done. + */ + if (zfpm_g->state == ZFPM_STATE_CONNECTING) { + zfpm_connect_check(); + return 0; } - if (nbyte != (ssize_t) (FPM_MSG_HDR_LEN - already)) - goto done; + assert(zfpm_g->state == ZFPM_STATE_ESTABLISHED); + assert(zfpm_g->sock >= 0); - already = FPM_MSG_HDR_LEN; - } + ibuf = zfpm_g->ibuf; - stream_set_getp (ibuf, 0); + already = stream_get_endp(ibuf); + if (already < FPM_MSG_HDR_LEN) { + ssize_t nbyte; - hdr = (fpm_msg_hdr_t *) stream_pnt (ibuf); + nbyte = stream_read_try(ibuf, zfpm_g->sock, + FPM_MSG_HDR_LEN - already); + if (nbyte == 0 || nbyte == -1) { + zfpm_connection_down("closed socket in read"); + return 0; + } - if (!fpm_msg_hdr_ok (hdr)) - { - zfpm_connection_down ("invalid message header"); - return 0; - } + if (nbyte != (ssize_t)(FPM_MSG_HDR_LEN - already)) + goto done; - msg_len = fpm_msg_len (hdr); + already = FPM_MSG_HDR_LEN; + } - /* - * Read out the rest of the packet. - */ - if (already < msg_len) - { - ssize_t nbyte; + stream_set_getp(ibuf, 0); - nbyte = stream_read_try (ibuf, zfpm_g->sock, msg_len - already); + hdr = (fpm_msg_hdr_t *)stream_pnt(ibuf); - if (nbyte == 0 || nbyte == -1) - { - zfpm_connection_down ("failed to read message"); - return 0; + if (!fpm_msg_hdr_ok(hdr)) { + zfpm_connection_down("invalid message header"); + return 0; } - if (nbyte != (ssize_t) (msg_len - already)) - goto done; - } + msg_len = fpm_msg_len(hdr); - zfpm_debug ("Read out a full fpm message"); + /* + * Read out the rest of the packet. + */ + if (already < msg_len) { + ssize_t nbyte; - /* - * Just throw it away for now. - */ - stream_reset (ibuf); + nbyte = stream_read_try(ibuf, zfpm_g->sock, msg_len - already); - done: - zfpm_read_on (); - return 0; + if (nbyte == 0 || nbyte == -1) { + zfpm_connection_down("failed to read message"); + return 0; + } + + if (nbyte != (ssize_t)(msg_len - already)) + goto done; + } + + zfpm_debug("Read out a full fpm message"); + + /* + * Just throw it away for now. + */ + stream_reset(ibuf); + +done: + zfpm_read_on(); + return 0; } /* @@ -837,24 +797,23 @@ zfpm_read_cb (struct thread *thread) * * Returns TRUE if we may have something to write to the FPM. */ -static int -zfpm_writes_pending (void) +static int zfpm_writes_pending(void) { - /* - * Check if there is any data in the outbound buffer that has not - * been written to the socket yet. - */ - if (stream_get_endp (zfpm_g->obuf) - stream_get_getp (zfpm_g->obuf)) - return 1; + /* + * Check if there is any data in the outbound buffer that has not + * been written to the socket yet. + */ + if (stream_get_endp(zfpm_g->obuf) - stream_get_getp(zfpm_g->obuf)) + return 1; - /* - * Check if there are any prefixes on the outbound queue. - */ - if (!TAILQ_EMPTY (&zfpm_g->dest_q)) - return 1; + /* + * Check if there are any prefixes on the outbound queue. + */ + if (!TAILQ_EMPTY(&zfpm_g->dest_q)) + return 1; - return 0; + return 0; } /* @@ -865,44 +824,44 @@ zfpm_writes_pending (void) * Returns the number of bytes written to the buffer. 0 or a negative * value indicates an error. */ -static inline int -zfpm_encode_route (rib_dest_t *dest, struct route_entry *re, char *in_buf, - size_t in_buf_len, fpm_msg_type_e *msg_type) +static inline int zfpm_encode_route(rib_dest_t *dest, struct route_entry *re, + char *in_buf, size_t in_buf_len, + fpm_msg_type_e *msg_type) { - size_t len; + size_t len; #ifdef HAVE_NETLINK - int cmd; + int cmd; #endif - len = 0; + len = 0; - *msg_type = FPM_MSG_TYPE_NONE; + *msg_type = FPM_MSG_TYPE_NONE; - switch (zfpm_g->message_format) { + switch (zfpm_g->message_format) { - case ZFPM_MSG_FORMAT_PROTOBUF: + case ZFPM_MSG_FORMAT_PROTOBUF: #ifdef HAVE_PROTOBUF - len = zfpm_protobuf_encode_route (dest, re, (uint8_t *) in_buf, - in_buf_len); - *msg_type = FPM_MSG_TYPE_PROTOBUF; + len = zfpm_protobuf_encode_route(dest, re, (uint8_t *)in_buf, + in_buf_len); + *msg_type = FPM_MSG_TYPE_PROTOBUF; #endif - break; + break; - case ZFPM_MSG_FORMAT_NETLINK: + case ZFPM_MSG_FORMAT_NETLINK: #ifdef HAVE_NETLINK - *msg_type = FPM_MSG_TYPE_NETLINK; - cmd = re ? RTM_NEWROUTE : RTM_DELROUTE; - len = zfpm_netlink_encode_route (cmd, dest, re, in_buf, in_buf_len); - assert(fpm_msg_align(len) == len); - *msg_type = FPM_MSG_TYPE_NETLINK; + *msg_type = FPM_MSG_TYPE_NETLINK; + cmd = re ? RTM_NEWROUTE : RTM_DELROUTE; + len = zfpm_netlink_encode_route(cmd, dest, re, in_buf, + in_buf_len); + assert(fpm_msg_align(len) == len); + *msg_type = FPM_MSG_TYPE_NETLINK; #endif /* HAVE_NETLINK */ - break; - - default: - break; - } + break; - return len; + default: + break; + } + return len; } /* @@ -910,23 +869,22 @@ zfpm_encode_route (rib_dest_t *dest, struct route_entry *re, char *in_buf, * * Returns the re that is to be sent to the FPM for a given dest. */ -struct route_entry * -zfpm_route_for_update (rib_dest_t *dest) +struct route_entry *zfpm_route_for_update(rib_dest_t *dest) { - struct route_entry *re; + struct route_entry *re; - RE_DEST_FOREACH_ROUTE (dest, re) - { - if (!CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB)) - continue; + RE_DEST_FOREACH_ROUTE(dest, re) + { + if (!CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) + continue; - return re; - } + return re; + } - /* - * We have no route for this destination. - */ - return NULL; + /* + * We have no route for this destination. + */ + return NULL; } /* @@ -935,262 +893,247 @@ zfpm_route_for_update (rib_dest_t *dest) * Process the outgoing queue and write messages to the outbound * buffer. */ -static void -zfpm_build_updates (void) +static void zfpm_build_updates(void) { - struct stream *s; - rib_dest_t *dest; - unsigned char *buf, *data, *buf_end; - size_t msg_len; - size_t data_len; - fpm_msg_hdr_t *hdr; - struct route_entry *re; - int is_add, write_msg; - fpm_msg_type_e msg_type; - - s = zfpm_g->obuf; - - assert (stream_empty (s)); - - do { - - /* - * Make sure there is enough space to write another message. - */ - if (STREAM_WRITEABLE (s) < FPM_MAX_MSG_LEN) - break; - - buf = STREAM_DATA (s) + stream_get_endp (s); - buf_end = buf + STREAM_WRITEABLE (s); - - dest = TAILQ_FIRST (&zfpm_g->dest_q); - if (!dest) - break; - - assert (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM)); - - hdr = (fpm_msg_hdr_t *) buf; - hdr->version = FPM_PROTO_VERSION; - - data = fpm_msg_data (hdr); - - re = zfpm_route_for_update (dest); - is_add = re ? 1 : 0; - - write_msg = 1; - - /* - * If this is a route deletion, and we have not sent the route to - * the FPM previously, skip it. - */ - if (!is_add && !CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM)) - { - write_msg = 0; - zfpm_g->stats.nop_deletes_skipped++; - } - - if (write_msg) { - data_len = zfpm_encode_route (dest, re, (char *) data, buf_end - data, - &msg_type); - - assert (data_len); - if (data_len) - { - hdr->msg_type = msg_type; - msg_len = fpm_data_len_to_msg_len (data_len); - hdr->msg_len = htons (msg_len); - stream_forward_endp (s, msg_len); - - if (is_add) - zfpm_g->stats.route_adds++; - else - zfpm_g->stats.route_dels++; - } - } - - /* - * Remove the dest from the queue, and reset the flag. - */ - UNSET_FLAG (dest->flags, RIB_DEST_UPDATE_FPM); - TAILQ_REMOVE (&zfpm_g->dest_q, dest, fpm_q_entries); - - if (is_add) - { - SET_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM); - } - else - { - UNSET_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM); - } - - /* - * Delete the destination if necessary. - */ - if (rib_gc_dest (dest->rnode)) - zfpm_g->stats.dests_del_after_update++; - - } while (1); - + struct stream *s; + rib_dest_t *dest; + unsigned char *buf, *data, *buf_end; + size_t msg_len; + size_t data_len; + fpm_msg_hdr_t *hdr; + struct route_entry *re; + int is_add, write_msg; + fpm_msg_type_e msg_type; + + s = zfpm_g->obuf; + + assert(stream_empty(s)); + + do { + + /* + * Make sure there is enough space to write another message. + */ + if (STREAM_WRITEABLE(s) < FPM_MAX_MSG_LEN) + break; + + buf = STREAM_DATA(s) + stream_get_endp(s); + buf_end = buf + STREAM_WRITEABLE(s); + + dest = TAILQ_FIRST(&zfpm_g->dest_q); + if (!dest) + break; + + assert(CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM)); + + hdr = (fpm_msg_hdr_t *)buf; + hdr->version = FPM_PROTO_VERSION; + + data = fpm_msg_data(hdr); + + re = zfpm_route_for_update(dest); + is_add = re ? 1 : 0; + + write_msg = 1; + + /* + * If this is a route deletion, and we have not sent the route + * to + * the FPM previously, skip it. + */ + if (!is_add && !CHECK_FLAG(dest->flags, RIB_DEST_SENT_TO_FPM)) { + write_msg = 0; + zfpm_g->stats.nop_deletes_skipped++; + } + + if (write_msg) { + data_len = zfpm_encode_route(dest, re, (char *)data, + buf_end - data, &msg_type); + + assert(data_len); + if (data_len) { + hdr->msg_type = msg_type; + msg_len = fpm_data_len_to_msg_len(data_len); + hdr->msg_len = htons(msg_len); + stream_forward_endp(s, msg_len); + + if (is_add) + zfpm_g->stats.route_adds++; + else + zfpm_g->stats.route_dels++; + } + } + + /* + * Remove the dest from the queue, and reset the flag. + */ + UNSET_FLAG(dest->flags, RIB_DEST_UPDATE_FPM); + TAILQ_REMOVE(&zfpm_g->dest_q, dest, fpm_q_entries); + + if (is_add) { + SET_FLAG(dest->flags, RIB_DEST_SENT_TO_FPM); + } else { + UNSET_FLAG(dest->flags, RIB_DEST_SENT_TO_FPM); + } + + /* + * Delete the destination if necessary. + */ + if (rib_gc_dest(dest->rnode)) + zfpm_g->stats.dests_del_after_update++; + + } while (1); } /* * zfpm_write_cb */ -static int -zfpm_write_cb (struct thread *thread) +static int zfpm_write_cb(struct thread *thread) { - struct stream *s; - int num_writes; + struct stream *s; + int num_writes; + + zfpm_g->stats.write_cb_calls++; + zfpm_g->t_write = NULL; + + /* + * Check if async connect is now done. + */ + if (zfpm_g->state == ZFPM_STATE_CONNECTING) { + zfpm_connect_check(); + return 0; + } - zfpm_g->stats.write_cb_calls++; - zfpm_g->t_write = NULL; + assert(zfpm_g->state == ZFPM_STATE_ESTABLISHED); + assert(zfpm_g->sock >= 0); - /* - * Check if async connect is now done. - */ - if (zfpm_g->state == ZFPM_STATE_CONNECTING) - { - zfpm_connect_check (); - return 0; - } + num_writes = 0; - assert (zfpm_g->state == ZFPM_STATE_ESTABLISHED); - assert (zfpm_g->sock >= 0); + do { + int bytes_to_write, bytes_written; - num_writes = 0; + s = zfpm_g->obuf; - do - { - int bytes_to_write, bytes_written; + /* + * If the stream is empty, try fill it up with data. + */ + if (stream_empty(s)) { + zfpm_build_updates(); + } - s = zfpm_g->obuf; + bytes_to_write = stream_get_endp(s) - stream_get_getp(s); + if (!bytes_to_write) + break; - /* - * If the stream is empty, try fill it up with data. - */ - if (stream_empty (s)) - { - zfpm_build_updates (); - } + bytes_written = + write(zfpm_g->sock, STREAM_PNT(s), bytes_to_write); + zfpm_g->stats.write_calls++; + num_writes++; - bytes_to_write = stream_get_endp (s) - stream_get_getp (s); - if (!bytes_to_write) - break; + if (bytes_written < 0) { + if (ERRNO_IO_RETRY(errno)) + break; - bytes_written = write (zfpm_g->sock, STREAM_PNT (s), bytes_to_write); - zfpm_g->stats.write_calls++; - num_writes++; + zfpm_connection_down("failed to write to socket"); + return 0; + } - if (bytes_written < 0) - { - if (ERRNO_IO_RETRY (errno)) - break; + if (bytes_written != bytes_to_write) { - zfpm_connection_down ("failed to write to socket"); - return 0; - } - - if (bytes_written != bytes_to_write) - { + /* + * Partial write. + */ + stream_forward_getp(s, bytes_written); + zfpm_g->stats.partial_writes++; + break; + } - /* - * Partial write. - */ - stream_forward_getp (s, bytes_written); - zfpm_g->stats.partial_writes++; - break; - } - - /* - * We've written out the entire contents of the stream. - */ - stream_reset (s); + /* + * We've written out the entire contents of the stream. + */ + stream_reset(s); - if (num_writes >= ZFPM_MAX_WRITES_PER_RUN) - { - zfpm_g->stats.max_writes_hit++; - break; - } + if (num_writes >= ZFPM_MAX_WRITES_PER_RUN) { + zfpm_g->stats.max_writes_hit++; + break; + } - if (zfpm_thread_should_yield (thread)) - { - zfpm_g->stats.t_write_yields++; - break; - } - } while (1); + if (zfpm_thread_should_yield(thread)) { + zfpm_g->stats.t_write_yields++; + break; + } + } while (1); - if (zfpm_writes_pending ()) - zfpm_write_on (); + if (zfpm_writes_pending()) + zfpm_write_on(); - return 0; + return 0; } /* * zfpm_connect_cb */ -static int -zfpm_connect_cb (struct thread *t) +static int zfpm_connect_cb(struct thread *t) { - int sock, ret; - struct sockaddr_in serv; - - zfpm_g->t_connect = NULL; - assert (zfpm_g->state == ZFPM_STATE_ACTIVE); - - sock = socket (AF_INET, SOCK_STREAM, 0); - if (sock < 0) - { - zfpm_debug ("Failed to create socket for connect(): %s", strerror(errno)); - zfpm_g->stats.connect_no_sock++; - return 0; - } - - set_nonblocking(sock); - - /* Make server socket. */ - memset (&serv, 0, sizeof (serv)); - serv.sin_family = AF_INET; - serv.sin_port = htons (zfpm_g->fpm_port); + int sock, ret; + struct sockaddr_in serv; + + zfpm_g->t_connect = NULL; + assert(zfpm_g->state == ZFPM_STATE_ACTIVE); + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + zfpm_debug("Failed to create socket for connect(): %s", + strerror(errno)); + zfpm_g->stats.connect_no_sock++; + return 0; + } + + set_nonblocking(sock); + + /* Make server socket. */ + memset(&serv, 0, sizeof(serv)); + serv.sin_family = AF_INET; + serv.sin_port = htons(zfpm_g->fpm_port); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - serv.sin_len = sizeof (struct sockaddr_in); + serv.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - if (!zfpm_g->fpm_server) - serv.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - else - serv.sin_addr.s_addr = (zfpm_g->fpm_server); - - /* - * Connect to the FPM. - */ - zfpm_g->connect_calls++; - zfpm_g->stats.connect_calls++; - zfpm_g->last_connect_call_time = monotime(NULL); - - ret = connect (sock, (struct sockaddr *) &serv, sizeof (serv)); - if (ret >= 0) - { - zfpm_g->sock = sock; - zfpm_connection_up ("connect succeeded"); - return 1; - } - - if (errno == EINPROGRESS) - { - zfpm_g->sock = sock; - zfpm_read_on (); - zfpm_write_on (); - zfpm_set_state (ZFPM_STATE_CONNECTING, "async connect in progress"); - return 0; - } - - zlog_info ("can't connect to FPM %d: %s", sock, safe_strerror (errno)); - close (sock); - - /* - * Restart timer for retrying connection. - */ - zfpm_start_connect_timer ("connect() failed"); - return 0; + if (!zfpm_g->fpm_server) + serv.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + else + serv.sin_addr.s_addr = (zfpm_g->fpm_server); + + /* + * Connect to the FPM. + */ + zfpm_g->connect_calls++; + zfpm_g->stats.connect_calls++; + zfpm_g->last_connect_call_time = monotime(NULL); + + ret = connect(sock, (struct sockaddr *)&serv, sizeof(serv)); + if (ret >= 0) { + zfpm_g->sock = sock; + zfpm_connection_up("connect succeeded"); + return 1; + } + + if (errno == EINPROGRESS) { + zfpm_g->sock = sock; + zfpm_read_on(); + zfpm_write_on(); + zfpm_set_state(ZFPM_STATE_CONNECTING, + "async connect in progress"); + return 0; + } + + zlog_info("can't connect to FPM %d: %s", sock, safe_strerror(errno)); + close(sock); + + /* + * Restart timer for retrying connection. + */ + zfpm_start_connect_timer("connect() failed"); + return 0; } /* @@ -1198,50 +1141,49 @@ zfpm_connect_cb (struct thread *t) * * Move state machine into the given state. */ -static void -zfpm_set_state (zfpm_state_t state, const char *reason) +static void zfpm_set_state(zfpm_state_t state, const char *reason) { - zfpm_state_t cur_state = zfpm_g->state; - - if (!reason) - reason = "Unknown"; - - if (state == cur_state) - return; - - zfpm_debug("beginning state transition %s -> %s. Reason: %s", - zfpm_state_to_str (cur_state), zfpm_state_to_str (state), - reason); - - switch (state) { - - case ZFPM_STATE_IDLE: - assert (cur_state == ZFPM_STATE_ESTABLISHED); - break; - - case ZFPM_STATE_ACTIVE: - assert (cur_state == ZFPM_STATE_IDLE || - cur_state == ZFPM_STATE_CONNECTING); - assert (zfpm_g->t_connect); - break; - - case ZFPM_STATE_CONNECTING: - assert (zfpm_g->sock); - assert (cur_state == ZFPM_STATE_ACTIVE); - assert (zfpm_g->t_read); - assert (zfpm_g->t_write); - break; - - case ZFPM_STATE_ESTABLISHED: - assert (cur_state == ZFPM_STATE_ACTIVE || - cur_state == ZFPM_STATE_CONNECTING); - assert (zfpm_g->sock); - assert (zfpm_g->t_read); - assert (zfpm_g->t_write); - break; - } - - zfpm_g->state = state; + zfpm_state_t cur_state = zfpm_g->state; + + if (!reason) + reason = "Unknown"; + + if (state == cur_state) + return; + + zfpm_debug("beginning state transition %s -> %s. Reason: %s", + zfpm_state_to_str(cur_state), zfpm_state_to_str(state), + reason); + + switch (state) { + + case ZFPM_STATE_IDLE: + assert(cur_state == ZFPM_STATE_ESTABLISHED); + break; + + case ZFPM_STATE_ACTIVE: + assert(cur_state == ZFPM_STATE_IDLE + || cur_state == ZFPM_STATE_CONNECTING); + assert(zfpm_g->t_connect); + break; + + case ZFPM_STATE_CONNECTING: + assert(zfpm_g->sock); + assert(cur_state == ZFPM_STATE_ACTIVE); + assert(zfpm_g->t_read); + assert(zfpm_g->t_write); + break; + + case ZFPM_STATE_ESTABLISHED: + assert(cur_state == ZFPM_STATE_ACTIVE + || cur_state == ZFPM_STATE_CONNECTING); + assert(zfpm_g->sock); + assert(zfpm_g->t_read); + assert(zfpm_g->t_write); + break; + } + + zfpm_g->state = state; } /* @@ -1250,49 +1192,46 @@ zfpm_set_state (zfpm_state_t state, const char *reason) * Returns the number of seconds after which we should attempt to * reconnect to the FPM. */ -static long -zfpm_calc_connect_delay (void) +static long zfpm_calc_connect_delay(void) { - time_t elapsed; + time_t elapsed; - /* - * Return 0 if this is our first attempt to connect. - */ - if (zfpm_g->connect_calls == 0) - { - return 0; - } + /* + * Return 0 if this is our first attempt to connect. + */ + if (zfpm_g->connect_calls == 0) { + return 0; + } - elapsed = zfpm_get_elapsed_time (zfpm_g->last_connect_call_time); + elapsed = zfpm_get_elapsed_time(zfpm_g->last_connect_call_time); - if (elapsed > ZFPM_CONNECT_RETRY_IVL) { - return 0; - } + if (elapsed > ZFPM_CONNECT_RETRY_IVL) { + return 0; + } - return ZFPM_CONNECT_RETRY_IVL - elapsed; + return ZFPM_CONNECT_RETRY_IVL - elapsed; } /* * zfpm_start_connect_timer */ -static void -zfpm_start_connect_timer (const char *reason) +static void zfpm_start_connect_timer(const char *reason) { - long delay_secs; + long delay_secs; - assert (!zfpm_g->t_connect); - assert (zfpm_g->sock < 0); + assert(!zfpm_g->t_connect); + assert(zfpm_g->sock < 0); - assert(zfpm_g->state == ZFPM_STATE_IDLE || - zfpm_g->state == ZFPM_STATE_ACTIVE || - zfpm_g->state == ZFPM_STATE_CONNECTING); + assert(zfpm_g->state == ZFPM_STATE_IDLE + || zfpm_g->state == ZFPM_STATE_ACTIVE + || zfpm_g->state == ZFPM_STATE_CONNECTING); - delay_secs = zfpm_calc_connect_delay(); - zfpm_debug ("scheduling connect in %ld seconds", delay_secs); + delay_secs = zfpm_calc_connect_delay(); + zfpm_debug("scheduling connect in %ld seconds", delay_secs); - thread_add_timer(zfpm_g->master, zfpm_connect_cb, 0, delay_secs, - &zfpm_g->t_connect); - zfpm_set_state (ZFPM_STATE_ACTIVE, reason); + thread_add_timer(zfpm_g->master, zfpm_connect_cb, 0, delay_secs, + &zfpm_g->t_connect); + zfpm_set_state(ZFPM_STATE_ACTIVE, reason); } /* @@ -1300,10 +1239,9 @@ zfpm_start_connect_timer (const char *reason) * * Returns TRUE if the zebra FPM module has been enabled. */ -static inline int -zfpm_is_enabled (void) +static inline int zfpm_is_enabled(void) { - return zfpm_g->enabled; + return zfpm_g->enabled; } /* @@ -1311,15 +1249,14 @@ zfpm_is_enabled (void) * * Returns TRUE if the connection to the FPM is up. */ -static inline int -zfpm_conn_is_up (void) +static inline int zfpm_conn_is_up(void) { - if (zfpm_g->state != ZFPM_STATE_ESTABLISHED) - return 0; + if (zfpm_g->state != ZFPM_STATE_ESTABLISHED) + return 0; - assert (zfpm_g->sock >= 0); + assert(zfpm_g->sock >= 0); - return 1; + return 1; } /* @@ -1328,194 +1265,185 @@ zfpm_conn_is_up (void) * The zebra code invokes this function to indicate that we should * send an update to the FPM about the given route_node. */ -static int -zfpm_trigger_update (struct route_node *rn, const char *reason) +static int zfpm_trigger_update(struct route_node *rn, const char *reason) { - rib_dest_t *dest; - char buf[PREFIX_STRLEN]; - - /* - * Ignore if the connection is down. We will update the FPM about - * all destinations once the connection comes up. - */ - if (!zfpm_conn_is_up ()) - return 0; - - dest = rib_dest_from_rnode (rn); - - /* - * Ignore the trigger if the dest is not in a table that we would - * send to the FPM. - */ - if (!zfpm_is_table_for_fpm (rib_dest_table (dest))) - { - zfpm_g->stats.non_fpm_table_triggers++; - return 0; - } - - if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM)) { - zfpm_g->stats.redundant_triggers++; - return 0; - } - - if (reason) - { - zfpm_debug ("%s triggering update to FPM - Reason: %s", - prefix2str (&rn->p, buf, sizeof(buf)), reason); - } - - SET_FLAG (dest->flags, RIB_DEST_UPDATE_FPM); - TAILQ_INSERT_TAIL (&zfpm_g->dest_q, dest, fpm_q_entries); - zfpm_g->stats.updates_triggered++; - - /* - * Make sure that writes are enabled. - */ - if (zfpm_g->t_write) - return 0; - - zfpm_write_on (); - return 0; + rib_dest_t *dest; + char buf[PREFIX_STRLEN]; + + /* + * Ignore if the connection is down. We will update the FPM about + * all destinations once the connection comes up. + */ + if (!zfpm_conn_is_up()) + return 0; + + dest = rib_dest_from_rnode(rn); + + /* + * Ignore the trigger if the dest is not in a table that we would + * send to the FPM. + */ + if (!zfpm_is_table_for_fpm(rib_dest_table(dest))) { + zfpm_g->stats.non_fpm_table_triggers++; + return 0; + } + + if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM)) { + zfpm_g->stats.redundant_triggers++; + return 0; + } + + if (reason) { + zfpm_debug("%s triggering update to FPM - Reason: %s", + prefix2str(&rn->p, buf, sizeof(buf)), reason); + } + + SET_FLAG(dest->flags, RIB_DEST_UPDATE_FPM); + TAILQ_INSERT_TAIL(&zfpm_g->dest_q, dest, fpm_q_entries); + zfpm_g->stats.updates_triggered++; + + /* + * Make sure that writes are enabled. + */ + if (zfpm_g->t_write) + return 0; + + zfpm_write_on(); + return 0; } /* * zfpm_stats_timer_cb */ -static int -zfpm_stats_timer_cb (struct thread *t) +static int zfpm_stats_timer_cb(struct thread *t) { - zfpm_g->t_stats = NULL; + zfpm_g->t_stats = NULL; - /* - * Remember the stats collected in the last interval for display - * purposes. - */ - zfpm_stats_copy (&zfpm_g->stats, &zfpm_g->last_ivl_stats); + /* + * Remember the stats collected in the last interval for display + * purposes. + */ + zfpm_stats_copy(&zfpm_g->stats, &zfpm_g->last_ivl_stats); - /* - * Add the current set of stats into the cumulative statistics. - */ - zfpm_stats_compose (&zfpm_g->cumulative_stats, &zfpm_g->stats, - &zfpm_g->cumulative_stats); + /* + * Add the current set of stats into the cumulative statistics. + */ + zfpm_stats_compose(&zfpm_g->cumulative_stats, &zfpm_g->stats, + &zfpm_g->cumulative_stats); - /* - * Start collecting stats afresh over the next interval. - */ - zfpm_stats_reset (&zfpm_g->stats); + /* + * Start collecting stats afresh over the next interval. + */ + zfpm_stats_reset(&zfpm_g->stats); - zfpm_start_stats_timer (); + zfpm_start_stats_timer(); - return 0; + return 0; } /* * zfpm_stop_stats_timer */ -static void -zfpm_stop_stats_timer (void) +static void zfpm_stop_stats_timer(void) { - if (!zfpm_g->t_stats) - return; + if (!zfpm_g->t_stats) + return; - zfpm_debug ("Stopping existing stats timer"); - THREAD_TIMER_OFF (zfpm_g->t_stats); + zfpm_debug("Stopping existing stats timer"); + THREAD_TIMER_OFF(zfpm_g->t_stats); } /* * zfpm_start_stats_timer */ -void -zfpm_start_stats_timer (void) +void zfpm_start_stats_timer(void) { - assert (!zfpm_g->t_stats); + assert(!zfpm_g->t_stats); - thread_add_timer(zfpm_g->master, zfpm_stats_timer_cb, 0, - ZFPM_STATS_IVL_SECS, &zfpm_g->t_stats); + thread_add_timer(zfpm_g->master, zfpm_stats_timer_cb, 0, + ZFPM_STATS_IVL_SECS, &zfpm_g->t_stats); } /* * Helper macro for zfpm_show_stats() below. */ -#define ZFPM_SHOW_STAT(counter) \ - do { \ - vty_out (vty, "%-40s %10lu %16lu\n", #counter, total_stats.counter, \ - zfpm_g->last_ivl_stats.counter); \ - } while (0) +#define ZFPM_SHOW_STAT(counter) \ + do { \ + vty_out(vty, "%-40s %10lu %16lu\n", #counter, \ + total_stats.counter, zfpm_g->last_ivl_stats.counter); \ + } while (0) /* * zfpm_show_stats */ -static void -zfpm_show_stats (struct vty *vty) +static void zfpm_show_stats(struct vty *vty) { - zfpm_stats_t total_stats; - time_t elapsed; - - vty_out (vty, "\n%-40s %10s Last %2d secs\n\n", "Counter", - "Total", ZFPM_STATS_IVL_SECS); - - /* - * Compute the total stats up to this instant. - */ - zfpm_stats_compose (&zfpm_g->cumulative_stats, &zfpm_g->stats, - &total_stats); - - ZFPM_SHOW_STAT (connect_calls); - ZFPM_SHOW_STAT (connect_no_sock); - ZFPM_SHOW_STAT (read_cb_calls); - ZFPM_SHOW_STAT (write_cb_calls); - ZFPM_SHOW_STAT (write_calls); - ZFPM_SHOW_STAT (partial_writes); - ZFPM_SHOW_STAT (max_writes_hit); - ZFPM_SHOW_STAT (t_write_yields); - ZFPM_SHOW_STAT (nop_deletes_skipped); - ZFPM_SHOW_STAT (route_adds); - ZFPM_SHOW_STAT (route_dels); - ZFPM_SHOW_STAT (updates_triggered); - ZFPM_SHOW_STAT (non_fpm_table_triggers); - ZFPM_SHOW_STAT (redundant_triggers); - ZFPM_SHOW_STAT (dests_del_after_update); - ZFPM_SHOW_STAT (t_conn_down_starts); - ZFPM_SHOW_STAT (t_conn_down_dests_processed); - ZFPM_SHOW_STAT (t_conn_down_yields); - ZFPM_SHOW_STAT (t_conn_down_finishes); - ZFPM_SHOW_STAT (t_conn_up_starts); - ZFPM_SHOW_STAT (t_conn_up_dests_processed); - ZFPM_SHOW_STAT (t_conn_up_yields); - ZFPM_SHOW_STAT (t_conn_up_aborts); - ZFPM_SHOW_STAT (t_conn_up_finishes); - - if (!zfpm_g->last_stats_clear_time) - return; - - elapsed = zfpm_get_elapsed_time (zfpm_g->last_stats_clear_time); - - vty_out (vty, "\nStats were cleared %lu seconds ago\n", - (unsigned long)elapsed); + zfpm_stats_t total_stats; + time_t elapsed; + + vty_out(vty, "\n%-40s %10s Last %2d secs\n\n", "Counter", "Total", + ZFPM_STATS_IVL_SECS); + + /* + * Compute the total stats up to this instant. + */ + zfpm_stats_compose(&zfpm_g->cumulative_stats, &zfpm_g->stats, + &total_stats); + + ZFPM_SHOW_STAT(connect_calls); + ZFPM_SHOW_STAT(connect_no_sock); + ZFPM_SHOW_STAT(read_cb_calls); + ZFPM_SHOW_STAT(write_cb_calls); + ZFPM_SHOW_STAT(write_calls); + ZFPM_SHOW_STAT(partial_writes); + ZFPM_SHOW_STAT(max_writes_hit); + ZFPM_SHOW_STAT(t_write_yields); + ZFPM_SHOW_STAT(nop_deletes_skipped); + ZFPM_SHOW_STAT(route_adds); + ZFPM_SHOW_STAT(route_dels); + ZFPM_SHOW_STAT(updates_triggered); + ZFPM_SHOW_STAT(non_fpm_table_triggers); + ZFPM_SHOW_STAT(redundant_triggers); + ZFPM_SHOW_STAT(dests_del_after_update); + ZFPM_SHOW_STAT(t_conn_down_starts); + ZFPM_SHOW_STAT(t_conn_down_dests_processed); + ZFPM_SHOW_STAT(t_conn_down_yields); + ZFPM_SHOW_STAT(t_conn_down_finishes); + ZFPM_SHOW_STAT(t_conn_up_starts); + ZFPM_SHOW_STAT(t_conn_up_dests_processed); + ZFPM_SHOW_STAT(t_conn_up_yields); + ZFPM_SHOW_STAT(t_conn_up_aborts); + ZFPM_SHOW_STAT(t_conn_up_finishes); + + if (!zfpm_g->last_stats_clear_time) + return; + + elapsed = zfpm_get_elapsed_time(zfpm_g->last_stats_clear_time); + + vty_out(vty, "\nStats were cleared %lu seconds ago\n", + (unsigned long)elapsed); } /* * zfpm_clear_stats */ -static void -zfpm_clear_stats (struct vty *vty) +static void zfpm_clear_stats(struct vty *vty) { - if (!zfpm_is_enabled ()) - { - vty_out (vty, "The FPM module is not enabled...\n"); - return; - } + if (!zfpm_is_enabled()) { + vty_out(vty, "The FPM module is not enabled...\n"); + return; + } - zfpm_stats_reset (&zfpm_g->stats); - zfpm_stats_reset (&zfpm_g->last_ivl_stats); - zfpm_stats_reset (&zfpm_g->cumulative_stats); + zfpm_stats_reset(&zfpm_g->stats); + zfpm_stats_reset(&zfpm_g->last_ivl_stats); + zfpm_stats_reset(&zfpm_g->cumulative_stats); - zfpm_stop_stats_timer (); - zfpm_start_stats_timer (); + zfpm_stop_stats_timer(); + zfpm_start_stats_timer(); - zfpm_g->last_stats_clear_time = monotime(NULL); + zfpm_g->last_stats_clear_time = monotime(NULL); - vty_out (vty, "Cleared FPM stats\n"); + vty_out(vty, "Cleared FPM stats\n"); } /* @@ -1529,8 +1457,8 @@ DEFUN (show_zebra_fpm_stats, "Forwarding Path Manager information\n" "Statistics\n") { - zfpm_show_stats (vty); - return CMD_SUCCESS; + zfpm_show_stats(vty); + return CMD_SUCCESS; } /* @@ -1544,12 +1472,12 @@ DEFUN (clear_zebra_fpm_stats, "Clear Forwarding Path Manager information\n" "Statistics\n") { - zfpm_clear_stats (vty); - return CMD_SUCCESS; + zfpm_clear_stats(vty); + return CMD_SUCCESS; } /* - * update fpm connection information + * update fpm connection information */ DEFUN ( fpm_remote_ip, fpm_remote_ip_cmd, @@ -1559,22 +1487,22 @@ DEFUN ( fpm_remote_ip, "Enter ip ") { - in_addr_t fpm_server; - uint32_t port_no; + in_addr_t fpm_server; + uint32_t port_no; - fpm_server = inet_addr (argv[3]->arg); - if (fpm_server == INADDR_NONE) - return CMD_ERR_INCOMPLETE; + fpm_server = inet_addr(argv[3]->arg); + if (fpm_server == INADDR_NONE) + return CMD_ERR_INCOMPLETE; - port_no = atoi (argv[5]->arg); - if (port_no < TCP_MIN_PORT || port_no > TCP_MAX_PORT) - return CMD_ERR_INCOMPLETE; + port_no = atoi(argv[5]->arg); + if (port_no < TCP_MIN_PORT || port_no > TCP_MAX_PORT) + return CMD_ERR_INCOMPLETE; - zfpm_g->fpm_server = fpm_server; - zfpm_g->fpm_port = port_no; + zfpm_g->fpm_server = fpm_server; + zfpm_g->fpm_port = port_no; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN ( no_fpm_remote_ip, @@ -1585,106 +1513,93 @@ DEFUN ( no_fpm_remote_ip, "Remote fpm server ip A.B.C.D\n" "Enter ip ") { - if (zfpm_g->fpm_server != inet_addr (argv[4]->arg) || - zfpm_g->fpm_port != atoi (argv[6]->arg)) - return CMD_ERR_NO_MATCH; + if (zfpm_g->fpm_server != inet_addr(argv[4]->arg) + || zfpm_g->fpm_port != atoi(argv[6]->arg)) + return CMD_ERR_NO_MATCH; - zfpm_g->fpm_server = FPM_DEFAULT_IP; - zfpm_g->fpm_port = FPM_DEFAULT_PORT; + zfpm_g->fpm_server = FPM_DEFAULT_IP; + zfpm_g->fpm_port = FPM_DEFAULT_PORT; - return CMD_SUCCESS; + return CMD_SUCCESS; } /* * zfpm_init_message_format */ -static inline void -zfpm_init_message_format (const char *format) +static inline void zfpm_init_message_format(const char *format) { - int have_netlink, have_protobuf; + int have_netlink, have_protobuf; #ifdef HAVE_NETLINK - have_netlink = 1; + have_netlink = 1; #else - have_netlink = 0; + have_netlink = 0; #endif #ifdef HAVE_PROTOBUF - have_protobuf = 1; + have_protobuf = 1; #else - have_protobuf = 0; + have_protobuf = 0; #endif - zfpm_g->message_format = ZFPM_MSG_FORMAT_NONE; + zfpm_g->message_format = ZFPM_MSG_FORMAT_NONE; - if (!format) - { - if (have_netlink) - { - zfpm_g->message_format = ZFPM_MSG_FORMAT_NETLINK; - } - else if (have_protobuf) - { - zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF; + if (!format) { + if (have_netlink) { + zfpm_g->message_format = ZFPM_MSG_FORMAT_NETLINK; + } else if (have_protobuf) { + zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF; + } + return; } - return; - } - if (!strcmp ("netlink", format)) - { - if (!have_netlink) - { - zlog_err ("FPM netlink message format is not available"); - return; + if (!strcmp("netlink", format)) { + if (!have_netlink) { + zlog_err("FPM netlink message format is not available"); + return; + } + zfpm_g->message_format = ZFPM_MSG_FORMAT_NETLINK; + return; } - zfpm_g->message_format = ZFPM_MSG_FORMAT_NETLINK; - return; - } - if (!strcmp ("protobuf", format)) - { - if (!have_protobuf) - { - zlog_err ("FPM protobuf message format is not available"); - return; + if (!strcmp("protobuf", format)) { + if (!have_protobuf) { + zlog_err( + "FPM protobuf message format is not available"); + return; + } + zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF; + return; } - zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF; - return; - } - zlog_warn ("Unknown fpm format '%s'", format); + zlog_warn("Unknown fpm format '%s'", format); } /** - * fpm_remote_srv_write + * fpm_remote_srv_write * - * Module to write remote fpm connection + * Module to write remote fpm connection * * Returns ZERO on success. */ -static int fpm_remote_srv_write (struct vty *vty) +static int fpm_remote_srv_write(struct vty *vty) { - struct in_addr in; + struct in_addr in; - in.s_addr = zfpm_g->fpm_server; + in.s_addr = zfpm_g->fpm_server; - if (zfpm_g->fpm_server != FPM_DEFAULT_IP || - zfpm_g->fpm_port != FPM_DEFAULT_PORT) - vty_out (vty,"fpm connection ip %s port %d\n", inet_ntoa (in), - zfpm_g->fpm_port); + if (zfpm_g->fpm_server != FPM_DEFAULT_IP + || zfpm_g->fpm_port != FPM_DEFAULT_PORT) + vty_out(vty, "fpm connection ip %s port %d\n", inet_ntoa(in), + zfpm_g->fpm_port); - return 0; + return 0; } /* Zebra node */ -static struct cmd_node zebra_node = -{ - ZEBRA_NODE, - "", - 1 -}; +static struct cmd_node zebra_node = {ZEBRA_NODE, "", 1}; /** @@ -1698,66 +1613,61 @@ static struct cmd_node zebra_node = * * Returns TRUE on success. */ -static int -zfpm_init (struct thread_master *master) +static int zfpm_init(struct thread_master *master) { - int enable = 1; - uint16_t port = 0; - const char *format = THIS_MODULE->load_args; + int enable = 1; + uint16_t port = 0; + const char *format = THIS_MODULE->load_args; - memset (zfpm_g, 0, sizeof (*zfpm_g)); - zfpm_g->master = master; - TAILQ_INIT(&zfpm_g->dest_q); - zfpm_g->sock = -1; - zfpm_g->state = ZFPM_STATE_IDLE; + memset(zfpm_g, 0, sizeof(*zfpm_g)); + zfpm_g->master = master; + TAILQ_INIT(&zfpm_g->dest_q); + zfpm_g->sock = -1; + zfpm_g->state = ZFPM_STATE_IDLE; - zfpm_stats_init (&zfpm_g->stats); - zfpm_stats_init (&zfpm_g->last_ivl_stats); - zfpm_stats_init (&zfpm_g->cumulative_stats); + zfpm_stats_init(&zfpm_g->stats); + zfpm_stats_init(&zfpm_g->last_ivl_stats); + zfpm_stats_init(&zfpm_g->cumulative_stats); - install_node (&zebra_node, fpm_remote_srv_write); - install_element (ENABLE_NODE, &show_zebra_fpm_stats_cmd); - install_element (ENABLE_NODE, &clear_zebra_fpm_stats_cmd); - install_element (CONFIG_NODE, &fpm_remote_ip_cmd); - install_element (CONFIG_NODE, &no_fpm_remote_ip_cmd); + install_node(&zebra_node, fpm_remote_srv_write); + install_element(ENABLE_NODE, &show_zebra_fpm_stats_cmd); + install_element(ENABLE_NODE, &clear_zebra_fpm_stats_cmd); + install_element(CONFIG_NODE, &fpm_remote_ip_cmd); + install_element(CONFIG_NODE, &no_fpm_remote_ip_cmd); - zfpm_init_message_format(format); + zfpm_init_message_format(format); - /* - * Disable FPM interface if no suitable format is available. - */ - if (zfpm_g->message_format == ZFPM_MSG_FORMAT_NONE) - enable = 0; + /* + * Disable FPM interface if no suitable format is available. + */ + if (zfpm_g->message_format == ZFPM_MSG_FORMAT_NONE) + enable = 0; - zfpm_g->enabled = enable; + zfpm_g->enabled = enable; - if (!zfpm_g->fpm_server) - zfpm_g->fpm_server = FPM_DEFAULT_IP; + if (!zfpm_g->fpm_server) + zfpm_g->fpm_server = FPM_DEFAULT_IP; - if (!port) - port = FPM_DEFAULT_PORT; + if (!port) + port = FPM_DEFAULT_PORT; - zfpm_g->fpm_port = port; + zfpm_g->fpm_port = port; - zfpm_g->obuf = stream_new (ZFPM_OBUF_SIZE); - zfpm_g->ibuf = stream_new (ZFPM_IBUF_SIZE); + zfpm_g->obuf = stream_new(ZFPM_OBUF_SIZE); + zfpm_g->ibuf = stream_new(ZFPM_IBUF_SIZE); - zfpm_start_stats_timer (); - zfpm_start_connect_timer ("initialized"); - return 0; + zfpm_start_stats_timer(); + zfpm_start_connect_timer("initialized"); + return 0; } -static int -zebra_fpm_module_init (void) +static int zebra_fpm_module_init(void) { - hook_register(rib_update, zfpm_trigger_update); - hook_register(frr_late_init, zfpm_init); - return 0; + hook_register(rib_update, zfpm_trigger_update); + hook_register(frr_late_init, zfpm_init); + return 0; } -FRR_MODULE_SETUP( - .name = "zebra_fpm", - .version = FRR_VERSION, - .description = "zebra FPM (Forwarding Plane Manager) module", - .init = zebra_fpm_module_init, -) +FRR_MODULE_SETUP(.name = "zebra_fpm", .version = FRR_VERSION, + .description = "zebra FPM (Forwarding Plane Manager) module", + .init = zebra_fpm_module_init, ) diff --git a/zebra/zebra_fpm_dt.c b/zebra/zebra_fpm_dt.c index 916640928..48db246bc 100644 --- a/zebra/zebra_fpm_dt.c +++ b/zebra/zebra_fpm_dt.c @@ -57,85 +57,83 @@ /* * Externs. */ -extern int zfpm_dt_benchmark_netlink_encode (int argc, const char **argv); -extern int zfpm_dt_benchmark_protobuf_encode (int argc, const char **argv); -extern int zfpm_dt_benchmark_protobuf_decode (int argc, const char **argv); +extern int zfpm_dt_benchmark_netlink_encode(int argc, const char **argv); +extern int zfpm_dt_benchmark_protobuf_encode(int argc, const char **argv); +extern int zfpm_dt_benchmark_protobuf_decode(int argc, const char **argv); /* * zfpm_dt_find_route * * Selects a suitable rib destination for fpm interface tests. */ -static int -zfpm_dt_find_route (rib_dest_t **dest_p, struct route_entry **re_p) +static int zfpm_dt_find_route(rib_dest_t **dest_p, struct route_entry **re_p) { - struct route_node *rnode; - route_table_iter_t iter; - struct route_table *table; - rib_dest_t *dest; - struct route_entry *re; - int ret; - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); - if (!table) - return 0; - - route_table_iter_init(&iter, table); - while ((rnode = route_table_iter_next(&iter))) - { - dest = rib_dest_from_rnode (rnode); - - if (!dest) - continue; - - re = zfpm_route_for_update(dest); - if (!re) - continue; - - if (re->nexthop_active_num <= 0) - continue; - - *dest_p = dest; - *re_p = re; - ret = 1; - goto done; - } - - ret = 0; - - done: - route_table_iter_cleanup(&iter); - return ret; + struct route_node *rnode; + route_table_iter_t iter; + struct route_table *table; + rib_dest_t *dest; + struct route_entry *re; + int ret; + + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (!table) + return 0; + + route_table_iter_init(&iter, table); + while ((rnode = route_table_iter_next(&iter))) { + dest = rib_dest_from_rnode(rnode); + + if (!dest) + continue; + + re = zfpm_route_for_update(dest); + if (!re) + continue; + + if (re->nexthop_active_num <= 0) + continue; + + *dest_p = dest; + *re_p = re; + ret = 1; + goto done; + } + + ret = 0; + +done: + route_table_iter_cleanup(&iter); + return ret; } #ifdef HAVE_NETLINK /* * zfpm_dt_benchmark_netlink_encode */ -int -zfpm_dt_benchmark_netlink_encode (int argc, const char **argv) +int zfpm_dt_benchmark_netlink_encode(int argc, const char **argv) { - int times, i, len; - rib_dest_t *dest; - struct route_entry *re; - char buf[4096]; - - times = 100000; - if (argc > 0) { - times = atoi(argv[0]); - } - - if (!zfpm_dt_find_route(&dest, &re)) { - return 1; - } - - for (i = 0; i < times; i++) { - len = zfpm_netlink_encode_route(RTM_NEWROUTE, dest, re, buf, sizeof(buf)); - if (len <= 0) { - return 2; - } - } - return 0; + int times, i, len; + rib_dest_t *dest; + struct route_entry *re; + char buf[4096]; + + times = 100000; + if (argc > 0) { + times = atoi(argv[0]); + } + + if (!zfpm_dt_find_route(&dest, &re)) { + return 1; + } + + for (i = 0; i < times; i++) { + len = zfpm_netlink_encode_route(RTM_NEWROUTE, dest, re, buf, + sizeof(buf)); + if (len <= 0) { + return 2; + } + } + return 0; } #endif /* HAVE_NETLINK */ @@ -145,134 +143,129 @@ zfpm_dt_benchmark_netlink_encode (int argc, const char **argv) /* * zfpm_dt_benchmark_protobuf_encode */ -int -zfpm_dt_benchmark_protobuf_encode (int argc, const char **argv) +int zfpm_dt_benchmark_protobuf_encode(int argc, const char **argv) { - int times, i, len; - rib_dest_t *dest; - struct route_entry *re; - uint8_t buf[4096]; - - times = 100000; - if (argc > 0) { - times = atoi(argv[0]); - } - - if (!zfpm_dt_find_route(&dest, &re)) { - return 1; - } - - for (i = 0; i < times; i++) { - len = zfpm_protobuf_encode_route(dest, re, buf, sizeof(buf)); - if (len <= 0) { - return 2; - } - } - return 0; + int times, i, len; + rib_dest_t *dest; + struct route_entry *re; + uint8_t buf[4096]; + + times = 100000; + if (argc > 0) { + times = atoi(argv[0]); + } + + if (!zfpm_dt_find_route(&dest, &re)) { + return 1; + } + + for (i = 0; i < times; i++) { + len = zfpm_protobuf_encode_route(dest, re, buf, sizeof(buf)); + if (len <= 0) { + return 2; + } + } + return 0; } /* * zfpm_dt_log_fpm_message */ -static void -zfpm_dt_log_fpm_message (Fpm__Message *msg) +static void zfpm_dt_log_fpm_message(Fpm__Message *msg) { - Fpm__AddRoute *add_route; - Fpm__Nexthop *nexthop; - struct prefix prefix; - u_char family, nh_family; - uint if_index; - char *if_name; - size_t i; - char buf[INET6_ADDRSTRLEN]; - union g_addr nh_addr; - - if (msg->type != FPM__MESSAGE__TYPE__ADD_ROUTE) - return; - - zfpm_debug ("Add route message"); - add_route = msg->add_route; - - if (!qpb_address_family_get (add_route->address_family, &family)) - return; - - if (!qpb_l3_prefix_get (add_route->key->prefix, family, &prefix)) - return; - - zfpm_debug ("Vrf id: %d, Prefix: %s/%d, Metric: %d", add_route->vrf_id, - inet_ntop (family, &prefix.u.prefix, buf, sizeof (buf)), - prefix.prefixlen, add_route->metric); - - /* - * Go over nexthops. - */ - for (i = 0; i < add_route->n_nexthops; i++) - { - nexthop = add_route->nexthops[i]; - if (!qpb_if_identifier_get (nexthop->if_id, &if_index, &if_name)) - continue; - - if (nexthop->address) - qpb_l3_address_get (nexthop->address, &nh_family, &nh_addr); - - zfpm_debug ("Nexthop - if_index: %d (%s), gateway: %s, ", if_index, - if_name ? if_name : "name not specified", - nexthop->address ? inet_ntoa (nh_addr.ipv4) : "None"); - } + Fpm__AddRoute *add_route; + Fpm__Nexthop *nexthop; + struct prefix prefix; + u_char family, nh_family; + uint if_index; + char *if_name; + size_t i; + char buf[INET6_ADDRSTRLEN]; + union g_addr nh_addr; + + if (msg->type != FPM__MESSAGE__TYPE__ADD_ROUTE) + return; + + zfpm_debug("Add route message"); + add_route = msg->add_route; + + if (!qpb_address_family_get(add_route->address_family, &family)) + return; + + if (!qpb_l3_prefix_get(add_route->key->prefix, family, &prefix)) + return; + + zfpm_debug("Vrf id: %d, Prefix: %s/%d, Metric: %d", add_route->vrf_id, + inet_ntop(family, &prefix.u.prefix, buf, sizeof(buf)), + prefix.prefixlen, add_route->metric); + + /* + * Go over nexthops. + */ + for (i = 0; i < add_route->n_nexthops; i++) { + nexthop = add_route->nexthops[i]; + if (!qpb_if_identifier_get(nexthop->if_id, &if_index, &if_name)) + continue; + + if (nexthop->address) + qpb_l3_address_get(nexthop->address, &nh_family, + &nh_addr); + + zfpm_debug("Nexthop - if_index: %d (%s), gateway: %s, ", + if_index, if_name ? if_name : "name not specified", + nexthop->address ? inet_ntoa(nh_addr.ipv4) : "None"); + } } /* * zfpm_dt_benchmark_protobuf_decode */ -int -zfpm_dt_benchmark_protobuf_decode (int argc, const char **argv) +int zfpm_dt_benchmark_protobuf_decode(int argc, const char **argv) { - int times, i, len; - rib_dest_t *dest; - struct route_entry *re; - uint8_t msg_buf[4096]; - QPB_DECLARE_STACK_ALLOCATOR (allocator, 8192); - Fpm__Message *fpm_msg; - - QPB_INIT_STACK_ALLOCATOR (allocator); - - times = 100000; - if (argc > 0) - times = atoi(argv[0]); - - if (!zfpm_dt_find_route (&dest, &re)) - return 1; - - /* - * Encode the route into the message buffer once only. - */ - len = zfpm_protobuf_encode_route (dest, re, msg_buf, sizeof (msg_buf)); - if (len <= 0) - return 2; - - // Decode once, and display the decoded message - fpm_msg = fpm__message__unpack(&allocator, len, msg_buf); - - if (fpm_msg) - { - zfpm_dt_log_fpm_message(fpm_msg); - QPB_RESET_STACK_ALLOCATOR (allocator); - } - - /* - * Decode encoded message the specified number of times. - */ - for (i = 0; i < times; i++) - { - fpm_msg = fpm__message__unpack (&allocator, len, msg_buf); - - if (!fpm_msg) - return 3; - - // fpm__message__free_unpacked(msg, NULL); - QPB_RESET_STACK_ALLOCATOR (allocator); - } - return 0; + int times, i, len; + rib_dest_t *dest; + struct route_entry *re; + uint8_t msg_buf[4096]; + QPB_DECLARE_STACK_ALLOCATOR(allocator, 8192); + Fpm__Message *fpm_msg; + + QPB_INIT_STACK_ALLOCATOR(allocator); + + times = 100000; + if (argc > 0) + times = atoi(argv[0]); + + if (!zfpm_dt_find_route(&dest, &re)) + return 1; + + /* + * Encode the route into the message buffer once only. + */ + len = zfpm_protobuf_encode_route(dest, re, msg_buf, sizeof(msg_buf)); + if (len <= 0) + return 2; + + // Decode once, and display the decoded message + fpm_msg = fpm__message__unpack(&allocator, len, msg_buf); + + if (fpm_msg) { + zfpm_dt_log_fpm_message(fpm_msg); + QPB_RESET_STACK_ALLOCATOR(allocator); + } + + /* + * Decode encoded message the specified number of times. + */ + for (i = 0; i < times; i++) { + fpm_msg = fpm__message__unpack(&allocator, len, msg_buf); + + if (!fpm_msg) + return 3; + + // fpm__message__free_unpacked(msg, NULL); + QPB_RESET_STACK_ALLOCATOR(allocator); + } + return 0; } #endif /* HAVE_PROTOBUF */ diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index d935826db..862049cb8 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -43,25 +43,23 @@ * * Returns string representation of an address of the given AF. */ -static inline const char * -addr_to_a (u_char af, void *addr) +static inline const char *addr_to_a(u_char af, void *addr) { - if (!addr) - return "<No address>"; - - switch (af) - { - - case AF_INET: - return inet_ntoa (*((struct in_addr *) addr)); - break; - case AF_INET6: - return inet6_ntoa (*((struct in6_addr *) addr)); - break; - default: - return "<Addr in unknown AF>"; - break; - } + if (!addr) + return "<No address>"; + + switch (af) { + + case AF_INET: + return inet_ntoa(*((struct in_addr *)addr)); + break; + case AF_INET6: + return inet6_ntoa(*((struct in6_addr *)addr)); + break; + default: + return "<Addr in unknown AF>"; + break; + } } /* @@ -70,13 +68,12 @@ addr_to_a (u_char af, void *addr) * Convience wrapper that returns a human-readable string for the * address in a prefix. */ -static const char * -prefix_addr_to_a (struct prefix *prefix) +static const char *prefix_addr_to_a(struct prefix *prefix) { - if (!prefix) - return "<No address>"; + if (!prefix) + return "<No address>"; - return addr_to_a (prefix->family, &prefix->u.prefix); + return addr_to_a(prefix->family, &prefix->u.prefix); } /* @@ -84,22 +81,20 @@ prefix_addr_to_a (struct prefix *prefix) * * The size of an address in a given address family. */ -static size_t -af_addr_size (u_char af) +static size_t af_addr_size(u_char af) { - switch (af) - { - - case AF_INET: - return 4; - break; - case AF_INET6: - return 16; - break; - default: - assert(0); - return 16; - } + switch (af) { + + case AF_INET: + return 4; + break; + case AF_INET6: + return 16; + break; + default: + assert(0); + return 16; + } } /* @@ -109,17 +104,16 @@ af_addr_size (u_char af) * structures are transient and may contain pointers into rib * data structures for convenience. */ -typedef struct netlink_nh_info_t_ -{ - uint32_t if_index; - union g_addr *gateway; - - /* - * Information from the struct nexthop from which this nh was - * derived. For debug purposes only. - */ - int recursive; - enum nexthop_types_t type; +typedef struct netlink_nh_info_t_ { + uint32_t if_index; + union g_addr *gateway; + + /* + * Information from the struct nexthop from which this nh was + * derived. For debug purposes only. + */ + int recursive; + enum nexthop_types_t type; } netlink_nh_info_t; /* @@ -127,22 +121,21 @@ typedef struct netlink_nh_info_t_ * * A structure for holding information for a netlink route message. */ -typedef struct netlink_route_info_t_ -{ - uint16_t nlmsg_type; - u_char rtm_type; - uint32_t rtm_table; - u_char rtm_protocol; - u_char af; - struct prefix *prefix; - uint32_t *metric; - unsigned int num_nhs; - - /* - * Nexthop structures - */ - netlink_nh_info_t nhs[MULTIPATH_NUM]; - union g_addr *pref_src; +typedef struct netlink_route_info_t_ { + uint16_t nlmsg_type; + u_char rtm_type; + uint32_t rtm_table; + u_char rtm_protocol; + u_char af; + struct prefix *prefix; + uint32_t *metric; + unsigned int num_nhs; + + /* + * Nexthop structures + */ + netlink_nh_info_t nhs[MULTIPATH_NUM]; + union g_addr *pref_src; } netlink_route_info_t; /* @@ -153,72 +146,67 @@ typedef struct netlink_route_info_t_ * * Returns TRUE if a nexthop was added, FALSE otherwise. */ -static int -netlink_route_info_add_nh (netlink_route_info_t *ri, struct nexthop *nexthop) +static int netlink_route_info_add_nh(netlink_route_info_t *ri, + struct nexthop *nexthop) { - netlink_nh_info_t nhi; - union g_addr *src; - - memset (&nhi, 0, sizeof (nhi)); - src = NULL; - - if (ri->num_nhs >= (int) ZEBRA_NUM_OF (ri->nhs)) - return 0; - - nhi.recursive = nexthop->rparent ? 1 : 0; - nhi.type = nexthop->type; - nhi.if_index = nexthop->ifindex; - - if (nexthop->type == NEXTHOP_TYPE_IPV4 - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - nhi.gateway = &nexthop->gate; - if (nexthop->src.ipv4.s_addr) - src = &nexthop->src; - } - - if (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - nhi.gateway = &nexthop->gate; - } - - if (nexthop->type == NEXTHOP_TYPE_IFINDEX) - { - if (nexthop->src.ipv4.s_addr) - src = &nexthop->src; - } - - if (!nhi.gateway && nhi.if_index == 0) - return 0; - - /* - * We have a valid nhi. Copy the structure over to the route_info. - */ - ri->nhs[ri->num_nhs] = nhi; - ri->num_nhs++; - - if (src && !ri->pref_src) - ri->pref_src = src; - - return 1; + netlink_nh_info_t nhi; + union g_addr *src; + + memset(&nhi, 0, sizeof(nhi)); + src = NULL; + + if (ri->num_nhs >= (int)ZEBRA_NUM_OF(ri->nhs)) + return 0; + + nhi.recursive = nexthop->rparent ? 1 : 0; + nhi.type = nexthop->type; + nhi.if_index = nexthop->ifindex; + + if (nexthop->type == NEXTHOP_TYPE_IPV4 + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + nhi.gateway = &nexthop->gate; + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + } + + if (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + nhi.gateway = &nexthop->gate; + } + + if (nexthop->type == NEXTHOP_TYPE_IFINDEX) { + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + } + + if (!nhi.gateway && nhi.if_index == 0) + return 0; + + /* + * We have a valid nhi. Copy the structure over to the route_info. + */ + ri->nhs[ri->num_nhs] = nhi; + ri->num_nhs++; + + if (src && !ri->pref_src) + ri->pref_src = src; + + return 1; } /* * netlink_proto_from_route_type */ -static u_char -netlink_proto_from_route_type (int type) +static u_char netlink_proto_from_route_type(int type) { - switch (type) - { - case ZEBRA_ROUTE_KERNEL: - case ZEBRA_ROUTE_CONNECT: - return RTPROT_KERNEL; - - default: - return RTPROT_ZEBRA; - } + switch (type) { + case ZEBRA_ROUTE_KERNEL: + case ZEBRA_ROUTE_CONNECT: + return RTPROT_KERNEL; + + default: + return RTPROT_ZEBRA; + } } /* @@ -228,87 +216,81 @@ netlink_proto_from_route_type (int type) * * Returns TRUE on success and FALSE on failure. */ -static int -netlink_route_info_fill (netlink_route_info_t *ri, int cmd, - rib_dest_t *dest, struct route_entry *re) +static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd, + rib_dest_t *dest, struct route_entry *re) { - struct nexthop *nexthop; - int discard; - - memset (ri, 0, sizeof (*ri)); - - ri->prefix = rib_dest_prefix (dest); - ri->af = rib_dest_af (dest); - - ri->nlmsg_type = cmd; - ri->rtm_table = zvrf_id (rib_dest_vrf (dest)); - ri->rtm_protocol = RTPROT_UNSPEC; - - /* - * An RTM_DELROUTE need not be accompanied by any nexthops, - * particularly in our communication with the FPM. - */ - if (cmd == RTM_DELROUTE && !re) - return 1; - - if (!re) - { - zfpm_debug ("%s: Expected non-NULL re pointer", __PRETTY_FUNCTION__); - return 0; - } - - ri->rtm_protocol = netlink_proto_from_route_type (re->type); - - if ((re->flags & ZEBRA_FLAG_BLACKHOLE) || (re->flags & ZEBRA_FLAG_REJECT)) - discard = 1; - else - discard = 0; - - if (cmd == RTM_NEWROUTE) - { - if (discard) - { - if (re->flags & ZEBRA_FLAG_BLACKHOLE) - ri->rtm_type = RTN_BLACKHOLE; - else if (re->flags & ZEBRA_FLAG_REJECT) - ri->rtm_type = RTN_UNREACHABLE; - else - assert (0); - } - else - ri->rtm_type = RTN_UNICAST; - } - - ri->metric = &re->metric; - - if (discard) - return 1; - - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (ri->num_nhs >= multipath_num) - break; - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - - if ((cmd == RTM_NEWROUTE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - || (cmd == RTM_DELROUTE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))) - { - netlink_route_info_add_nh (ri, nexthop); - } - } - - /* If there is no useful nexthop then return. */ - if (ri->num_nhs == 0) - { - zfpm_debug ("netlink_encode_route(): No useful nexthop."); - return 0; - } - - return 1; + struct nexthop *nexthop; + int discard; + + memset(ri, 0, sizeof(*ri)); + + ri->prefix = rib_dest_prefix(dest); + ri->af = rib_dest_af(dest); + + ri->nlmsg_type = cmd; + ri->rtm_table = zvrf_id(rib_dest_vrf(dest)); + ri->rtm_protocol = RTPROT_UNSPEC; + + /* + * An RTM_DELROUTE need not be accompanied by any nexthops, + * particularly in our communication with the FPM. + */ + if (cmd == RTM_DELROUTE && !re) + return 1; + + if (!re) { + zfpm_debug("%s: Expected non-NULL re pointer", + __PRETTY_FUNCTION__); + return 0; + } + + ri->rtm_protocol = netlink_proto_from_route_type(re->type); + + if ((re->flags & ZEBRA_FLAG_BLACKHOLE) + || (re->flags & ZEBRA_FLAG_REJECT)) + discard = 1; + else + discard = 0; + + if (cmd == RTM_NEWROUTE) { + if (discard) { + if (re->flags & ZEBRA_FLAG_BLACKHOLE) + ri->rtm_type = RTN_BLACKHOLE; + else if (re->flags & ZEBRA_FLAG_REJECT) + ri->rtm_type = RTN_UNREACHABLE; + else + assert(0); + } else + ri->rtm_type = RTN_UNICAST; + } + + ri->metric = &re->metric; + + if (discard) + return 1; + + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (ri->num_nhs >= multipath_num) + break; + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + + if ((cmd == RTM_NEWROUTE + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + || (cmd == RTM_DELROUTE + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))) { + netlink_route_info_add_nh(ri, nexthop); + } + } + + /* If there is no useful nexthop then return. */ + if (ri->num_nhs == 0) { + zfpm_debug("netlink_encode_route(): No useful nexthop."); + return 0; + } + + return 1; } /* @@ -317,122 +299,114 @@ netlink_route_info_fill (netlink_route_info_t *ri, int cmd, * Returns the number of bytes written to the buffer. 0 or a negative * value indicates an error. */ -static int -netlink_route_info_encode (netlink_route_info_t *ri, char *in_buf, - size_t in_buf_len) +static int netlink_route_info_encode(netlink_route_info_t *ri, char *in_buf, + size_t in_buf_len) { - size_t bytelen; - unsigned int nexthop_num = 0; - size_t buf_offset; - netlink_nh_info_t *nhi; + size_t bytelen; + unsigned int nexthop_num = 0; + size_t buf_offset; + netlink_nh_info_t *nhi; - struct - { - struct nlmsghdr n; - struct rtmsg r; - char buf[1]; - } *req; + struct { + struct nlmsghdr n; + struct rtmsg r; + char buf[1]; + } * req; - req = (void *) in_buf; + req = (void *)in_buf; - buf_offset = ((char *) req->buf) - ((char *) req); + buf_offset = ((char *)req->buf) - ((char *)req); - if (in_buf_len < buf_offset) { - assert(0); - return 0; - } - - memset (req, 0, buf_offset); - - bytelen = af_addr_size (ri->af); - - req->n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); - req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; - req->n.nlmsg_type = ri->nlmsg_type; - req->r.rtm_family = ri->af; - req->r.rtm_table = ri->rtm_table; - req->r.rtm_dst_len = ri->prefix->prefixlen; - req->r.rtm_protocol = ri->rtm_protocol; - req->r.rtm_scope = RT_SCOPE_UNIVERSE; - - addattr_l (&req->n, in_buf_len, RTA_DST, &ri->prefix->u.prefix, bytelen); - - req->r.rtm_type = ri->rtm_type; - - /* Metric. */ - if (ri->metric) - addattr32 (&req->n, in_buf_len, RTA_PRIORITY, *ri->metric); + if (in_buf_len < buf_offset) { + assert(0); + return 0; + } - if (ri->num_nhs == 0) - goto done; + memset(req, 0, buf_offset); - if (ri->num_nhs == 1) - { - nhi = &ri->nhs[0]; + bytelen = af_addr_size(ri->af); - if (nhi->gateway) - { - addattr_l (&req->n, in_buf_len, RTA_GATEWAY, nhi->gateway, - bytelen); - } + req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; + req->n.nlmsg_type = ri->nlmsg_type; + req->r.rtm_family = ri->af; + req->r.rtm_table = ri->rtm_table; + req->r.rtm_dst_len = ri->prefix->prefixlen; + req->r.rtm_protocol = ri->rtm_protocol; + req->r.rtm_scope = RT_SCOPE_UNIVERSE; - if (nhi->if_index) - { - addattr32 (&req->n, in_buf_len, RTA_OIF, nhi->if_index); - } + addattr_l(&req->n, in_buf_len, RTA_DST, &ri->prefix->u.prefix, bytelen); - goto done; + req->r.rtm_type = ri->rtm_type; - } + /* Metric. */ + if (ri->metric) + addattr32(&req->n, in_buf_len, RTA_PRIORITY, *ri->metric); - /* - * Multipath case. - */ - char buf[NL_PKT_BUF_SIZE]; - struct rtattr *rta = (void *) buf; - struct rtnexthop *rtnh; + if (ri->num_nhs == 0) + goto done; - rta->rta_type = RTA_MULTIPATH; - rta->rta_len = RTA_LENGTH (0); - rtnh = RTA_DATA (rta); + if (ri->num_nhs == 1) { + nhi = &ri->nhs[0]; - for (nexthop_num = 0; nexthop_num < ri->num_nhs; nexthop_num++) - { - nhi = &ri->nhs[nexthop_num]; + if (nhi->gateway) { + addattr_l(&req->n, in_buf_len, RTA_GATEWAY, + nhi->gateway, bytelen); + } - rtnh->rtnh_len = sizeof (*rtnh); - rtnh->rtnh_flags = 0; - rtnh->rtnh_hops = 0; - rtnh->rtnh_ifindex = 0; - rta->rta_len += rtnh->rtnh_len; + if (nhi->if_index) { + addattr32(&req->n, in_buf_len, RTA_OIF, nhi->if_index); + } - if (nhi->gateway) - { - rta_addattr_l (rta, sizeof (buf), RTA_GATEWAY, nhi->gateway, bytelen); - rtnh->rtnh_len += sizeof (struct rtattr) + bytelen; + goto done; } - if (nhi->if_index) - { - rtnh->rtnh_ifindex = nhi->if_index; + /* + * Multipath case. + */ + char buf[NL_PKT_BUF_SIZE]; + struct rtattr *rta = (void *)buf; + struct rtnexthop *rtnh; + + rta->rta_type = RTA_MULTIPATH; + rta->rta_len = RTA_LENGTH(0); + rtnh = RTA_DATA(rta); + + for (nexthop_num = 0; nexthop_num < ri->num_nhs; nexthop_num++) { + nhi = &ri->nhs[nexthop_num]; + + rtnh->rtnh_len = sizeof(*rtnh); + rtnh->rtnh_flags = 0; + rtnh->rtnh_hops = 0; + rtnh->rtnh_ifindex = 0; + rta->rta_len += rtnh->rtnh_len; + + if (nhi->gateway) { + rta_addattr_l(rta, sizeof(buf), RTA_GATEWAY, + nhi->gateway, bytelen); + rtnh->rtnh_len += sizeof(struct rtattr) + bytelen; + } + + if (nhi->if_index) { + rtnh->rtnh_ifindex = nhi->if_index; + } + + rtnh = RTNH_NEXT(rtnh); } - rtnh = RTNH_NEXT (rtnh); - } - - assert (rta->rta_len > RTA_LENGTH (0)); - addattr_l (&req->n, in_buf_len, RTA_MULTIPATH, RTA_DATA (rta), - RTA_PAYLOAD (rta)); + assert(rta->rta_len > RTA_LENGTH(0)); + addattr_l(&req->n, in_buf_len, RTA_MULTIPATH, RTA_DATA(rta), + RTA_PAYLOAD(rta)); done: - if (ri->pref_src) - { - addattr_l (&req->n, in_buf_len, RTA_PREFSRC, &ri->pref_src, bytelen); - } + if (ri->pref_src) { + addattr_l(&req->n, in_buf_len, RTA_PREFSRC, &ri->pref_src, + bytelen); + } - assert (req->n.nlmsg_len < in_buf_len); - return req->n.nlmsg_len; + assert(req->n.nlmsg_len < in_buf_len); + return req->n.nlmsg_len; } /* @@ -440,26 +414,24 @@ done: * * Helper function to log the information in a route_info structure. */ -static void -zfpm_log_route_info (netlink_route_info_t *ri, const char *label) +static void zfpm_log_route_info(netlink_route_info_t *ri, const char *label) { - netlink_nh_info_t *nhi; - unsigned int i; - - zfpm_debug ("%s : %s %s/%d, Proto: %s, Metric: %u", label, - nl_msg_type_to_str (ri->nlmsg_type), - prefix_addr_to_a (ri->prefix), ri->prefix->prefixlen, - nl_rtproto_to_str (ri->rtm_protocol), - ri->metric ? *ri->metric : 0); - - for (i = 0; i < ri->num_nhs; i++) - { - nhi = &ri->nhs[i]; - zfpm_debug(" Intf: %u, Gateway: %s, Recursive: %s, Type: %s", - nhi->if_index, addr_to_a (ri->af, nhi->gateway), - nhi->recursive ? "yes" : "no", - nexthop_type_to_str (nhi->type)); - } + netlink_nh_info_t *nhi; + unsigned int i; + + zfpm_debug("%s : %s %s/%d, Proto: %s, Metric: %u", label, + nl_msg_type_to_str(ri->nlmsg_type), + prefix_addr_to_a(ri->prefix), ri->prefix->prefixlen, + nl_rtproto_to_str(ri->rtm_protocol), + ri->metric ? *ri->metric : 0); + + for (i = 0; i < ri->num_nhs; i++) { + nhi = &ri->nhs[i]; + zfpm_debug(" Intf: %u, Gateway: %s, Recursive: %s, Type: %s", + nhi->if_index, addr_to_a(ri->af, nhi->gateway), + nhi->recursive ? "yes" : "no", + nexthop_type_to_str(nhi->type)); + } } /* @@ -471,18 +443,17 @@ zfpm_log_route_info (netlink_route_info_t *ri, const char *label) * Returns the number of bytes written to the buffer. 0 or a negative * value indicates an error. */ -int -zfpm_netlink_encode_route (int cmd, rib_dest_t *dest, struct route_entry *re, - char *in_buf, size_t in_buf_len) +int zfpm_netlink_encode_route(int cmd, rib_dest_t *dest, struct route_entry *re, + char *in_buf, size_t in_buf_len) { - netlink_route_info_t ri_space, *ri; + netlink_route_info_t ri_space, *ri; - ri = &ri_space; + ri = &ri_space; - if (!netlink_route_info_fill (ri, cmd, dest, re)) - return 0; + if (!netlink_route_info_fill(ri, cmd, dest, re)) + return 0; - zfpm_log_route_info (ri, __FUNCTION__); + zfpm_log_route_info(ri, __FUNCTION__); - return netlink_route_info_encode (ri, in_buf, in_buf_len); + return netlink_route_info_encode(ri, in_buf, in_buf_len); } diff --git a/zebra/zebra_fpm_private.h b/zebra/zebra_fpm_private.h index 441a22a79..969ab6cfe 100644 --- a/zebra/zebra_fpm_private.h +++ b/zebra/zebra_fpm_private.h @@ -28,33 +28,37 @@ #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L -#define zfpm_debug(...) \ - do { \ - if (IS_ZEBRA_DEBUG_FPM) zlog_debug("FPM: " __VA_ARGS__); \ - } while(0) +#define zfpm_debug(...) \ + do { \ + if (IS_ZEBRA_DEBUG_FPM) \ + zlog_debug("FPM: " __VA_ARGS__); \ + } while (0) #elif defined __GNUC__ -#define zfpm_debug(_args...) \ - do { \ - if (IS_ZEBRA_DEBUG_FPM) zlog_debug("FPM: " _args); \ - } while(0) +#define zfpm_debug(_args...) \ + do { \ + if (IS_ZEBRA_DEBUG_FPM) \ + zlog_debug("FPM: " _args); \ + } while (0) #else -static inline void zfpm_debug(const char *format, ...) { return; } +static inline void zfpm_debug(const char *format, ...) +{ + return; +} #endif /* * Externs */ -extern int -zfpm_netlink_encode_route (int cmd, rib_dest_t *dest, struct route_entry *re, - char *in_buf, size_t in_buf_len); +extern int zfpm_netlink_encode_route(int cmd, rib_dest_t *dest, + struct route_entry *re, char *in_buf, + size_t in_buf_len); -extern int -zfpm_protobuf_encode_route (rib_dest_t *dest, struct route_entry *re, - uint8_t *in_buf, size_t in_buf_len); +extern int zfpm_protobuf_encode_route(rib_dest_t *dest, struct route_entry *re, + uint8_t *in_buf, size_t in_buf_len); -extern struct route_entry *zfpm_route_for_update (rib_dest_t *dest); +extern struct route_entry *zfpm_route_for_update(rib_dest_t *dest); #endif /* _ZEBRA_FPM_PRIVATE_H */ diff --git a/zebra/zebra_fpm_protobuf.c b/zebra/zebra_fpm_protobuf.c index 1e8af19ea..450ad5b0b 100644 --- a/zebra/zebra_fpm_protobuf.c +++ b/zebra/zebra_fpm_protobuf.c @@ -39,241 +39,237 @@ /* * create_delete_route_message */ -static Fpm__DeleteRoute * -create_delete_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, - struct route_entry *re) +static Fpm__DeleteRoute *create_delete_route_message(qpb_allocator_t *allocator, + rib_dest_t *dest, + struct route_entry *re) { - Fpm__DeleteRoute *msg; - - msg = QPB_ALLOC(allocator, typeof(*msg)); - if (!msg) { - assert(0); - return NULL; - } - - fpm__delete_route__init(msg); - msg->vrf_id = zvrf_id(rib_dest_vrf(dest)); - - qpb_address_family_set(&msg->address_family, rib_dest_af(dest)); - - /* - * XXX Hardcode subaddress family for now. - */ - msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST; - msg->key = fpm_route_key_create (allocator, rib_dest_prefix(dest)); - if (!msg->key) { - assert(0); - return NULL; - } - - return msg; + Fpm__DeleteRoute *msg; + + msg = QPB_ALLOC(allocator, typeof(*msg)); + if (!msg) { + assert(0); + return NULL; + } + + fpm__delete_route__init(msg); + msg->vrf_id = zvrf_id(rib_dest_vrf(dest)); + + qpb_address_family_set(&msg->address_family, rib_dest_af(dest)); + + /* + * XXX Hardcode subaddress family for now. + */ + msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST; + msg->key = fpm_route_key_create(allocator, rib_dest_prefix(dest)); + if (!msg->key) { + assert(0); + return NULL; + } + + return msg; } /* * add_nexthop */ -static inline int -add_nexthop (qpb_allocator_t *allocator, Fpm__AddRoute *msg, rib_dest_t *dest, - struct nexthop *nexthop) +static inline int add_nexthop(qpb_allocator_t *allocator, Fpm__AddRoute *msg, + rib_dest_t *dest, struct nexthop *nexthop) { - uint32_t if_index; - union g_addr *gateway, *src; - - gateway = src = NULL; - - if_index = nexthop->ifindex; - - if (nexthop->type == NEXTHOP_TYPE_IPV4 - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - gateway = &nexthop->gate; - if (nexthop->src.ipv4.s_addr) - src = &nexthop->src; - } - - if (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - gateway = &nexthop->gate; - } - - if (nexthop->type == NEXTHOP_TYPE_IFINDEX) - { - if (nexthop->src.ipv4.s_addr) - src = &nexthop->src; - } - - if (!gateway && if_index == 0) - return 0; - - /* - * We have a valid nexthop. - */ - { - Fpm__Nexthop *pb_nh; - pb_nh = QPB_ALLOC(allocator, typeof(*pb_nh)); - if (!pb_nh) { - assert(0); - return 0; - } - - fpm__nexthop__init(pb_nh); - - if (if_index != 0) { - pb_nh->if_id = qpb_if_identifier_create (allocator, if_index); - } - - if (gateway) { - pb_nh->address = qpb_l3_address_create (allocator, gateway, - rib_dest_af(dest)); - } - - msg->nexthops[msg->n_nexthops++] = pb_nh; - } - - // TODO: Use src. - - return 1; + uint32_t if_index; + union g_addr *gateway, *src; + + gateway = src = NULL; + + if_index = nexthop->ifindex; + + if (nexthop->type == NEXTHOP_TYPE_IPV4 + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + gateway = &nexthop->gate; + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + } + + if (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + gateway = &nexthop->gate; + } + + if (nexthop->type == NEXTHOP_TYPE_IFINDEX) { + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + } + + if (!gateway && if_index == 0) + return 0; + + /* + * We have a valid nexthop. + */ + { + Fpm__Nexthop *pb_nh; + pb_nh = QPB_ALLOC(allocator, typeof(*pb_nh)); + if (!pb_nh) { + assert(0); + return 0; + } + + fpm__nexthop__init(pb_nh); + + if (if_index != 0) { + pb_nh->if_id = + qpb_if_identifier_create(allocator, if_index); + } + + if (gateway) { + pb_nh->address = qpb_l3_address_create( + allocator, gateway, rib_dest_af(dest)); + } + + msg->nexthops[msg->n_nexthops++] = pb_nh; + } + + // TODO: Use src. + + return 1; } /* * create_add_route_message */ -static Fpm__AddRoute * -create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, - struct route_entry *re) +static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator, + rib_dest_t *dest, + struct route_entry *re) { - Fpm__AddRoute *msg; - int discard; - struct nexthop *nexthop; - uint num_nhs, u; - struct nexthop *nexthops[MULTIPATH_NUM]; - - msg = QPB_ALLOC(allocator, typeof(*msg)); - if (!msg) { - assert(0); - return NULL; - } - - fpm__add_route__init(msg); - - msg->vrf_id = zvrf_id(rib_dest_vrf(dest)); - - qpb_address_family_set (&msg->address_family, rib_dest_af(dest)); - - /* - * XXX Hardcode subaddress family for now. - */ - msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST; - msg->key = fpm_route_key_create (allocator, rib_dest_prefix(dest)); - qpb_protocol_set (&msg->protocol, re->type); - - if ((re->flags & ZEBRA_FLAG_BLACKHOLE) || (re->flags & ZEBRA_FLAG_REJECT)) - discard = 1; - else - discard = 0; - - if (discard) - { - if (re->flags & ZEBRA_FLAG_BLACKHOLE) { - msg->route_type = FPM__ROUTE_TYPE__BLACKHOLE; - } else if (re->flags & ZEBRA_FLAG_REJECT) { - msg->route_type = FPM__ROUTE_TYPE__UNREACHABLE; - } else { - assert (0); - } - return msg; - } - else { - msg->route_type = FPM__ROUTE_TYPE__NORMAL; - } - - msg->metric = re->metric; - - /* - * Figure out the set of nexthops to be added to the message. - */ - num_nhs = 0; - for (ALL_NEXTHOPS (re->nexthop, nexthop)) - { - if (num_nhs >= multipath_num) - break; - - if (num_nhs >= ZEBRA_NUM_OF(nexthops)) - break; - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - - if (!CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - continue; - - nexthops[num_nhs] = nexthop; - num_nhs++; - } - - if (!num_nhs) { - zfpm_debug ("netlink_encode_route(): No useful nexthop."); - assert(0); - return NULL; - } - - /* - * And add them to the message. - */ - if (!(msg->nexthops = qpb_alloc_ptr_array(allocator, num_nhs))) { - assert(0); - return NULL; - } - - msg->n_nexthops = 0; - for (u = 0; u < num_nhs; u++) { - if (!add_nexthop(allocator, msg, dest, nexthops[u])) { - assert(0); - return NULL; - } - } - - assert(msg->n_nexthops == num_nhs); - - return msg; + Fpm__AddRoute *msg; + int discard; + struct nexthop *nexthop; + uint num_nhs, u; + struct nexthop *nexthops[MULTIPATH_NUM]; + + msg = QPB_ALLOC(allocator, typeof(*msg)); + if (!msg) { + assert(0); + return NULL; + } + + fpm__add_route__init(msg); + + msg->vrf_id = zvrf_id(rib_dest_vrf(dest)); + + qpb_address_family_set(&msg->address_family, rib_dest_af(dest)); + + /* + * XXX Hardcode subaddress family for now. + */ + msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST; + msg->key = fpm_route_key_create(allocator, rib_dest_prefix(dest)); + qpb_protocol_set(&msg->protocol, re->type); + + if ((re->flags & ZEBRA_FLAG_BLACKHOLE) + || (re->flags & ZEBRA_FLAG_REJECT)) + discard = 1; + else + discard = 0; + + if (discard) { + if (re->flags & ZEBRA_FLAG_BLACKHOLE) { + msg->route_type = FPM__ROUTE_TYPE__BLACKHOLE; + } else if (re->flags & ZEBRA_FLAG_REJECT) { + msg->route_type = FPM__ROUTE_TYPE__UNREACHABLE; + } else { + assert(0); + } + return msg; + } else { + msg->route_type = FPM__ROUTE_TYPE__NORMAL; + } + + msg->metric = re->metric; + + /* + * Figure out the set of nexthops to be added to the message. + */ + num_nhs = 0; + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (num_nhs >= multipath_num) + break; + + if (num_nhs >= ZEBRA_NUM_OF(nexthops)) + break; + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + continue; + + nexthops[num_nhs] = nexthop; + num_nhs++; + } + + if (!num_nhs) { + zfpm_debug("netlink_encode_route(): No useful nexthop."); + assert(0); + return NULL; + } + + /* + * And add them to the message. + */ + if (!(msg->nexthops = qpb_alloc_ptr_array(allocator, num_nhs))) { + assert(0); + return NULL; + } + + msg->n_nexthops = 0; + for (u = 0; u < num_nhs; u++) { + if (!add_nexthop(allocator, msg, dest, nexthops[u])) { + assert(0); + return NULL; + } + } + + assert(msg->n_nexthops == num_nhs); + + return msg; } /* * create_route_message */ -static Fpm__Message * -create_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, - struct route_entry *re) +static Fpm__Message *create_route_message(qpb_allocator_t *allocator, + rib_dest_t *dest, + struct route_entry *re) { - Fpm__Message *msg; - - msg = QPB_ALLOC(allocator, typeof(*msg)); - if (!msg) { - assert(0); - return NULL; - } - - fpm__message__init(msg); - - if (!re) { - msg->type = FPM__MESSAGE__TYPE__DELETE_ROUTE; - msg->delete_route = create_delete_route_message(allocator, dest, re); - if (!msg->delete_route) { - assert(0); - return NULL; - } - return msg; - } - - msg->type = FPM__MESSAGE__TYPE__ADD_ROUTE; - msg->add_route = create_add_route_message(allocator, dest, re); - if (!msg->add_route) { - assert(0); - return NULL; - } - - return msg; + Fpm__Message *msg; + + msg = QPB_ALLOC(allocator, typeof(*msg)); + if (!msg) { + assert(0); + return NULL; + } + + fpm__message__init(msg); + + if (!re) { + msg->type = FPM__MESSAGE__TYPE__DELETE_ROUTE; + msg->delete_route = + create_delete_route_message(allocator, dest, re); + if (!msg->delete_route) { + assert(0); + return NULL; + } + return msg; + } + + msg->type = FPM__MESSAGE__TYPE__ADD_ROUTE; + msg->add_route = create_add_route_message(allocator, dest, re); + if (!msg->add_route) { + assert(0); + return NULL; + } + + return msg; } /* @@ -285,25 +281,24 @@ create_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, * Returns the number of bytes written to the buffer. 0 or a negative * value indicates an error. */ -int -zfpm_protobuf_encode_route (rib_dest_t *dest, struct route_entry *re, - uint8_t *in_buf, size_t in_buf_len) +int zfpm_protobuf_encode_route(rib_dest_t *dest, struct route_entry *re, + uint8_t *in_buf, size_t in_buf_len) { - Fpm__Message *msg; - QPB_DECLARE_STACK_ALLOCATOR (allocator, 4096); - size_t len; + Fpm__Message *msg; + QPB_DECLARE_STACK_ALLOCATOR(allocator, 4096); + size_t len; - QPB_INIT_STACK_ALLOCATOR (allocator); + QPB_INIT_STACK_ALLOCATOR(allocator); - msg = create_route_message(&allocator, dest, re); - if (!msg) { - assert(0); - return 0; - } + msg = create_route_message(&allocator, dest, re); + if (!msg) { + assert(0); + return 0; + } - len = fpm__message__pack(msg, (uint8_t *) in_buf); - assert(len <= in_buf_len); + len = fpm__message__pack(msg, (uint8_t *)in_buf); + assert(len <= in_buf_len); - QPB_RESET_STACK_ALLOCATOR (allocator); - return len; + QPB_RESET_STACK_ALLOCATOR(allocator); + return len; } diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c index b71b96a18..5d059a450 100644 --- a/zebra/zebra_l2.c +++ b/zebra/zebra_l2.c @@ -49,111 +49,101 @@ /* static function declarations */ /* Private functions */ -static void -map_slaves_to_bridge (struct interface *br_if, int link) +static void map_slaves_to_bridge(struct interface *br_if, int link) { - struct vrf *vrf; - struct listnode *node; - struct interface *ifp; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) - { - struct zebra_if *zif; - struct zebra_l2info_brslave *br_slave; - - if (ifp->ifindex == IFINDEX_INTERNAL || - !ifp->info) - continue; - if (!IS_ZEBRA_IF_BRIDGE_SLAVE (ifp)) - continue; - - /* NOTE: This assumes 'zebra_l2info_brslave' is the first field - * for any L2 interface. - */ - zif = (struct zebra_if *) ifp->info; - br_slave = &zif->brslave_info; - - if (link) - { - if (br_slave->bridge_ifindex == br_if->ifindex) - br_slave->br_if = br_if; - } - else - { - if (br_slave->br_if == br_if) - br_slave->br_if = NULL; - } - } - } + struct vrf *vrf; + struct listnode *node; + struct interface *ifp; + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, ifp)) { + struct zebra_if *zif; + struct zebra_l2info_brslave *br_slave; + + if (ifp->ifindex == IFINDEX_INTERNAL || !ifp->info) + continue; + if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) + continue; + + /* NOTE: This assumes 'zebra_l2info_brslave' is the + * first field + * for any L2 interface. + */ + zif = (struct zebra_if *)ifp->info; + br_slave = &zif->brslave_info; + + if (link) { + if (br_slave->bridge_ifindex == br_if->ifindex) + br_slave->br_if = br_if; + } else { + if (br_slave->br_if == br_if) + br_slave->br_if = NULL; + } + } + } } /* Public functions */ -void -zebra_l2_map_slave_to_bridge (struct zebra_l2info_brslave *br_slave) +void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave) { - struct interface *br_if; + struct interface *br_if; - /* TODO: Handle change of master */ - br_if = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), - br_slave->bridge_ifindex); - if (br_if) - br_slave->br_if = br_if; + /* TODO: Handle change of master */ + br_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), + br_slave->bridge_ifindex); + if (br_if) + br_slave->br_if = br_if; } -void -zebra_l2_unmap_slave_from_bridge (struct zebra_l2info_brslave *br_slave) +void zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave) { - br_slave->br_if = NULL; + br_slave->br_if = NULL; } /* * Handle Bridge interface add or update. Update relevant info, * map slaves (if any) to the bridge. */ -void -zebra_l2_bridge_add_update (struct interface *ifp, - struct zebra_l2info_bridge *bridge_info, - int add) +void zebra_l2_bridge_add_update(struct interface *ifp, + struct zebra_l2info_bridge *bridge_info, + int add) { - struct zebra_if *zif; + struct zebra_if *zif; - zif = ifp->info; - assert(zif); + zif = ifp->info; + assert(zif); - /* Copy over the L2 information. */ - memcpy (&zif->l2info.br, bridge_info, sizeof (*bridge_info)); + /* Copy over the L2 information. */ + memcpy(&zif->l2info.br, bridge_info, sizeof(*bridge_info)); - /* Link all slaves to this bridge */ - map_slaves_to_bridge (ifp, 1); + /* Link all slaves to this bridge */ + map_slaves_to_bridge(ifp, 1); } /* * Handle Bridge interface delete. */ -void -zebra_l2_bridge_del (struct interface *ifp) +void zebra_l2_bridge_del(struct interface *ifp) { - /* Unlink all slaves to this bridge */ - map_slaves_to_bridge (ifp, 0); + /* Unlink all slaves to this bridge */ + map_slaves_to_bridge(ifp, 0); } /* * Update L2 info for a VLAN interface. Only relevant parameter is the * VLAN Id and this cannot change. */ -void -zebra_l2_vlanif_update (struct interface *ifp, - struct zebra_l2info_vlan *vlan_info) +void zebra_l2_vlanif_update(struct interface *ifp, + struct zebra_l2info_vlan *vlan_info) { - struct zebra_if *zif; + struct zebra_if *zif; - zif = ifp->info; - assert(zif); + zif = ifp->info; + assert(zif); - /* Copy over the L2 information. */ - memcpy (&zif->l2info.vl, vlan_info, sizeof (*vlan_info)); + /* Copy over the L2 information. */ + memcpy(&zif->l2info.vl, vlan_info, sizeof(*vlan_info)); } /* @@ -162,60 +152,55 @@ zebra_l2_vlanif_update (struct interface *ifp, * function. Upon update, the params of interest are the local tunnel * IP and VLAN mapping, but the latter is handled separately. */ -void -zebra_l2_vxlanif_add_update (struct interface *ifp, - struct zebra_l2info_vxlan *vxlan_info, - int add) +void zebra_l2_vxlanif_add_update(struct interface *ifp, + struct zebra_l2info_vxlan *vxlan_info, int add) { - struct zebra_if *zif; - struct in_addr old_vtep_ip; + struct zebra_if *zif; + struct in_addr old_vtep_ip; - zif = ifp->info; - assert(zif); + zif = ifp->info; + assert(zif); - if (add) - { - memcpy (&zif->l2info.vxl, vxlan_info, sizeof (*vxlan_info)); - zebra_vxlan_if_add (ifp); - return; - } + if (add) { + memcpy(&zif->l2info.vxl, vxlan_info, sizeof(*vxlan_info)); + zebra_vxlan_if_add(ifp); + return; + } - old_vtep_ip = zif->l2info.vxl.vtep_ip; - if (IPV4_ADDR_SAME(&old_vtep_ip, &vxlan_info->vtep_ip)) - return; + old_vtep_ip = zif->l2info.vxl.vtep_ip; + if (IPV4_ADDR_SAME(&old_vtep_ip, &vxlan_info->vtep_ip)) + return; - zif->l2info.vxl.vtep_ip = vxlan_info->vtep_ip; - zebra_vxlan_if_update (ifp, ZEBRA_VXLIF_LOCAL_IP_CHANGE); + zif->l2info.vxl.vtep_ip = vxlan_info->vtep_ip; + zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_LOCAL_IP_CHANGE); } /* * Handle change to VLAN to VNI mapping. */ -void -zebra_l2_vxlanif_update_access_vlan (struct interface *ifp, - vlanid_t access_vlan) +void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp, + vlanid_t access_vlan) { - struct zebra_if *zif; - vlanid_t old_access_vlan; + struct zebra_if *zif; + vlanid_t old_access_vlan; - zif = ifp->info; - assert(zif); + zif = ifp->info; + assert(zif); - old_access_vlan = zif->l2info.vxl.access_vlan; - if (old_access_vlan == access_vlan) - return; + old_access_vlan = zif->l2info.vxl.access_vlan; + if (old_access_vlan == access_vlan) + return; - zif->l2info.vxl.access_vlan = access_vlan; - zebra_vxlan_if_update (ifp, ZEBRA_VXLIF_VLAN_CHANGE); + zif->l2info.vxl.access_vlan = access_vlan; + zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_VLAN_CHANGE); } /* * Handle VxLAN interface delete. */ -void -zebra_l2_vxlanif_del (struct interface *ifp) +void zebra_l2_vxlanif_del(struct interface *ifp) { - zebra_vxlan_if_del (ifp); + zebra_vxlan_if_del(ifp); } /* @@ -223,29 +208,28 @@ zebra_l2_vxlanif_del (struct interface *ifp) * NOTE: It is currently assumped that an interface has to be unmapped * from a bridge before it can be mapped to another bridge. */ -void -zebra_l2if_update_bridge_slave (struct interface *ifp, - ifindex_t bridge_ifindex) +void zebra_l2if_update_bridge_slave(struct interface *ifp, + ifindex_t bridge_ifindex) { - struct zebra_if *zif; - ifindex_t old_bridge_ifindex; + struct zebra_if *zif; + ifindex_t old_bridge_ifindex; - zif = ifp->info; - assert(zif); + zif = ifp->info; + assert(zif); - old_bridge_ifindex = zif->brslave_info.bridge_ifindex; - if (old_bridge_ifindex == bridge_ifindex) - return; + old_bridge_ifindex = zif->brslave_info.bridge_ifindex; + if (old_bridge_ifindex == bridge_ifindex) + return; - zif->brslave_info.bridge_ifindex = bridge_ifindex; + zif->brslave_info.bridge_ifindex = bridge_ifindex; - /* Set up or remove link with master */ - if (bridge_ifindex != IFINDEX_INTERNAL) - zebra_l2_map_slave_to_bridge (&zif->brslave_info); - else if (old_bridge_ifindex != IFINDEX_INTERNAL) - zebra_l2_unmap_slave_from_bridge (&zif->brslave_info); + /* Set up or remove link with master */ + if (bridge_ifindex != IFINDEX_INTERNAL) + zebra_l2_map_slave_to_bridge(&zif->brslave_info); + else if (old_bridge_ifindex != IFINDEX_INTERNAL) + zebra_l2_unmap_slave_from_bridge(&zif->brslave_info); - /* In the case of VxLAN, invoke the handler for EVPN. */ - if (zif->zif_type == ZEBRA_IF_VXLAN) - zebra_vxlan_if_update (ifp, ZEBRA_VXLIF_MASTER_CHANGE); + /* In the case of VxLAN, invoke the handler for EVPN. */ + if (zif->zif_type == ZEBRA_IF_VXLAN) + zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE); } diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h index 5cfc6dee4..d9bbcfed6 100644 --- a/zebra/zebra_l2.h +++ b/zebra/zebra_l2.h @@ -30,37 +30,32 @@ #include "vxlan.h" /* zebra L2 interface information - bridge slave (linkage to bridge) */ -struct zebra_l2info_brslave -{ - ifindex_t bridge_ifindex; /* Bridge Master */ - struct interface *br_if; /* Pointer to master */ +struct zebra_l2info_brslave { + ifindex_t bridge_ifindex; /* Bridge Master */ + struct interface *br_if; /* Pointer to master */ }; /* zebra L2 interface information - bridge interface */ -struct zebra_l2info_bridge -{ - u_char vlan_aware; /* VLAN-aware bridge? */ +struct zebra_l2info_bridge { + u_char vlan_aware; /* VLAN-aware bridge? */ }; /* zebra L2 interface information - VLAN interface */ -struct zebra_l2info_vlan -{ - vlanid_t vid; /* VLAN id */ +struct zebra_l2info_vlan { + vlanid_t vid; /* VLAN id */ }; /* zebra L2 interface information - VXLAN interface */ -struct zebra_l2info_vxlan -{ - vni_t vni; /* VNI */ - struct in_addr vtep_ip; /* Local tunnel IP */ - vlanid_t access_vlan; /* Access VLAN - for VLAN-aware bridge. */ +struct zebra_l2info_vxlan { + vni_t vni; /* VNI */ + struct in_addr vtep_ip; /* Local tunnel IP */ + vlanid_t access_vlan; /* Access VLAN - for VLAN-aware bridge. */ }; -union zebra_l2if_info -{ - struct zebra_l2info_bridge br; - struct zebra_l2info_vlan vl; - struct zebra_l2info_vxlan vxl; +union zebra_l2if_info { + struct zebra_l2info_bridge br; + struct zebra_l2info_vlan vl; + struct zebra_l2info_vxlan vxl; }; /* NOTE: These macros are to be invoked only in the "correct" context. @@ -70,25 +65,25 @@ union zebra_l2if_info #define VNI_FROM_ZEBRA_IF(zif) (zif)->l2info.vxl.vni #define VLAN_ID_FROM_ZEBRA_IF(zif) (zif)->l2info.vl.vid -#define IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zif) \ - ((zif)->l2info.br.vlan_aware == 1) +#define IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zif) ((zif)->l2info.br.vlan_aware == 1) -extern void zebra_l2_map_slave_to_bridge (struct zebra_l2info_brslave *br_slave); -extern void zebra_l2_unmap_slave_from_bridge (struct zebra_l2info_brslave *br_slave); -extern void zebra_l2_bridge_add_update (struct interface *ifp, - struct zebra_l2info_bridge *bridge_info, - int add); -extern void zebra_l2_bridge_del (struct interface *ifp); -extern void zebra_l2_vlanif_update (struct interface *ifp, - struct zebra_l2info_vlan *vlan_info); -extern void zebra_l2_vxlanif_add_update (struct interface *ifp, - struct zebra_l2info_vxlan *vxlan_info, - int add); -extern void zebra_l2_vxlanif_update_access_vlan (struct interface *ifp, - vlanid_t access_vlan); -extern void zebra_l2_vxlanif_del (struct interface *ifp); -extern void zebra_l2if_update_bridge_slave (struct interface *ifp, - ifindex_t bridge_ifindex); +extern void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave); +extern void +zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave); +extern void zebra_l2_bridge_add_update(struct interface *ifp, + struct zebra_l2info_bridge *bridge_info, + int add); +extern void zebra_l2_bridge_del(struct interface *ifp); +extern void zebra_l2_vlanif_update(struct interface *ifp, + struct zebra_l2info_vlan *vlan_info); +extern void zebra_l2_vxlanif_add_update(struct interface *ifp, + struct zebra_l2info_vxlan *vxlan_info, + int add); +extern void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp, + vlanid_t access_vlan); +extern void zebra_l2_vxlanif_del(struct interface *ifp); +extern void zebra_l2if_update_bridge_slave(struct interface *ifp, + ifindex_t bridge_ifindex); #endif /* _ZEBRA_L2_H */ diff --git a/zebra/zebra_l2_null.c b/zebra/zebra_l2_null.c index d50107f65..c063f77bd 100644 --- a/zebra/zebra_l2_null.c +++ b/zebra/zebra_l2_null.c @@ -29,48 +29,44 @@ #include "zebra/zebra_vrf.h" #include "zebra/zebra_l2.h" -void zebra_l2_map_slave_to_bridge (struct zebra_l2info_brslave *br_slave) +void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave) { } -void -zebra_l2_unmap_slave_from_bridge (struct zebra_l2info_brslave *br_slave) +void zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave) { } -void zebra_l2_bridge_add_update (struct interface *ifp, - struct zebra_l2info_bridge *bridge_info, - int add) +void zebra_l2_bridge_add_update(struct interface *ifp, + struct zebra_l2info_bridge *bridge_info, + int add) { } -void zebra_l2_bridge_del (struct interface *ifp) +void zebra_l2_bridge_del(struct interface *ifp) { } -void zebra_l2_vlanif_update (struct interface *ifp, - struct zebra_l2info_vlan *vlan_info) +void zebra_l2_vlanif_update(struct interface *ifp, + struct zebra_l2info_vlan *vlan_info) { } -void zebra_l2_vxlanif_add_update (struct interface *ifp, - struct zebra_l2info_vxlan *vxlan_info, - int add) +void zebra_l2_vxlanif_add_update(struct interface *ifp, + struct zebra_l2info_vxlan *vxlan_info, int add) { } -void -zebra_l2_vxlanif_update_access_vlan (struct interface *ifp, - vlanid_t access_vlan) +void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp, + vlanid_t access_vlan) { } -void zebra_l2_vxlanif_del (struct interface *ifp) +void zebra_l2_vxlanif_del(struct interface *ifp) { } -void -zebra_l2if_update_bridge_slave (struct interface *ifp, - ifindex_t bridge_ifindex) +void zebra_l2if_update_bridge_slave(struct interface *ifp, + ifindex_t bridge_ifindex) { } diff --git a/zebra/zebra_memory.c b/zebra/zebra_memory.c index b8e1a130e..ee041b1c3 100644 --- a/zebra/zebra_memory.c +++ b/zebra/zebra_memory.c @@ -26,11 +26,11 @@ #include "zebra_memory.h" DEFINE_MGROUP(ZEBRA, "zebra") -DEFINE_MTYPE(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix") -DEFINE_MTYPE(ZEBRA, ZEBRA_VRF, "ZEBRA VRF") -DEFINE_MTYPE(ZEBRA, RE, "Route Entry") -DEFINE_MTYPE(ZEBRA, RIB_QUEUE, "RIB process work queue") -DEFINE_MTYPE(ZEBRA, STATIC_ROUTE, "Static route") -DEFINE_MTYPE(ZEBRA, RIB_DEST, "RIB destination") +DEFINE_MTYPE(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix") +DEFINE_MTYPE(ZEBRA, ZEBRA_VRF, "ZEBRA VRF") +DEFINE_MTYPE(ZEBRA, RE, "Route Entry") +DEFINE_MTYPE(ZEBRA, RIB_QUEUE, "RIB process work queue") +DEFINE_MTYPE(ZEBRA, STATIC_ROUTE, "Static route") +DEFINE_MTYPE(ZEBRA, RIB_DEST, "RIB destination") DEFINE_MTYPE(ZEBRA, RIB_TABLE_INFO, "RIB table info") -DEFINE_MTYPE(ZEBRA, RNH, "Nexthop tracking object") +DEFINE_MTYPE(ZEBRA, RNH, "Nexthop tracking object") diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 3c8503878..e44e5d2e6 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -45,12 +45,12 @@ #include "zebra/zebra_vrf.h" #include "zebra/zebra_mpls.h" -DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object") -DEFINE_MTYPE_STATIC(ZEBRA, FEC, "MPLS FEC object") -DEFINE_MTYPE_STATIC(ZEBRA, SLSP, "MPLS static LSP config") -DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object") -DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE, "MPLS static nexthop object") -DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE_IFNAME, "MPLS static nexthop ifname") +DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object") +DEFINE_MTYPE_STATIC(ZEBRA, FEC, "MPLS FEC object") +DEFINE_MTYPE_STATIC(ZEBRA, SLSP, "MPLS static LSP config") +DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object") +DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE, "MPLS static nexthop object") +DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE_IFNAME, "MPLS static nexthop ifname") int mpls_enabled; @@ -59,106 +59,72 @@ extern struct zebra_t zebrad; /* static function declarations */ -static void -fec_evaluate (struct zebra_vrf *zvrf); -static u_int32_t -fec_derive_label_from_index (struct zebra_vrf *vrf, zebra_fec_t *fec); -static int -lsp_install (struct zebra_vrf *zvrf, mpls_label_t label, - struct route_node *rn, struct route_entry *re); -static int -lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t label); -static int -fec_change_update_lsp (struct zebra_vrf *zvrf, zebra_fec_t *fec, mpls_label_t old_label); -static int -fec_send (zebra_fec_t *fec, struct zserv *client); -static void -fec_update_clients (zebra_fec_t *fec); -static void -fec_print (zebra_fec_t *fec, struct vty *vty); -static zebra_fec_t * -fec_find (struct route_table *table, struct prefix *p); -static zebra_fec_t * -fec_add (struct route_table *table, struct prefix *p, mpls_label_t label, - u_int32_t flags, u_int32_t label_index); -static int -fec_del (zebra_fec_t *fec); - -static unsigned int -label_hash (void *p); -static int -label_cmp (const void *p1, const void *p2); -static int -nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop); -static int -nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop); -static int -nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe); - -static void -lsp_select_best_nhlfe (zebra_lsp_t *lsp); -static void -lsp_uninstall_from_kernel (struct hash_backet *backet, void *ctxt); -static void -lsp_schedule (struct hash_backet *backet, void *ctxt); -static wq_item_status -lsp_process (struct work_queue *wq, void *data); -static void -lsp_processq_del (struct work_queue *wq, void *data); -static void -lsp_processq_complete (struct work_queue *wq); -static int -lsp_processq_add (zebra_lsp_t *lsp); -static void * -lsp_alloc (void *p); - -static char * -nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size); -static int -nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex); -static zebra_nhlfe_t * -nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex); -static zebra_nhlfe_t * -nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex, mpls_label_t out_label); -static int -nhlfe_del (zebra_nhlfe_t *snhlfe); -static void -nhlfe_out_label_update (zebra_nhlfe_t *nhlfe, struct nexthop_label *nh_label); -static int -mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp, - enum lsp_types_t type); -static int -mpls_static_lsp_uninstall_all (struct zebra_vrf *zvrf, mpls_label_t in_label); -static void -nhlfe_print (zebra_nhlfe_t *nhlfe, struct vty *vty); -static void -lsp_print (zebra_lsp_t *lsp, void *ctxt); -static void * -slsp_alloc (void *p); -static int -snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex); -static zebra_snhlfe_t * -snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex); -static zebra_snhlfe_t * -snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex, mpls_label_t out_label); -static int -snhlfe_del (zebra_snhlfe_t *snhlfe); -static int -snhlfe_del_all (zebra_slsp_t *slsp); -static char * -snhlfe2str (zebra_snhlfe_t *snhlfe, char *buf, int size); -static int -mpls_processq_init (struct zebra_t *zebra); - - +static void fec_evaluate(struct zebra_vrf *zvrf); +static u_int32_t fec_derive_label_from_index(struct zebra_vrf *vrf, + zebra_fec_t *fec); +static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label, + struct route_node *rn, struct route_entry *re); +static int lsp_uninstall(struct zebra_vrf *zvrf, mpls_label_t label); +static int fec_change_update_lsp(struct zebra_vrf *zvrf, zebra_fec_t *fec, + mpls_label_t old_label); +static int fec_send(zebra_fec_t *fec, struct zserv *client); +static void fec_update_clients(zebra_fec_t *fec); +static void fec_print(zebra_fec_t *fec, struct vty *vty); +static zebra_fec_t *fec_find(struct route_table *table, struct prefix *p); +static zebra_fec_t *fec_add(struct route_table *table, struct prefix *p, + mpls_label_t label, u_int32_t flags, + u_int32_t label_index); +static int fec_del(zebra_fec_t *fec); + +static unsigned int label_hash(void *p); +static int label_cmp(const void *p1, const void *p2); +static int nhlfe_nexthop_active_ipv4(zebra_nhlfe_t *nhlfe, + struct nexthop *nexthop); +static int nhlfe_nexthop_active_ipv6(zebra_nhlfe_t *nhlfe, + struct nexthop *nexthop); +static int nhlfe_nexthop_active(zebra_nhlfe_t *nhlfe); + +static void lsp_select_best_nhlfe(zebra_lsp_t *lsp); +static void lsp_uninstall_from_kernel(struct hash_backet *backet, void *ctxt); +static void lsp_schedule(struct hash_backet *backet, void *ctxt); +static wq_item_status lsp_process(struct work_queue *wq, void *data); +static void lsp_processq_del(struct work_queue *wq, void *data); +static void lsp_processq_complete(struct work_queue *wq); +static int lsp_processq_add(zebra_lsp_t *lsp); +static void *lsp_alloc(void *p); + +static char *nhlfe2str(zebra_nhlfe_t *nhlfe, char *buf, int size); +static int nhlfe_nhop_match(zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex); +static zebra_nhlfe_t *nhlfe_find(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex); +static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex, mpls_label_t out_label); +static int nhlfe_del(zebra_nhlfe_t *snhlfe); +static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe, + struct nexthop_label *nh_label); +static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp, + enum lsp_types_t type); +static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf, + mpls_label_t in_label); +static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty); +static void lsp_print(zebra_lsp_t *lsp, void *ctxt); +static void *slsp_alloc(void *p); +static int snhlfe_match(zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex); +static zebra_snhlfe_t *snhlfe_find(zebra_slsp_t *slsp, + enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex); +static zebra_snhlfe_t *snhlfe_add(zebra_slsp_t *slsp, + enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex, + mpls_label_t out_label); +static int snhlfe_del(zebra_snhlfe_t *snhlfe); +static int snhlfe_del_all(zebra_slsp_t *slsp); +static char *snhlfe2str(zebra_snhlfe_t *snhlfe, char *buf, int size); +static int mpls_processq_init(struct zebra_t *zebra); /* Static functions */ @@ -166,189 +132,175 @@ mpls_processq_init (struct zebra_t *zebra); /* * Install label forwarding entry based on labeled-route entry. */ -static int -lsp_install (struct zebra_vrf *zvrf, mpls_label_t label, - struct route_node *rn, struct route_entry *re) -{ - struct hash *lsp_table; - zebra_ile_t tmp_ile; - zebra_lsp_t *lsp; - zebra_nhlfe_t *nhlfe; - struct nexthop *nexthop; - enum lsp_types_t lsp_type; - char buf[BUFSIZ]; - int added, changed; - - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return -1; - - lsp_type = lsp_type_from_re_type (re->type); - added = changed = 0; - - /* Locate or allocate LSP entry. */ - tmp_ile.in_label = label; - lsp = hash_get (lsp_table, &tmp_ile, lsp_alloc); - if (!lsp) - return -1; - - /* For each active nexthop, create NHLFE. Note that we deliberately skip - * recursive nexthops right now, because intermediate hops won't understand - * the label advertised by the recursive nexthop (plus we don't have the - * logic yet to push multiple labels). - */ - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - { - /* Skip inactive and recursive entries. */ - if (!CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - continue; - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - - nhlfe = nhlfe_find (lsp, lsp_type, nexthop->type, &nexthop->gate, - nexthop->ifindex); - if (nhlfe) - { - /* Clear deleted flag (in case it was set) */ - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED); - if (nexthop_labels_match (nhlfe->nexthop, nexthop)) - /* No change */ - continue; - - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("LSP in-label %u type %d nexthop %s " - "out-label changed", - lsp->ile.in_label, lsp_type, buf); - } - - /* Update out label, trigger processing. */ - nhlfe_out_label_update (nhlfe, nexthop->nh_label); - SET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - changed++; - } - else - { - /* Add LSP entry to this nexthop */ - nhlfe = nhlfe_add (lsp, lsp_type, nexthop->type, - &nexthop->gate, nexthop->ifindex, - nexthop->nh_label->label[0]); - if (!nhlfe) - return -1; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("Add LSP in-label %u type %d nexthop %s " - "out-label %u", - lsp->ile.in_label, lsp_type, buf, - nexthop->nh_label->label[0]); - } - - lsp->addr_family = NHLFE_FAMILY (nhlfe); - - /* Mark NHLFE as changed. */ - SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); - added++; - } - } - - /* Queue LSP for processing if necessary. If no NHLFE got added (special - * case), delete the LSP entry; this case results in somewhat ugly logging. - */ - if (added || changed) - { - if (lsp_processq_add (lsp)) - return -1; - } - else if (!lsp->nhlfe_list && - !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Free LSP in-label %u flags 0x%x", - lsp->ile.in_label, lsp->flags); - - lsp = hash_release(lsp_table, &lsp->ile); - if (lsp) - XFREE(MTYPE_LSP, lsp); - } - - return 0; +static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label, + struct route_node *rn, struct route_entry *re) +{ + struct hash *lsp_table; + zebra_ile_t tmp_ile; + zebra_lsp_t *lsp; + zebra_nhlfe_t *nhlfe; + struct nexthop *nexthop; + enum lsp_types_t lsp_type; + char buf[BUFSIZ]; + int added, changed; + + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return -1; + + lsp_type = lsp_type_from_re_type(re->type); + added = changed = 0; + + /* Locate or allocate LSP entry. */ + tmp_ile.in_label = label; + lsp = hash_get(lsp_table, &tmp_ile, lsp_alloc); + if (!lsp) + return -1; + + /* For each active nexthop, create NHLFE. Note that we deliberately skip + * recursive nexthops right now, because intermediate hops won't + * understand + * the label advertised by the recursive nexthop (plus we don't have the + * logic yet to push multiple labels). + */ + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { + /* Skip inactive and recursive entries. */ + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + continue; + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + + nhlfe = nhlfe_find(lsp, lsp_type, nexthop->type, &nexthop->gate, + nexthop->ifindex); + if (nhlfe) { + /* Clear deleted flag (in case it was set) */ + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); + if (nexthop_labels_match(nhlfe->nexthop, nexthop)) + /* No change */ + continue; + + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "LSP in-label %u type %d nexthop %s " + "out-label changed", + lsp->ile.in_label, lsp_type, buf); + } + + /* Update out label, trigger processing. */ + nhlfe_out_label_update(nhlfe, nexthop->nh_label); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + changed++; + } else { + /* Add LSP entry to this nexthop */ + nhlfe = nhlfe_add(lsp, lsp_type, nexthop->type, + &nexthop->gate, nexthop->ifindex, + nexthop->nh_label->label[0]); + if (!nhlfe) + return -1; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "Add LSP in-label %u type %d nexthop %s " + "out-label %u", + lsp->ile.in_label, lsp_type, buf, + nexthop->nh_label->label[0]); + } + + lsp->addr_family = NHLFE_FAMILY(nhlfe); + + /* Mark NHLFE as changed. */ + SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + added++; + } + } + + /* Queue LSP for processing if necessary. If no NHLFE got added (special + * case), delete the LSP entry; this case results in somewhat ugly + * logging. + */ + if (added || changed) { + if (lsp_processq_add(lsp)) + return -1; + } else if (!lsp->nhlfe_list + && !CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Free LSP in-label %u flags 0x%x", + lsp->ile.in_label, lsp->flags); + + lsp = hash_release(lsp_table, &lsp->ile); + if (lsp) + XFREE(MTYPE_LSP, lsp); + } + + return 0; } /* * Uninstall all non-static NHLFEs of a label forwarding entry. If all * NHLFEs are removed, the entire entry is deleted. */ -static int -lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t label) -{ - struct hash *lsp_table; - zebra_ile_t tmp_ile; - zebra_lsp_t *lsp; - zebra_nhlfe_t *nhlfe, *nhlfe_next; - char buf[BUFSIZ]; - - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return -1; - - /* If entry is not present, exit. */ - tmp_ile.in_label = label; - lsp = hash_lookup (lsp_table, &tmp_ile); - if (!lsp || !lsp->nhlfe_list) - return 0; - - /* Mark NHLFEs for delete or directly delete, as appropriate. */ - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) - { - nhlfe_next = nhlfe->next; - - /* Skip static NHLFEs */ - if (nhlfe->type == ZEBRA_LSP_STATIC) - continue; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x", - label, nhlfe->type, buf, nhlfe->flags); - } - - if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)) - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED); - } - else - { - nhlfe_del (nhlfe); - } - } - - /* Queue LSP for processing, if needed, else delete. */ - if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) - { - if (lsp_processq_add (lsp)) - return -1; - } - else if (!lsp->nhlfe_list && - !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Del LSP in-label %u flags 0x%x", - lsp->ile.in_label, lsp->flags); - - lsp = hash_release(lsp_table, &lsp->ile); - if (lsp) - XFREE(MTYPE_LSP, lsp); - } - - return 0; +static int lsp_uninstall(struct zebra_vrf *zvrf, mpls_label_t label) +{ + struct hash *lsp_table; + zebra_ile_t tmp_ile; + zebra_lsp_t *lsp; + zebra_nhlfe_t *nhlfe, *nhlfe_next; + char buf[BUFSIZ]; + + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return -1; + + /* If entry is not present, exit. */ + tmp_ile.in_label = label; + lsp = hash_lookup(lsp_table, &tmp_ile); + if (!lsp || !lsp->nhlfe_list) + return 0; + + /* Mark NHLFEs for delete or directly delete, as appropriate. */ + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) { + nhlfe_next = nhlfe->next; + + /* Skip static NHLFEs */ + if (nhlfe->type == ZEBRA_LSP_STATIC) + continue; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "Del LSP in-label %u type %d nexthop %s flags 0x%x", + label, nhlfe->type, buf, nhlfe->flags); + } + + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)) { + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); + } else { + nhlfe_del(nhlfe); + } + } + + /* Queue LSP for processing, if needed, else delete. */ + if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) { + if (lsp_processq_add(lsp)) + return -1; + } else if (!lsp->nhlfe_list + && !CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Del LSP in-label %u flags 0x%x", + lsp->ile.in_label, lsp->flags); + + lsp = hash_release(lsp_table, &lsp->ile); + if (lsp) + XFREE(MTYPE_LSP, lsp); + } + + return 0; } /* @@ -356,54 +308,55 @@ lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t label) * will walk all registered FECs with label-index and appropriately update * their local labels and trigger client updates. */ -static void -fec_evaluate (struct zebra_vrf *zvrf) -{ - struct route_node *rn; - zebra_fec_t *fec; - u_int32_t old_label, new_label; - int af; - char buf[BUFSIZ]; - - for (af = AFI_IP; af < AFI_MAX; af++) - { - if (zvrf->fec_table[af] == NULL) - continue; - - for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn)) - { - if ((fec = rn->info) == NULL) - continue; - - /* Skip configured FECs and those without a label index. */ - if (fec->flags & FEC_FLAG_CONFIGURED || - fec->label_index == MPLS_INVALID_LABEL_INDEX) - continue; - - if (IS_ZEBRA_DEBUG_MPLS) - prefix2str(&rn->p, buf, BUFSIZ); - - /* Save old label, determine new label. */ - old_label = fec->label; - new_label = zvrf->mpls_srgb.start_label + fec->label_index; - if (new_label >= zvrf->mpls_srgb.end_label) - new_label = MPLS_INVALID_LABEL; - - /* If label has changed, update FEC and clients. */ - if (new_label == old_label) - continue; - - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Update fec %s new label %u upon label block", - buf, new_label); - - fec->label = new_label; - fec_update_clients (fec); - - /* Update label forwarding entries appropriately */ - fec_change_update_lsp (zvrf, fec, old_label); - } - } +static void fec_evaluate(struct zebra_vrf *zvrf) +{ + struct route_node *rn; + zebra_fec_t *fec; + u_int32_t old_label, new_label; + int af; + char buf[BUFSIZ]; + + for (af = AFI_IP; af < AFI_MAX; af++) { + if (zvrf->fec_table[af] == NULL) + continue; + + for (rn = route_top(zvrf->fec_table[af]); rn; + rn = route_next(rn)) { + if ((fec = rn->info) == NULL) + continue; + + /* Skip configured FECs and those without a label index. + */ + if (fec->flags & FEC_FLAG_CONFIGURED + || fec->label_index == MPLS_INVALID_LABEL_INDEX) + continue; + + if (IS_ZEBRA_DEBUG_MPLS) + prefix2str(&rn->p, buf, BUFSIZ); + + /* Save old label, determine new label. */ + old_label = fec->label; + new_label = + zvrf->mpls_srgb.start_label + fec->label_index; + if (new_label >= zvrf->mpls_srgb.end_label) + new_label = MPLS_INVALID_LABEL; + + /* If label has changed, update FEC and clients. */ + if (new_label == old_label) + continue; + + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "Update fec %s new label %u upon label block", + buf, new_label); + + fec->label = new_label; + fec_update_clients(fec); + + /* Update label forwarding entries appropriately */ + fec_change_update_lsp(zvrf, fec, old_label); + } + } } /* @@ -411,195 +364,188 @@ fec_evaluate (struct zebra_vrf *zvrf) * its label index. The index is "acceptable" if it falls within the * globally configured label block (SRGB). */ -static u_int32_t -fec_derive_label_from_index (struct zebra_vrf *zvrf, zebra_fec_t *fec) +static u_int32_t fec_derive_label_from_index(struct zebra_vrf *zvrf, + zebra_fec_t *fec) { - u_int32_t label; + u_int32_t label; - if (fec->label_index != MPLS_INVALID_LABEL_INDEX && - zvrf->mpls_srgb.start_label && - ((label = zvrf->mpls_srgb.start_label + fec->label_index) < - zvrf->mpls_srgb.end_label)) - fec->label = label; - else - fec->label = MPLS_INVALID_LABEL; + if (fec->label_index != MPLS_INVALID_LABEL_INDEX + && zvrf->mpls_srgb.start_label + && ((label = zvrf->mpls_srgb.start_label + fec->label_index) + < zvrf->mpls_srgb.end_label)) + fec->label = label; + else + fec->label = MPLS_INVALID_LABEL; - return fec->label; + return fec->label; } /* * There is a change for this FEC. Install or uninstall label forwarding * entries, as appropriate. */ -static int -fec_change_update_lsp (struct zebra_vrf *zvrf, zebra_fec_t *fec, mpls_label_t old_label) +static int fec_change_update_lsp(struct zebra_vrf *zvrf, zebra_fec_t *fec, + mpls_label_t old_label) { - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - afi_t afi; + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + afi_t afi; - /* Uninstall label forwarding entry, if previously installed. */ - if (old_label != MPLS_INVALID_LABEL && - old_label != MPLS_IMP_NULL_LABEL) - lsp_uninstall (zvrf, old_label); + /* Uninstall label forwarding entry, if previously installed. */ + if (old_label != MPLS_INVALID_LABEL && old_label != MPLS_IMP_NULL_LABEL) + lsp_uninstall(zvrf, old_label); - /* Install label forwarding entry corr. to new label, if needed. */ - if (fec->label == MPLS_INVALID_LABEL || - fec->label == MPLS_IMP_NULL_LABEL) - return 0; + /* Install label forwarding entry corr. to new label, if needed. */ + if (fec->label == MPLS_INVALID_LABEL + || fec->label == MPLS_IMP_NULL_LABEL) + return 0; - afi = family2afi(PREFIX_FAMILY(&fec->rn->p)); - table = zebra_vrf_table (afi, SAFI_UNICAST, zvrf_id (zvrf)); - if (!table) - return 0; + afi = family2afi(PREFIX_FAMILY(&fec->rn->p)); + table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf)); + if (!table) + return 0; - /* See if labeled route exists. */ - rn = route_node_lookup (table, &fec->rn->p); - if (!rn) - return 0; + /* See if labeled route exists. */ + rn = route_node_lookup(table, &fec->rn->p); + if (!rn) + return 0; - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED)) - break; - } + RNODE_FOREACH_RE(rn, re) + { + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) + break; + } - if (!re || !zebra_rib_labeled_unicast (re)) - return 0; + if (!re || !zebra_rib_labeled_unicast(re)) + return 0; - if (lsp_install (zvrf, fec->label, rn, re)) - return -1; + if (lsp_install(zvrf, fec->label, rn, re)) + return -1; - return 0; + return 0; } /* * Inform about FEC to a registered client. */ -static int -fec_send (zebra_fec_t *fec, struct zserv *client) +static int fec_send(zebra_fec_t *fec, struct zserv *client) { - struct stream *s; - struct route_node *rn; + struct stream *s; + struct route_node *rn; - rn = fec->rn; + rn = fec->rn; - /* Get output stream. */ - s = client->obuf; - stream_reset (s); + /* Get output stream. */ + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_FEC_UPDATE, VRF_DEFAULT); + zserv_create_header(s, ZEBRA_FEC_UPDATE, VRF_DEFAULT); - stream_putw(s, rn->p.family); - stream_put_prefix (s, &rn->p); - stream_putl(s, fec->label); - stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client); + stream_putw(s, rn->p.family); + stream_put_prefix(s, &rn->p); + stream_putl(s, fec->label); + stream_putw_at(s, 0, stream_get_endp(s)); + return zebra_server_send_message(client); } /* * Update all registered clients about this FEC. Caller should've updated * FEC and ensure no duplicate updates. */ -static void -fec_update_clients (zebra_fec_t *fec) +static void fec_update_clients(zebra_fec_t *fec) { - struct listnode *node; - struct zserv *client; + struct listnode *node; + struct zserv *client; - for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, client)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Update client %s", zebra_route_string(client->proto)); - fec_send(fec, client); - } + for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, client)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Update client %s", + zebra_route_string(client->proto)); + fec_send(fec, client); + } } /* * Print a FEC-label binding entry. */ -static void -fec_print (zebra_fec_t *fec, struct vty *vty) -{ - struct route_node *rn; - struct listnode *node; - struct zserv *client; - char buf[BUFSIZ]; - - rn = fec->rn; - prefix2str(&rn->p, buf, BUFSIZ); - vty_out (vty, "%s\n", buf); - vty_out(vty, " Label: %s", label2str(fec->label, buf, BUFSIZ)); - if (fec->label_index != MPLS_INVALID_LABEL_INDEX) - vty_out(vty, ", Label Index: %u", fec->label_index); - vty_out (vty, "\n"); - if (!list_isempty(fec->client_list)) - { - vty_out(vty, " Client list:"); - for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, client)) - vty_out(vty, " %s(fd %d)", - zebra_route_string(client->proto), client->sock); - vty_out (vty, "\n"); - } +static void fec_print(zebra_fec_t *fec, struct vty *vty) +{ + struct route_node *rn; + struct listnode *node; + struct zserv *client; + char buf[BUFSIZ]; + + rn = fec->rn; + prefix2str(&rn->p, buf, BUFSIZ); + vty_out(vty, "%s\n", buf); + vty_out(vty, " Label: %s", label2str(fec->label, buf, BUFSIZ)); + if (fec->label_index != MPLS_INVALID_LABEL_INDEX) + vty_out(vty, ", Label Index: %u", fec->label_index); + vty_out(vty, "\n"); + if (!list_isempty(fec->client_list)) { + vty_out(vty, " Client list:"); + for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, client)) + vty_out(vty, " %s(fd %d)", + zebra_route_string(client->proto), + client->sock); + vty_out(vty, "\n"); + } } /* * Locate FEC-label binding that matches with passed info. */ -static zebra_fec_t * -fec_find (struct route_table *table, struct prefix *p) +static zebra_fec_t *fec_find(struct route_table *table, struct prefix *p) { - struct route_node *rn; + struct route_node *rn; - apply_mask (p); - rn = route_node_lookup(table, p); - if (!rn) - return NULL; + apply_mask(p); + rn = route_node_lookup(table, p); + if (!rn) + return NULL; - route_unlock_node(rn); - return (rn->info); + route_unlock_node(rn); + return (rn->info); } /* * Add a FEC. This may be upon a client registering for a binding * or when a binding is configured. */ -static zebra_fec_t * -fec_add (struct route_table *table, struct prefix *p, - mpls_label_t label, u_int32_t flags, u_int32_t label_index) +static zebra_fec_t *fec_add(struct route_table *table, struct prefix *p, + mpls_label_t label, u_int32_t flags, + u_int32_t label_index) { - struct route_node *rn; - zebra_fec_t *fec; + struct route_node *rn; + zebra_fec_t *fec; - apply_mask (p); + apply_mask(p); - /* Lookup (or add) route node.*/ - rn = route_node_get (table, p); - if (!rn) - return NULL; + /* Lookup (or add) route node.*/ + rn = route_node_get(table, p); + if (!rn) + return NULL; - fec = rn->info; + fec = rn->info; - if (!fec) - { - fec = XCALLOC (MTYPE_FEC, sizeof(zebra_fec_t)); - if (!fec) - return NULL; + if (!fec) { + fec = XCALLOC(MTYPE_FEC, sizeof(zebra_fec_t)); + if (!fec) + return NULL; - rn->info = fec; - fec->rn = rn; - fec->label = label; - fec->client_list = list_new(); - } - else - route_unlock_node (rn); /* for the route_node_get */ + rn->info = fec; + fec->rn = rn; + fec->label = label; + fec->client_list = list_new(); + } else + route_unlock_node(rn); /* for the route_node_get */ - fec->label_index = label_index; - fec->flags = flags; + fec->label_index = label_index; + fec->flags = flags; - return fec; + return fec; } /* @@ -607,37 +553,34 @@ fec_add (struct route_table *table, struct prefix *p, * a FEC and no binding exists or when the binding is deleted and there * are no registered clients. */ -static int -fec_del (zebra_fec_t *fec) +static int fec_del(zebra_fec_t *fec) { - list_free (fec->client_list); - fec->rn->info = NULL; - route_unlock_node (fec->rn); - XFREE (MTYPE_FEC, fec); - return 0; + list_free(fec->client_list); + fec->rn->info = NULL; + route_unlock_node(fec->rn); + XFREE(MTYPE_FEC, fec); + return 0; } /* * Hash function for label. */ -static unsigned int -label_hash (void *p) +static unsigned int label_hash(void *p) { - const zebra_ile_t *ile = p; + const zebra_ile_t *ile = p; - return (jhash_1word(ile->in_label, 0)); + return (jhash_1word(ile->in_label, 0)); } /* * Compare 2 LSP hash entries based on in-label. */ -static int -label_cmp (const void *p1, const void *p2) +static int label_cmp(const void *p1, const void *p2) { - const zebra_ile_t *ile1 = p1; - const zebra_ile_t *ile2 = p2; + const zebra_ile_t *ile1 = p1; + const zebra_ile_t *ile2 = p2; - return (ile1->in_label == ile2->in_label); + return (ile1->in_label == ile2->in_label); } /* @@ -645,50 +588,49 @@ label_cmp (const void *p1, const void *p2) * the passed flag. * NOTE: Looking only for connected routes right now. */ -static int -nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop) +static int nhlfe_nexthop_active_ipv4(zebra_nhlfe_t *nhlfe, + struct nexthop *nexthop) { - struct route_table *table; - struct prefix_ipv4 p; - struct route_node *rn; - struct route_entry *match; - struct nexthop *match_nh; - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); - if (!table) - return 0; + struct route_table *table; + struct prefix_ipv4 p; + struct route_node *rn; + struct route_entry *match; + struct nexthop *match_nh; - /* Lookup nexthop in IPv4 routing table. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = IPV4_MAX_PREFIXLEN; - p.prefix = nexthop->gate.ipv4; + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (!table) + return 0; - rn = route_node_match (table, (struct prefix *) &p); - if (!rn) - return 0; + /* Lookup nexthop in IPv4 routing table. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = IPV4_MAX_PREFIXLEN; + p.prefix = nexthop->gate.ipv4; - route_unlock_node (rn); + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + return 0; - /* Locate a valid connected route. */ - RNODE_FOREACH_RE (rn, match) - { - if (CHECK_FLAG (match->status, ROUTE_ENTRY_REMOVED) || - !CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - continue; + route_unlock_node(rn); - for (match_nh = match->nexthop; match_nh; match_nh = match_nh->next) + /* Locate a valid connected route. */ + RNODE_FOREACH_RE(rn, match) { - if (match->type == ZEBRA_ROUTE_CONNECT || - nexthop->ifindex == match_nh->ifindex) - { - nexthop->ifindex = match_nh->ifindex; - return 1; - } + if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED) + || !CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED)) + continue; + + for (match_nh = match->nexthop; match_nh; + match_nh = match_nh->next) { + if (match->type == ZEBRA_ROUTE_CONNECT + || nexthop->ifindex == match_nh->ifindex) { + nexthop->ifindex = match_nh->ifindex; + return 1; + } + } } - } - return 0; + return 0; } @@ -697,44 +639,44 @@ nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop) * the passed flag. * NOTE: Looking only for connected routes right now. */ -static int -nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop) +static int nhlfe_nexthop_active_ipv6(zebra_nhlfe_t *nhlfe, + struct nexthop *nexthop) { - struct route_table *table; - struct prefix_ipv6 p; - struct route_node *rn; - struct route_entry *match; + struct route_table *table; + struct prefix_ipv6 p; + struct route_node *rn; + struct route_entry *match; - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); - if (!table) - return 0; + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + if (!table) + return 0; - /* Lookup nexthop in IPv6 routing table. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_PREFIXLEN; - p.prefix = nexthop->gate.ipv6; + /* Lookup nexthop in IPv6 routing table. */ + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_PREFIXLEN; + p.prefix = nexthop->gate.ipv6; - rn = route_node_match (table, (struct prefix *) &p); - if (!rn) - return 0; + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + return 0; - route_unlock_node (rn); + route_unlock_node(rn); - /* Locate a valid connected route. */ - RNODE_FOREACH_RE (rn, match) - { - if ((match->type == ZEBRA_ROUTE_CONNECT) && - !CHECK_FLAG (match->status, ROUTE_ENTRY_REMOVED) && - CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - break; - } + /* Locate a valid connected route. */ + RNODE_FOREACH_RE(rn, match) + { + if ((match->type == ZEBRA_ROUTE_CONNECT) + && !CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED) + && CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED)) + break; + } - if (!match || !match->nexthop) - return 0; + if (!match || !match->nexthop) + return 0; - nexthop->ifindex = match->nexthop->ifindex; - return 1; + nexthop->ifindex = match->nexthop->ifindex; + return 1; } @@ -743,57 +685,52 @@ nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop) * or not. * NOTE: Each NHLFE points to only 1 nexthop. */ -static int -nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe) -{ - struct nexthop *nexthop; - struct interface *ifp; - - nexthop = nhlfe->nexthop; - if (!nexthop) // unexpected - return 0; - - /* Check on nexthop based on type. */ - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nhlfe_nexthop_active_ipv4 (nhlfe, nexthop)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - - case NEXTHOP_TYPE_IPV6: - if (nhlfe_nexthop_active_ipv6 (nhlfe, nexthop)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6)) - { - ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); - if (ifp && if_is_operative(ifp)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - } - else - { - if (nhlfe_nexthop_active_ipv6 (nhlfe, nexthop)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - } - break; - - default: - break; - } - - return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); +static int nhlfe_nexthop_active(zebra_nhlfe_t *nhlfe) +{ + struct nexthop *nexthop; + struct interface *ifp; + + nexthop = nhlfe->nexthop; + if (!nexthop) // unexpected + return 0; + + /* Check on nexthop based on type. */ + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nhlfe_nexthop_active_ipv4(nhlfe, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + + case NEXTHOP_TYPE_IPV6: + if (nhlfe_nexthop_active_ipv6(nhlfe, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (IN6_IS_ADDR_LINKLOCAL(&nexthop->gate.ipv6)) { + ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT); + if (ifp && if_is_operative(ifp)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } else { + if (nhlfe_nexthop_active_ipv6(nhlfe, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } + break; + + default: + break; + } + + return CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); } /* @@ -802,783 +739,739 @@ nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe) * marked. This is invoked when an LSP scheduled for processing (due * to some change) is examined. */ -static void -lsp_select_best_nhlfe (zebra_lsp_t *lsp) -{ - zebra_nhlfe_t *nhlfe; - zebra_nhlfe_t *best; - struct nexthop *nexthop; - int changed = 0; - - if (!lsp) - return; - - best = NULL; - lsp->num_ecmp = 0; - UNSET_FLAG (lsp->flags, LSP_FLAG_CHANGED); - - /* - * First compute the best path, after checking nexthop status. We are only - * concerned with non-deleted NHLFEs. - */ - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - /* Clear selection flags. */ - UNSET_FLAG (nhlfe->flags, - (NHLFE_FLAG_SELECTED | NHLFE_FLAG_MULTIPATH)); - - if (!CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED) && - nhlfe_nexthop_active (nhlfe)) - { - if (!best || (nhlfe->distance < best->distance)) - best = nhlfe; - } - } - - lsp->best_nhlfe = best; - if (!lsp->best_nhlfe) - return; - - /* Mark best NHLFE as selected. */ - SET_FLAG (lsp->best_nhlfe->flags, NHLFE_FLAG_SELECTED); - - /* - * If best path exists, see if there is ECMP. While doing this, note if a - * new (uninstalled) NHLFE has been selected, an installed entry that is - * still selected has a change or an installed entry is to be removed. - */ - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - int nh_chg, nh_sel, nh_inst; - - nexthop = nhlfe->nexthop; - if (!nexthop) // unexpected - continue; - - if (!CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) && - (nhlfe->distance == lsp->best_nhlfe->distance)) - { - SET_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED); - SET_FLAG (nhlfe->flags, NHLFE_FLAG_MULTIPATH); - lsp->num_ecmp++; - } - - if (CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED) && - !changed) - { - nh_chg = CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - nh_sel = CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED); - nh_inst = CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - - if ((nh_sel && !nh_inst) || - (nh_sel && nh_inst && nh_chg) || - (nh_inst && !nh_sel)) - changed = 1; - } - - /* We have finished examining, clear changed flag. */ - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - } - - if (changed) - SET_FLAG (lsp->flags, LSP_FLAG_CHANGED); +static void lsp_select_best_nhlfe(zebra_lsp_t *lsp) +{ + zebra_nhlfe_t *nhlfe; + zebra_nhlfe_t *best; + struct nexthop *nexthop; + int changed = 0; + + if (!lsp) + return; + + best = NULL; + lsp->num_ecmp = 0; + UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); + + /* + * First compute the best path, after checking nexthop status. We are + * only + * concerned with non-deleted NHLFEs. + */ + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + /* Clear selection flags. */ + UNSET_FLAG(nhlfe->flags, + (NHLFE_FLAG_SELECTED | NHLFE_FLAG_MULTIPATH)); + + if (!CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED) + && nhlfe_nexthop_active(nhlfe)) { + if (!best || (nhlfe->distance < best->distance)) + best = nhlfe; + } + } + + lsp->best_nhlfe = best; + if (!lsp->best_nhlfe) + return; + + /* Mark best NHLFE as selected. */ + SET_FLAG(lsp->best_nhlfe->flags, NHLFE_FLAG_SELECTED); + + /* + * If best path exists, see if there is ECMP. While doing this, note if + * a + * new (uninstalled) NHLFE has been selected, an installed entry that is + * still selected has a change or an installed entry is to be removed. + */ + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + int nh_chg, nh_sel, nh_inst; + + nexthop = nhlfe->nexthop; + if (!nexthop) // unexpected + continue; + + if (!CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED) + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE) + && (nhlfe->distance == lsp->best_nhlfe->distance)) { + SET_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_MULTIPATH); + lsp->num_ecmp++; + } + + if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED) && !changed) { + nh_chg = CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + nh_sel = CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED); + nh_inst = + CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + + if ((nh_sel && !nh_inst) + || (nh_sel && nh_inst && nh_chg) + || (nh_inst && !nh_sel)) + changed = 1; + } + + /* We have finished examining, clear changed flag. */ + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + } + + if (changed) + SET_FLAG(lsp->flags, LSP_FLAG_CHANGED); } /* * Delete LSP forwarding entry from kernel, if installed. Called upon * process exit. */ -static void -lsp_uninstall_from_kernel (struct hash_backet *backet, void *ctxt) +static void lsp_uninstall_from_kernel(struct hash_backet *backet, void *ctxt) { - zebra_lsp_t *lsp; + zebra_lsp_t *lsp; - lsp = (zebra_lsp_t *) backet->data; - if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) - kernel_del_lsp (lsp); + lsp = (zebra_lsp_t *)backet->data; + if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) + kernel_del_lsp(lsp); } /* * Schedule LSP forwarding entry for processing. Called upon changes * that may impact LSPs such as nexthop / connected route changes. */ -static void -lsp_schedule (struct hash_backet *backet, void *ctxt) +static void lsp_schedule(struct hash_backet *backet, void *ctxt) { - zebra_lsp_t *lsp; + zebra_lsp_t *lsp; - lsp = (zebra_lsp_t *) backet->data; - lsp_processq_add (lsp); + lsp = (zebra_lsp_t *)backet->data; + lsp_processq_add(lsp); } /* * Process a LSP entry that is in the queue. Recalculate best NHLFE and * any multipaths and update or delete from the kernel, as needed. */ -static wq_item_status -lsp_process (struct work_queue *wq, void *data) -{ - zebra_lsp_t *lsp; - zebra_nhlfe_t *oldbest, *newbest; - char buf[BUFSIZ], buf2[BUFSIZ]; - struct zebra_vrf *zvrf = vrf_info_lookup (VRF_DEFAULT); - - lsp = (zebra_lsp_t *)data; - if (!lsp) // unexpected - return WQ_SUCCESS; - - oldbest = lsp->best_nhlfe; - - /* Select best NHLFE(s) */ - lsp_select_best_nhlfe (lsp); - - newbest = lsp->best_nhlfe; - - if (IS_ZEBRA_DEBUG_MPLS) - { - if (oldbest) - nhlfe2str (oldbest, buf, BUFSIZ); - if (newbest) - nhlfe2str (newbest, buf2, BUFSIZ); - zlog_debug ("Process LSP in-label %u oldbest %s newbest %s " - "flags 0x%x ecmp# %d", - lsp->ile.in_label, oldbest ? buf : "NULL", - newbest ? buf2 : "NULL", lsp->flags, lsp->num_ecmp); - } - - if (!CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED)) - { - /* Not already installed */ - if (newbest) - { - kernel_add_lsp (lsp); - zvrf->lsp_installs++; - } - } - else - { - /* Installed, may need an update and/or delete. */ - if (!newbest) - { - kernel_del_lsp (lsp); - zvrf->lsp_removals++; - } - else if (CHECK_FLAG (lsp->flags, LSP_FLAG_CHANGED)) - { - kernel_upd_lsp (lsp); - zvrf->lsp_installs++; - } - } - - return WQ_SUCCESS; +static wq_item_status lsp_process(struct work_queue *wq, void *data) +{ + zebra_lsp_t *lsp; + zebra_nhlfe_t *oldbest, *newbest; + char buf[BUFSIZ], buf2[BUFSIZ]; + struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT); + + lsp = (zebra_lsp_t *)data; + if (!lsp) // unexpected + return WQ_SUCCESS; + + oldbest = lsp->best_nhlfe; + + /* Select best NHLFE(s) */ + lsp_select_best_nhlfe(lsp); + + newbest = lsp->best_nhlfe; + + if (IS_ZEBRA_DEBUG_MPLS) { + if (oldbest) + nhlfe2str(oldbest, buf, BUFSIZ); + if (newbest) + nhlfe2str(newbest, buf2, BUFSIZ); + zlog_debug( + "Process LSP in-label %u oldbest %s newbest %s " + "flags 0x%x ecmp# %d", + lsp->ile.in_label, oldbest ? buf : "NULL", + newbest ? buf2 : "NULL", lsp->flags, lsp->num_ecmp); + } + + if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) { + /* Not already installed */ + if (newbest) { + kernel_add_lsp(lsp); + zvrf->lsp_installs++; + } + } else { + /* Installed, may need an update and/or delete. */ + if (!newbest) { + kernel_del_lsp(lsp); + zvrf->lsp_removals++; + } else if (CHECK_FLAG(lsp->flags, LSP_FLAG_CHANGED)) { + kernel_upd_lsp(lsp); + zvrf->lsp_installs++; + } + } + + return WQ_SUCCESS; } /* * Callback upon processing completion of a LSP forwarding entry. */ -static void -lsp_processq_del (struct work_queue *wq, void *data) +static void lsp_processq_del(struct work_queue *wq, void *data) { - struct zebra_vrf *zvrf; - zebra_lsp_t *lsp; - struct hash *lsp_table; - zebra_nhlfe_t *nhlfe, *nhlfe_next; + struct zebra_vrf *zvrf; + zebra_lsp_t *lsp; + struct hash *lsp_table; + zebra_nhlfe_t *nhlfe, *nhlfe_next; - zvrf = vrf_info_lookup(VRF_DEFAULT); - assert (zvrf); + zvrf = vrf_info_lookup(VRF_DEFAULT); + assert(zvrf); - lsp_table = zvrf->lsp_table; - if (!lsp_table) // unexpected - return; + lsp_table = zvrf->lsp_table; + if (!lsp_table) // unexpected + return; - lsp = (zebra_lsp_t *)data; - if (!lsp) // unexpected - return; + lsp = (zebra_lsp_t *)data; + if (!lsp) // unexpected + return; - /* Clear flag, remove any NHLFEs marked for deletion. If no NHLFEs exist, - * delete LSP entry also. - */ - UNSET_FLAG (lsp->flags, LSP_FLAG_SCHEDULED); + /* Clear flag, remove any NHLFEs marked for deletion. If no NHLFEs + * exist, + * delete LSP entry also. + */ + UNSET_FLAG(lsp->flags, LSP_FLAG_SCHEDULED); - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) - { - nhlfe_next = nhlfe->next; - if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED)) - nhlfe_del (nhlfe); - } + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) { + nhlfe_next = nhlfe->next; + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED)) + nhlfe_del(nhlfe); + } - if (!lsp->nhlfe_list) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Free LSP in-label %u flags 0x%x", - lsp->ile.in_label, lsp->flags); + if (!lsp->nhlfe_list) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Free LSP in-label %u flags 0x%x", + lsp->ile.in_label, lsp->flags); - lsp = hash_release(lsp_table, &lsp->ile); - if (lsp) - XFREE(MTYPE_LSP, lsp); - } + lsp = hash_release(lsp_table, &lsp->ile); + if (lsp) + XFREE(MTYPE_LSP, lsp); + } } /* * Callback upon finishing the processing of all scheduled * LSP forwarding entries. */ -static void -lsp_processq_complete (struct work_queue *wq) +static void lsp_processq_complete(struct work_queue *wq) { - /* Nothing to do for now. */ + /* Nothing to do for now. */ } /* * Add LSP forwarding entry to queue for subsequent processing. */ -static int -lsp_processq_add (zebra_lsp_t *lsp) +static int lsp_processq_add(zebra_lsp_t *lsp) { - /* If already scheduled, exit. */ - if (CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED)) - return 0; + /* If already scheduled, exit. */ + if (CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED)) + return 0; - if (zebrad.lsp_process_q == NULL) - { - zlog_err ("%s: work_queue does not exist!", __func__); - return -1; - } + if (zebrad.lsp_process_q == NULL) { + zlog_err("%s: work_queue does not exist!", __func__); + return -1; + } - work_queue_add (zebrad.lsp_process_q, lsp); - SET_FLAG (lsp->flags, LSP_FLAG_SCHEDULED); - return 0; + work_queue_add(zebrad.lsp_process_q, lsp); + SET_FLAG(lsp->flags, LSP_FLAG_SCHEDULED); + return 0; } /* * Callback to allocate LSP forwarding table entry. */ -static void * -lsp_alloc (void *p) +static void *lsp_alloc(void *p) { - const zebra_ile_t *ile = p; - zebra_lsp_t *lsp; + const zebra_ile_t *ile = p; + zebra_lsp_t *lsp; - lsp = XCALLOC (MTYPE_LSP, sizeof(zebra_lsp_t)); - lsp->ile = *ile; + lsp = XCALLOC(MTYPE_LSP, sizeof(zebra_lsp_t)); + lsp->ile = *ile; - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Alloc LSP in-label %u", lsp->ile.in_label); + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Alloc LSP in-label %u", lsp->ile.in_label); - return ((void *)lsp); + return ((void *)lsp); } /* * Create printable string for NHLFE entry. */ -static char * -nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size) +static char *nhlfe2str(zebra_nhlfe_t *nhlfe, char *buf, int size) { - struct nexthop *nexthop; + struct nexthop *nexthop; - buf[0] = '\0'; - nexthop = nhlfe->nexthop; - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - inet_ntop (AF_INET, &nexthop->gate.ipv4, buf, size); - break; - case NEXTHOP_TYPE_IPV6: - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, size); - break; - default: - break; - } + buf[0] = '\0'; + nexthop = nhlfe->nexthop; + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, size); + break; + case NEXTHOP_TYPE_IPV6: + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, size); + break; + default: + break; + } - return buf; + return buf; } /* * Check if NHLFE matches with search info passed. */ -static int -nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex) +static int nhlfe_nhop_match(zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex) { - struct nexthop *nhop; - int cmp = 1; + struct nexthop *nhop; + int cmp = 1; - nhop = nhlfe->nexthop; - if (!nhop) - return 1; + nhop = nhlfe->nexthop; + if (!nhop) + return 1; - if (nhop->type != gtype) - return 1; + if (nhop->type != gtype) + return 1; - switch (nhop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - cmp = memcmp(&(nhop->gate.ipv4), &(gate->ipv4), - sizeof(struct in_addr)); - if (!cmp && nhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - cmp = !(nhop->ifindex == ifindex); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - cmp = memcmp(&(nhop->gate.ipv6), &(gate->ipv6), - sizeof(struct in6_addr)); - if (!cmp && nhop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - cmp = !(nhop->ifindex == ifindex); - break; - default: - break; - } + switch (nhop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + cmp = memcmp(&(nhop->gate.ipv4), &(gate->ipv4), + sizeof(struct in_addr)); + if (!cmp && nhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) + cmp = !(nhop->ifindex == ifindex); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + cmp = memcmp(&(nhop->gate.ipv6), &(gate->ipv6), + sizeof(struct in6_addr)); + if (!cmp && nhop->type == NEXTHOP_TYPE_IPV6_IFINDEX) + cmp = !(nhop->ifindex == ifindex); + break; + default: + break; + } - return cmp; + return cmp; } /* * Locate NHLFE that matches with passed info. */ -static zebra_nhlfe_t * -nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex) +static zebra_nhlfe_t *nhlfe_find(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex) { - zebra_nhlfe_t *nhlfe; + zebra_nhlfe_t *nhlfe; - if (!lsp) - return NULL; + if (!lsp) + return NULL; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - if (nhlfe->type != lsp_type) - continue; - if (!nhlfe_nhop_match (nhlfe, gtype, gate, ifindex)) - break; - } + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + if (nhlfe->type != lsp_type) + continue; + if (!nhlfe_nhop_match(nhlfe, gtype, gate, ifindex)) + break; + } - return nhlfe; + return nhlfe; } /* * Add NHLFE. Base entry must have been created and duplicate * check done. */ -static zebra_nhlfe_t * -nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex, mpls_label_t out_label) -{ - zebra_nhlfe_t *nhlfe; - struct nexthop *nexthop; - - if (!lsp) - return NULL; - - nhlfe = XCALLOC(MTYPE_NHLFE, sizeof(zebra_nhlfe_t)); - if (!nhlfe) - return NULL; - - nhlfe->lsp = lsp; - nhlfe->type = lsp_type; - nhlfe->distance = lsp_distance (lsp_type); - - nexthop = nexthop_new(); - if (!nexthop) - { - XFREE (MTYPE_NHLFE, nhlfe); - return NULL; - } - nexthop_add_labels (nexthop, lsp_type, 1, &out_label); - - nexthop->type = gtype; - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - nexthop->gate.ipv4 = gate->ipv4; - if (ifindex) - nexthop->ifindex = ifindex; - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - nexthop->gate.ipv6 = gate->ipv6; - if (ifindex) - nexthop->ifindex = ifindex; - break; - default: - nexthop_free(nexthop); - XFREE (MTYPE_NHLFE, nhlfe); - return NULL; - break; - } - - nhlfe->nexthop = nexthop; - if (lsp->nhlfe_list) - lsp->nhlfe_list->prev = nhlfe; - nhlfe->next = lsp->nhlfe_list; - lsp->nhlfe_list = nhlfe; - - return nhlfe; +static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex, mpls_label_t out_label) +{ + zebra_nhlfe_t *nhlfe; + struct nexthop *nexthop; + + if (!lsp) + return NULL; + + nhlfe = XCALLOC(MTYPE_NHLFE, sizeof(zebra_nhlfe_t)); + if (!nhlfe) + return NULL; + + nhlfe->lsp = lsp; + nhlfe->type = lsp_type; + nhlfe->distance = lsp_distance(lsp_type); + + nexthop = nexthop_new(); + if (!nexthop) { + XFREE(MTYPE_NHLFE, nhlfe); + return NULL; + } + nexthop_add_labels(nexthop, lsp_type, 1, &out_label); + + nexthop->type = gtype; + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + nexthop->gate.ipv4 = gate->ipv4; + if (ifindex) + nexthop->ifindex = ifindex; + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + nexthop->gate.ipv6 = gate->ipv6; + if (ifindex) + nexthop->ifindex = ifindex; + break; + default: + nexthop_free(nexthop); + XFREE(MTYPE_NHLFE, nhlfe); + return NULL; + break; + } + + nhlfe->nexthop = nexthop; + if (lsp->nhlfe_list) + lsp->nhlfe_list->prev = nhlfe; + nhlfe->next = lsp->nhlfe_list; + lsp->nhlfe_list = nhlfe; + + return nhlfe; } /* * Delete NHLFE. Entry must be present on list. */ -static int -nhlfe_del (zebra_nhlfe_t *nhlfe) +static int nhlfe_del(zebra_nhlfe_t *nhlfe) { - zebra_lsp_t *lsp; + zebra_lsp_t *lsp; - if (!nhlfe) - return -1; + if (!nhlfe) + return -1; - lsp = nhlfe->lsp; - if (!lsp) - return -1; + lsp = nhlfe->lsp; + if (!lsp) + return -1; - /* Free nexthop. */ - if (nhlfe->nexthop) - nexthop_free(nhlfe->nexthop); + /* Free nexthop. */ + if (nhlfe->nexthop) + nexthop_free(nhlfe->nexthop); - /* Unlink from LSP */ - if (nhlfe->next) - nhlfe->next->prev = nhlfe->prev; - if (nhlfe->prev) - nhlfe->prev->next = nhlfe->next; - else - lsp->nhlfe_list = nhlfe->next; + /* Unlink from LSP */ + if (nhlfe->next) + nhlfe->next->prev = nhlfe->prev; + if (nhlfe->prev) + nhlfe->prev->next = nhlfe->next; + else + lsp->nhlfe_list = nhlfe->next; - if (nhlfe == lsp->best_nhlfe) - lsp->best_nhlfe = NULL; + if (nhlfe == lsp->best_nhlfe) + lsp->best_nhlfe = NULL; - XFREE (MTYPE_NHLFE, nhlfe); + XFREE(MTYPE_NHLFE, nhlfe); - return 0; + return 0; } /* * Update label for NHLFE entry. */ -static void -nhlfe_out_label_update (zebra_nhlfe_t *nhlfe, struct nexthop_label *nh_label) -{ - nhlfe->nexthop->nh_label->label[0] = nh_label->label[0]; -} - -static int -mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp, - enum lsp_types_t type) -{ - zebra_nhlfe_t *nhlfe, *nhlfe_next; - int schedule_lsp = 0; - char buf[BUFSIZ]; - - /* Mark NHLFEs for delete or directly delete, as appropriate. */ - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) - { - nhlfe_next = nhlfe->next; - - /* Skip non-static NHLFEs */ - if (nhlfe->type != type) - continue; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x", - lsp->ile.in_label, type, buf, nhlfe->flags); - } - - if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED); - schedule_lsp = 1; - } - else - { - nhlfe_del (nhlfe); - } - } - - /* Queue LSP for processing, if needed, else delete. */ - if (schedule_lsp) - { - if (lsp_processq_add (lsp)) - return -1; - } - else if (!lsp->nhlfe_list && - !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Free LSP in-label %u flags 0x%x", - lsp->ile.in_label, lsp->flags); - - lsp = hash_release(lsp_table, &lsp->ile); - if (lsp) - XFREE(MTYPE_LSP, lsp); - } - - return 0; +static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe, + struct nexthop_label *nh_label) +{ + nhlfe->nexthop->nh_label->label[0] = nh_label->label[0]; +} + +static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp, + enum lsp_types_t type) +{ + zebra_nhlfe_t *nhlfe, *nhlfe_next; + int schedule_lsp = 0; + char buf[BUFSIZ]; + + /* Mark NHLFEs for delete or directly delete, as appropriate. */ + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) { + nhlfe_next = nhlfe->next; + + /* Skip non-static NHLFEs */ + if (nhlfe->type != type) + continue; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "Del LSP in-label %u type %d nexthop %s flags 0x%x", + lsp->ile.in_label, type, buf, nhlfe->flags); + } + + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) { + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); + schedule_lsp = 1; + } else { + nhlfe_del(nhlfe); + } + } + + /* Queue LSP for processing, if needed, else delete. */ + if (schedule_lsp) { + if (lsp_processq_add(lsp)) + return -1; + } else if (!lsp->nhlfe_list + && !CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Free LSP in-label %u flags 0x%x", + lsp->ile.in_label, lsp->flags); + + lsp = hash_release(lsp_table, &lsp->ile); + if (lsp) + XFREE(MTYPE_LSP, lsp); + } + + return 0; } /* * Uninstall all static NHLFEs for a particular LSP forwarding entry. * If no other NHLFEs exist, the entry would be deleted. */ -static int -mpls_static_lsp_uninstall_all (struct zebra_vrf *zvrf, mpls_label_t in_label) +static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf, + mpls_label_t in_label) { - struct hash *lsp_table; - zebra_ile_t tmp_ile; - zebra_lsp_t *lsp; + struct hash *lsp_table; + zebra_ile_t tmp_ile; + zebra_lsp_t *lsp; - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return -1; + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return -1; - /* If entry is not present, exit. */ - tmp_ile.in_label = in_label; - lsp = hash_lookup (lsp_table, &tmp_ile); - if (!lsp || !lsp->nhlfe_list) - return 0; + /* If entry is not present, exit. */ + tmp_ile.in_label = in_label; + lsp = hash_lookup(lsp_table, &tmp_ile); + if (!lsp || !lsp->nhlfe_list) + return 0; - return mpls_lsp_uninstall_all (lsp_table, lsp, ZEBRA_LSP_STATIC); + return mpls_lsp_uninstall_all(lsp_table, lsp, ZEBRA_LSP_STATIC); } -static json_object * -nhlfe_json (zebra_nhlfe_t *nhlfe) +static json_object *nhlfe_json(zebra_nhlfe_t *nhlfe) { - char buf[BUFSIZ]; - json_object *json_nhlfe = NULL; - struct nexthop *nexthop = nhlfe->nexthop; + char buf[BUFSIZ]; + json_object *json_nhlfe = NULL; + struct nexthop *nexthop = nhlfe->nexthop; - json_nhlfe = json_object_new_object(); - json_object_string_add(json_nhlfe, "type", nhlfe_type2str(nhlfe->type)); - json_object_int_add(json_nhlfe, "outLabel", nexthop->nh_label->label[0]); - json_object_int_add(json_nhlfe, "distance", nhlfe->distance); + json_nhlfe = json_object_new_object(); + json_object_string_add(json_nhlfe, "type", nhlfe_type2str(nhlfe->type)); + json_object_int_add(json_nhlfe, "outLabel", + nexthop->nh_label->label[0]); + json_object_int_add(json_nhlfe, "distance", nhlfe->distance); - if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED)) - json_object_boolean_true_add(json_nhlfe, "installed"); + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) + json_object_boolean_true_add(json_nhlfe, "installed"); - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - json_object_string_add(json_nhlfe, "nexthop", - inet_ntoa (nexthop->gate.ipv4)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - json_object_string_add(json_nhlfe, "nexthop", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); - - if (nexthop->ifindex) - json_object_string_add(json_nhlfe, "interface", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT)); - break; - default: - break; - } - return json_nhlfe; + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + json_object_string_add(json_nhlfe, "nexthop", + inet_ntoa(nexthop->gate.ipv4)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + json_object_string_add( + json_nhlfe, "nexthop", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); + + if (nexthop->ifindex) + json_object_string_add( + json_nhlfe, "interface", + ifindex2ifname(nexthop->ifindex, VRF_DEFAULT)); + break; + default: + break; + } + return json_nhlfe; } /* * Print the NHLFE for a LSP forwarding entry. */ -static void -nhlfe_print (zebra_nhlfe_t *nhlfe, struct vty *vty) -{ - struct nexthop *nexthop; - char buf[BUFSIZ]; - - nexthop = nhlfe->nexthop; - if (!nexthop || !nexthop->nh_label) // unexpected - return; - - vty_out (vty, " type: %s remote label: %s distance: %d\n", - nhlfe_type2str(nhlfe->type), - label2str(nexthop->nh_label->label[0], buf, BUFSIZ), - nhlfe->distance); - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); - if (nexthop->ifindex) - vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out (vty, " via %s", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); - if (nexthop->ifindex) - vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT)); - break; - default: - break; - } - vty_out(vty, "%s", CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) ? - " (installed)" : ""); - vty_out (vty, "\n"); +static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty) +{ + struct nexthop *nexthop; + char buf[BUFSIZ]; + + nexthop = nhlfe->nexthop; + if (!nexthop || !nexthop->nh_label) // unexpected + return; + + vty_out(vty, " type: %s remote label: %s distance: %d\n", + nhlfe_type2str(nhlfe->type), + label2str(nexthop->nh_label->label[0], buf, BUFSIZ), + nhlfe->distance); + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4)); + if (nexthop->ifindex) + vty_out(vty, " dev %s", + ifindex2ifname(nexthop->ifindex, VRF_DEFAULT)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, " via %s", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); + if (nexthop->ifindex) + vty_out(vty, " dev %s", + ifindex2ifname(nexthop->ifindex, VRF_DEFAULT)); + break; + default: + break; + } + vty_out(vty, "%s", + CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) ? " (installed)" + : ""); + vty_out(vty, "\n"); } /* * Print an LSP forwarding entry. */ -static void -lsp_print (zebra_lsp_t *lsp, void *ctxt) +static void lsp_print(zebra_lsp_t *lsp, void *ctxt) { - zebra_nhlfe_t *nhlfe; - struct vty *vty; + zebra_nhlfe_t *nhlfe; + struct vty *vty; - vty = (struct vty *) ctxt; + vty = (struct vty *)ctxt; - vty_out (vty, "Local label: %u%s\n", - lsp->ile.in_label, - CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED) ? " (installed)" : ""); + vty_out(vty, "Local label: %u%s\n", lsp->ile.in_label, + CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED) ? " (installed)" + : ""); - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - nhlfe_print (nhlfe, vty); + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) + nhlfe_print(nhlfe, vty); } /* * JSON objects for an LSP forwarding entry. */ -static json_object * -lsp_json (zebra_lsp_t *lsp) +static json_object *lsp_json(zebra_lsp_t *lsp) { - zebra_nhlfe_t *nhlfe = NULL; - json_object *json = json_object_new_object(); - json_object *json_nhlfe_list = json_object_new_array(); + zebra_nhlfe_t *nhlfe = NULL; + json_object *json = json_object_new_object(); + json_object *json_nhlfe_list = json_object_new_array(); - json_object_int_add(json, "inLabel", lsp->ile.in_label); + json_object_int_add(json, "inLabel", lsp->ile.in_label); - if (CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED)) - json_object_boolean_true_add(json, "installed"); + if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) + json_object_boolean_true_add(json, "installed"); - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - json_object_array_add(json_nhlfe_list, nhlfe_json(nhlfe)); + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) + json_object_array_add(json_nhlfe_list, nhlfe_json(nhlfe)); - json_object_object_add(json, "nexthops", json_nhlfe_list); - return json; + json_object_object_add(json, "nexthops", json_nhlfe_list); + return json; } /* Return a sorted linked list of the hash contents */ -static struct list * -hash_get_sorted_list (struct hash *hash, void *cmp) +static struct list *hash_get_sorted_list(struct hash *hash, void *cmp) { - unsigned int i; - struct hash_backet *hb; - struct list *sorted_list = list_new(); + unsigned int i; + struct hash_backet *hb; + struct list *sorted_list = list_new(); - sorted_list->cmp = (int (*)(void *, void *)) cmp; + sorted_list->cmp = (int (*)(void *, void *))cmp; - for (i = 0; i < hash->size; i++) - for (hb = hash->index[i]; hb; hb = hb->next) - listnode_add_sort(sorted_list, hb->data); + for (i = 0; i < hash->size; i++) + for (hb = hash->index[i]; hb; hb = hb->next) + listnode_add_sort(sorted_list, hb->data); - return sorted_list; + return sorted_list; } /* * Compare two LSPs based on their label values. */ -static int -lsp_cmp (zebra_lsp_t *lsp1, zebra_lsp_t *lsp2) +static int lsp_cmp(zebra_lsp_t *lsp1, zebra_lsp_t *lsp2) { - if (lsp1->ile.in_label < lsp2->ile.in_label) - return -1; + if (lsp1->ile.in_label < lsp2->ile.in_label) + return -1; - if (lsp1->ile.in_label > lsp2->ile.in_label) - return 1; + if (lsp1->ile.in_label > lsp2->ile.in_label) + return 1; - return 0; + return 0; } /* * Callback to allocate static LSP. */ -static void * -slsp_alloc (void *p) +static void *slsp_alloc(void *p) { - const zebra_ile_t *ile = p; - zebra_slsp_t *slsp; + const zebra_ile_t *ile = p; + zebra_slsp_t *slsp; - slsp = XCALLOC (MTYPE_SLSP, sizeof(zebra_slsp_t)); - slsp->ile = *ile; - return ((void *)slsp); + slsp = XCALLOC(MTYPE_SLSP, sizeof(zebra_slsp_t)); + slsp->ile = *ile; + return ((void *)slsp); } /* * Compare two static LSPs based on their label values. */ -static int -slsp_cmp (zebra_slsp_t *slsp1, zebra_slsp_t *slsp2) +static int slsp_cmp(zebra_slsp_t *slsp1, zebra_slsp_t *slsp2) { - if (slsp1->ile.in_label < slsp2->ile.in_label) - return -1; + if (slsp1->ile.in_label < slsp2->ile.in_label) + return -1; - if (slsp1->ile.in_label > slsp2->ile.in_label) - return 1; + if (slsp1->ile.in_label > slsp2->ile.in_label) + return 1; - return 0; + return 0; } /* * Check if static NHLFE matches with search info passed. */ -static int -snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex) +static int snhlfe_match(zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex) { - int cmp = 1; + int cmp = 1; - if (snhlfe->gtype != gtype) - return 1; + if (snhlfe->gtype != gtype) + return 1; - switch (snhlfe->gtype) - { - case NEXTHOP_TYPE_IPV4: - cmp = memcmp(&(snhlfe->gate.ipv4), &(gate->ipv4), - sizeof(struct in_addr)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - cmp = memcmp(&(snhlfe->gate.ipv6), &(gate->ipv6), - sizeof(struct in6_addr)); - if (!cmp && snhlfe->gtype == NEXTHOP_TYPE_IPV6_IFINDEX) - cmp = !(snhlfe->ifindex == ifindex); - break; - default: - break; - } + switch (snhlfe->gtype) { + case NEXTHOP_TYPE_IPV4: + cmp = memcmp(&(snhlfe->gate.ipv4), &(gate->ipv4), + sizeof(struct in_addr)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + cmp = memcmp(&(snhlfe->gate.ipv6), &(gate->ipv6), + sizeof(struct in6_addr)); + if (!cmp && snhlfe->gtype == NEXTHOP_TYPE_IPV6_IFINDEX) + cmp = !(snhlfe->ifindex == ifindex); + break; + default: + break; + } - return cmp; + return cmp; } /* * Locate static NHLFE that matches with passed info. */ -static zebra_snhlfe_t * -snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex) +static zebra_snhlfe_t *snhlfe_find(zebra_slsp_t *slsp, + enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex) { - zebra_snhlfe_t *snhlfe; + zebra_snhlfe_t *snhlfe; - if (!slsp) - return NULL; + if (!slsp) + return NULL; - for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe->next) - { - if (!snhlfe_match (snhlfe, gtype, gate, ifindex)) - break; - } + for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe->next) { + if (!snhlfe_match(snhlfe, gtype, gate, ifindex)) + break; + } - return snhlfe; + return snhlfe; } @@ -1586,144 +1479,136 @@ snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype, * Add static NHLFE. Base LSP config entry must have been created * and duplicate check done. */ -static zebra_snhlfe_t * -snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex, - mpls_label_t out_label) -{ - zebra_snhlfe_t *snhlfe; - - if (!slsp) - return NULL; - - snhlfe = XCALLOC(MTYPE_SNHLFE, sizeof(zebra_snhlfe_t)); - snhlfe->slsp = slsp; - snhlfe->out_label = out_label; - snhlfe->gtype = gtype; - switch (gtype) - { - case NEXTHOP_TYPE_IPV4: - snhlfe->gate.ipv4 = gate->ipv4; - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - snhlfe->gate.ipv6 = gate->ipv6; - if (ifindex) - snhlfe->ifindex = ifindex; - break; - default: - XFREE (MTYPE_SNHLFE, snhlfe); - return NULL; - } - - if (slsp->snhlfe_list) - slsp->snhlfe_list->prev = snhlfe; - snhlfe->next = slsp->snhlfe_list; - slsp->snhlfe_list = snhlfe; - - return snhlfe; +static zebra_snhlfe_t *snhlfe_add(zebra_slsp_t *slsp, + enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex, + mpls_label_t out_label) +{ + zebra_snhlfe_t *snhlfe; + + if (!slsp) + return NULL; + + snhlfe = XCALLOC(MTYPE_SNHLFE, sizeof(zebra_snhlfe_t)); + snhlfe->slsp = slsp; + snhlfe->out_label = out_label; + snhlfe->gtype = gtype; + switch (gtype) { + case NEXTHOP_TYPE_IPV4: + snhlfe->gate.ipv4 = gate->ipv4; + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + snhlfe->gate.ipv6 = gate->ipv6; + if (ifindex) + snhlfe->ifindex = ifindex; + break; + default: + XFREE(MTYPE_SNHLFE, snhlfe); + return NULL; + } + + if (slsp->snhlfe_list) + slsp->snhlfe_list->prev = snhlfe; + snhlfe->next = slsp->snhlfe_list; + slsp->snhlfe_list = snhlfe; + + return snhlfe; } /* * Delete static NHLFE. Entry must be present on list. */ -static int -snhlfe_del (zebra_snhlfe_t *snhlfe) +static int snhlfe_del(zebra_snhlfe_t *snhlfe) { - zebra_slsp_t *slsp; + zebra_slsp_t *slsp; - if (!snhlfe) - return -1; + if (!snhlfe) + return -1; - slsp = snhlfe->slsp; - if (!slsp) - return -1; + slsp = snhlfe->slsp; + if (!slsp) + return -1; - if (snhlfe->next) - snhlfe->next->prev = snhlfe->prev; - if (snhlfe->prev) - snhlfe->prev->next = snhlfe->next; - else - slsp->snhlfe_list = snhlfe->next; + if (snhlfe->next) + snhlfe->next->prev = snhlfe->prev; + if (snhlfe->prev) + snhlfe->prev->next = snhlfe->next; + else + slsp->snhlfe_list = snhlfe->next; - snhlfe->prev = snhlfe->next = NULL; - if (snhlfe->ifname) - XFREE (MTYPE_SNHLFE_IFNAME, snhlfe->ifname); - XFREE (MTYPE_SNHLFE, snhlfe); + snhlfe->prev = snhlfe->next = NULL; + if (snhlfe->ifname) + XFREE(MTYPE_SNHLFE_IFNAME, snhlfe->ifname); + XFREE(MTYPE_SNHLFE, snhlfe); - return 0; + return 0; } /* * Delete all static NHLFE entries for this LSP (in label). */ -static int -snhlfe_del_all (zebra_slsp_t *slsp) +static int snhlfe_del_all(zebra_slsp_t *slsp) { - zebra_snhlfe_t *snhlfe, *snhlfe_next; + zebra_snhlfe_t *snhlfe, *snhlfe_next; - if (!slsp) - return -1; + if (!slsp) + return -1; - for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe_next) - { - snhlfe_next = snhlfe->next; - snhlfe_del (snhlfe); - } + for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe_next) { + snhlfe_next = snhlfe->next; + snhlfe_del(snhlfe); + } - return 0; + return 0; } /* * Create printable string for NHLFE configuration. */ -static char * -snhlfe2str (zebra_snhlfe_t *snhlfe, char *buf, int size) +static char *snhlfe2str(zebra_snhlfe_t *snhlfe, char *buf, int size) { - buf[0] = '\0'; - switch (snhlfe->gtype) - { - case NEXTHOP_TYPE_IPV4: - inet_ntop (AF_INET, &snhlfe->gate.ipv4, buf, size); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - inet_ntop (AF_INET6, &snhlfe->gate.ipv6, buf, size); - if (snhlfe->ifindex) - strcat (buf, ifindex2ifname (snhlfe->ifindex, VRF_DEFAULT)); - break; - default: - break; - } + buf[0] = '\0'; + switch (snhlfe->gtype) { + case NEXTHOP_TYPE_IPV4: + inet_ntop(AF_INET, &snhlfe->gate.ipv4, buf, size); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + inet_ntop(AF_INET6, &snhlfe->gate.ipv6, buf, size); + if (snhlfe->ifindex) + strcat(buf, + ifindex2ifname(snhlfe->ifindex, VRF_DEFAULT)); + break; + default: + break; + } - return buf; + return buf; } /* * Initialize work queue for processing changed LSPs. */ -static int -mpls_processq_init (struct zebra_t *zebra) +static int mpls_processq_init(struct zebra_t *zebra) { - zebra->lsp_process_q = work_queue_new (zebra->master, "LSP processing"); - if (!zebra->lsp_process_q) - { - zlog_err ("%s: could not initialise work queue!", __func__); - return -1; - } + zebra->lsp_process_q = work_queue_new(zebra->master, "LSP processing"); + if (!zebra->lsp_process_q) { + zlog_err("%s: could not initialise work queue!", __func__); + return -1; + } - zebra->lsp_process_q->spec.workfunc = &lsp_process; - zebra->lsp_process_q->spec.del_item_data = &lsp_processq_del; - zebra->lsp_process_q->spec.errorfunc = NULL; - zebra->lsp_process_q->spec.completion_func = &lsp_processq_complete; - zebra->lsp_process_q->spec.max_retries = 0; - zebra->lsp_process_q->spec.hold = 10; + zebra->lsp_process_q->spec.workfunc = &lsp_process; + zebra->lsp_process_q->spec.del_item_data = &lsp_processq_del; + zebra->lsp_process_q->spec.errorfunc = NULL; + zebra->lsp_process_q->spec.completion_func = &lsp_processq_complete; + zebra->lsp_process_q->spec.max_retries = 0; + zebra->lsp_process_q->spec.hold = 10; - return 0; + return 0; } - /* Public functions */ /* @@ -1738,132 +1623,128 @@ mpls_processq_init (struct zebra_t *zebra) * -2 if a label was inside the reserved range (0-15) * -3 if the number of labels given exceeds MPLS_MAX_LABELS */ -int -mpls_str2label (const char *label_str, u_int8_t *num_labels, - mpls_label_t *labels) -{ - char *ostr; // copy of label string (start) - char *lstr; // copy of label string - char *nump; // pointer to next segment - char *endp; // end pointer - int i; // for iterating label_str - int rc; // return code - mpls_label_t pl[MPLS_MAX_LABELS]; // parsed labels - - /* labels to zero until we have a successful parse */ - ostr = lstr = XSTRDUP (MTYPE_TMP, label_str); - *num_labels = 0; - rc = 0; - - for (i = 0; i < MPLS_MAX_LABELS && lstr && !rc; i++) - { - nump = strsep (&lstr, "/"); - pl[i] = strtoul(nump, &endp, 10); - - /* format check */ - if (*endp != '\0') - rc = -1; - /* validity check */ - else if (!IS_MPLS_UNRESERVED_LABEL(pl[i])) - rc = -2; - } +int mpls_str2label(const char *label_str, u_int8_t *num_labels, + mpls_label_t *labels) +{ + char *ostr; // copy of label string (start) + char *lstr; // copy of label string + char *nump; // pointer to next segment + char *endp; // end pointer + int i; // for iterating label_str + int rc; // return code + mpls_label_t pl[MPLS_MAX_LABELS]; // parsed labels + + /* labels to zero until we have a successful parse */ + ostr = lstr = XSTRDUP(MTYPE_TMP, label_str); + *num_labels = 0; + rc = 0; + + for (i = 0; i < MPLS_MAX_LABELS && lstr && !rc; i++) { + nump = strsep(&lstr, "/"); + pl[i] = strtoul(nump, &endp, 10); + + /* format check */ + if (*endp != '\0') + rc = -1; + /* validity check */ + else if (!IS_MPLS_UNRESERVED_LABEL(pl[i])) + rc = -2; + } - /* excess labels */ - if (!rc && i == MPLS_MAX_LABELS && lstr) - rc = -3; + /* excess labels */ + if (!rc && i == MPLS_MAX_LABELS && lstr) + rc = -3; - if (!rc) - { - *num_labels = i; - memcpy (labels, pl, *num_labels * sizeof (mpls_label_t)); - } + if (!rc) { + *num_labels = i; + memcpy(labels, pl, *num_labels * sizeof(mpls_label_t)); + } - XFREE (MTYPE_TMP, ostr); + XFREE(MTYPE_TMP, ostr); - return rc; + return rc; } /* * Label to string conversion, labels in string separated by '/'. */ -char * -mpls_label2str (u_int8_t num_labels, mpls_label_t *labels, - char *buf, int len, int pretty) -{ - char *buf_ptr = buf; - buf[0] = '\0'; - - if (pretty) { - if (num_labels == 1) { - label2str(labels[0], buf, len); - } else if (num_labels == 2) { - label2str(labels[0], buf, len); - buf_ptr += strlen(buf); - - snprintf (buf_ptr, len, "/"); - buf_ptr++; - - label2str(labels[1], buf_ptr, len); - } - } else { - if (num_labels == 1) - snprintf (buf, len, "%u", labels[0]); - else if (num_labels == 2) - snprintf (buf, len, "%u/%u", labels[0], labels[1]); - } - return buf; +char *mpls_label2str(u_int8_t num_labels, mpls_label_t *labels, char *buf, + int len, int pretty) +{ + char *buf_ptr = buf; + buf[0] = '\0'; + + if (pretty) { + if (num_labels == 1) { + label2str(labels[0], buf, len); + } else if (num_labels == 2) { + label2str(labels[0], buf, len); + buf_ptr += strlen(buf); + + snprintf(buf_ptr, len, "/"); + buf_ptr++; + + label2str(labels[1], buf_ptr, len); + } + } else { + if (num_labels == 1) + snprintf(buf, len, "%u", labels[0]); + else if (num_labels == 2) + snprintf(buf, len, "%u/%u", labels[0], labels[1]); + } + return buf; } /* * Install dynamic LSP entry. */ -int -zebra_mpls_lsp_install (struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *re) +int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn, + struct route_entry *re) { - struct route_table *table; - zebra_fec_t *fec; + struct route_table *table; + zebra_fec_t *fec; - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))]; - if (!table) - return -1; + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))]; + if (!table) + return -1; - /* See if there is a configured label binding for this FEC. */ - fec = fec_find (table, &rn->p); - if (!fec || fec->label == MPLS_INVALID_LABEL) - return 0; + /* See if there is a configured label binding for this FEC. */ + fec = fec_find(table, &rn->p); + if (!fec || fec->label == MPLS_INVALID_LABEL) + return 0; - /* We cannot install a label forwarding entry if local label is the - * implicit-null label. - */ - if (fec->label == MPLS_IMP_NULL_LABEL) - return 0; + /* We cannot install a label forwarding entry if local label is the + * implicit-null label. + */ + if (fec->label == MPLS_IMP_NULL_LABEL) + return 0; - if (lsp_install (zvrf, fec->label, rn, re)) - return -1; + if (lsp_install(zvrf, fec->label, rn, re)) + return -1; - return 0; + return 0; } /* * Uninstall dynamic LSP entry, if any. */ -int -zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *re) +int zebra_mpls_lsp_uninstall(struct zebra_vrf *zvrf, struct route_node *rn, + struct route_entry *re) { - struct route_table *table; - zebra_fec_t *fec; + struct route_table *table; + zebra_fec_t *fec; - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))]; - if (!table) - return -1; + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))]; + if (!table) + return -1; - /* See if there is a configured label binding for this FEC. */ - fec = fec_find (table, &rn->p); - if (!fec || fec->label == MPLS_INVALID_LABEL) - return 0; + /* See if there is a configured label binding for this FEC. */ + fec = fec_find(table, &rn->p); + if (!fec || fec->label == MPLS_INVALID_LABEL) + return 0; - /* Uninstall always removes all dynamic NHLFEs. */ - return lsp_uninstall (zvrf, fec->label); + /* Uninstall always removes all dynamic NHLFEs. */ + return lsp_uninstall(zvrf, fec->label); } /* @@ -1874,91 +1755,85 @@ zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct * label from a locally configured label block (SRGB), if one exists and index * is acceptable. */ -int -zebra_mpls_fec_register (struct zebra_vrf *zvrf, struct prefix *p, - u_int32_t label_index, struct zserv *client) -{ - struct route_table *table; - zebra_fec_t *fec; - char buf[BUFSIZ]; - int new_client; - int label_change = 0; - u_int32_t old_label; - - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; - if (!table) - return -1; - - if (IS_ZEBRA_DEBUG_MPLS) - prefix2str(p, buf, BUFSIZ); - - /* Locate FEC */ - fec = fec_find (table, p); - if (!fec) - { - fec = fec_add (table, p, MPLS_INVALID_LABEL, 0, label_index); - if (!fec) - { - prefix2str(p, buf, BUFSIZ); - zlog_err("Failed to add FEC %s upon register, client %s", - buf, zebra_route_string(client->proto)); - return -1; - } - - old_label = MPLS_INVALID_LABEL; - new_client = 1; - } - else - { - /* Client may register same FEC with different label index. */ - new_client = (listnode_lookup(fec->client_list, client) == NULL); - if (!new_client && fec->label_index == label_index) - /* Duplicate register */ - return 0; - - /* Save current label, update label index */ - old_label = fec->label; - fec->label_index = label_index; - } - - if (new_client) - listnode_add (fec->client_list, client); - - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug("FEC %s Label Index %u %s by client %s", - buf, label_index, new_client ? "registered" : "updated", - zebra_route_string(client->proto)); - - /* If not a configured FEC, derive the local label (from label index) - * or reset it. - */ - if (!(fec->flags & FEC_FLAG_CONFIGURED)) - { - fec_derive_label_from_index (zvrf, fec); - - /* If no label change, exit. */ - if (fec->label == old_label) - return 0; - - label_change = 1; - } - - /* If new client or label change, update client and install or uninstall - * label forwarding entry as needed. - */ - /* Inform client of label, if needed. */ - if ((new_client && fec->label != MPLS_INVALID_LABEL) || - label_change) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Update client label %u", fec->label); - fec_send (fec, client); - } - - if (new_client || label_change) - return fec_change_update_lsp (zvrf, fec, old_label); - - return 0; +int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p, + u_int32_t label_index, struct zserv *client) +{ + struct route_table *table; + zebra_fec_t *fec; + char buf[BUFSIZ]; + int new_client; + int label_change = 0; + u_int32_t old_label; + + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; + if (!table) + return -1; + + if (IS_ZEBRA_DEBUG_MPLS) + prefix2str(p, buf, BUFSIZ); + + /* Locate FEC */ + fec = fec_find(table, p); + if (!fec) { + fec = fec_add(table, p, MPLS_INVALID_LABEL, 0, label_index); + if (!fec) { + prefix2str(p, buf, BUFSIZ); + zlog_err( + "Failed to add FEC %s upon register, client %s", + buf, zebra_route_string(client->proto)); + return -1; + } + + old_label = MPLS_INVALID_LABEL; + new_client = 1; + } else { + /* Client may register same FEC with different label index. */ + new_client = + (listnode_lookup(fec->client_list, client) == NULL); + if (!new_client && fec->label_index == label_index) + /* Duplicate register */ + return 0; + + /* Save current label, update label index */ + old_label = fec->label; + fec->label_index = label_index; + } + + if (new_client) + listnode_add(fec->client_list, client); + + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("FEC %s Label Index %u %s by client %s", buf, + label_index, new_client ? "registered" : "updated", + zebra_route_string(client->proto)); + + /* If not a configured FEC, derive the local label (from label index) + * or reset it. + */ + if (!(fec->flags & FEC_FLAG_CONFIGURED)) { + fec_derive_label_from_index(zvrf, fec); + + /* If no label change, exit. */ + if (fec->label == old_label) + return 0; + + label_change = 1; + } + + /* If new client or label change, update client and install or uninstall + * label forwarding entry as needed. + */ + /* Inform client of label, if needed. */ + if ((new_client && fec->label != MPLS_INVALID_LABEL) || label_change) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Update client label %u", fec->label); + fec_send(fec, client); + } + + if (new_client || label_change) + return fec_change_update_lsp(zvrf, fec, old_label); + + return 0; } /* @@ -1966,89 +1841,85 @@ zebra_mpls_fec_register (struct zebra_vrf *zvrf, struct prefix *p, * itself is deleted if no other registered clients exist and there is no * label bound to the FEC. */ -int -zebra_mpls_fec_unregister (struct zebra_vrf *zvrf, struct prefix *p, - struct zserv *client) +int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p, + struct zserv *client) { - struct route_table *table; - zebra_fec_t *fec; - char buf[BUFSIZ]; - - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; - if (!table) - return -1; + struct route_table *table; + zebra_fec_t *fec; + char buf[BUFSIZ]; - if (IS_ZEBRA_DEBUG_MPLS) - prefix2str(p, buf, BUFSIZ); + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; + if (!table) + return -1; - fec = fec_find (table, p); - if (!fec) - { - prefix2str(p, buf, BUFSIZ); - zlog_err("Failed to find FEC %s upon unregister, client %s", - buf, zebra_route_string(client->proto)); - return -1; - } + if (IS_ZEBRA_DEBUG_MPLS) + prefix2str(p, buf, BUFSIZ); - listnode_delete(fec->client_list, client); - - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug("FEC %s unregistered by client %s", - buf, zebra_route_string(client->proto)); + fec = fec_find(table, p); + if (!fec) { + prefix2str(p, buf, BUFSIZ); + zlog_err("Failed to find FEC %s upon unregister, client %s", + buf, zebra_route_string(client->proto)); + return -1; + } - /* If not a configured entry, delete the FEC if no other clients. Before - * deleting, see if any LSP needs to be uninstalled. - */ - if (!(fec->flags & FEC_FLAG_CONFIGURED) && - list_isempty(fec->client_list)) - { - mpls_label_t old_label = fec->label; - fec->label = MPLS_INVALID_LABEL; /* reset */ - fec_change_update_lsp (zvrf, fec, old_label); - fec_del (fec); - } + listnode_delete(fec->client_list, client); + + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("FEC %s unregistered by client %s", buf, + zebra_route_string(client->proto)); + + /* If not a configured entry, delete the FEC if no other clients. Before + * deleting, see if any LSP needs to be uninstalled. + */ + if (!(fec->flags & FEC_FLAG_CONFIGURED) + && list_isempty(fec->client_list)) { + mpls_label_t old_label = fec->label; + fec->label = MPLS_INVALID_LABEL; /* reset */ + fec_change_update_lsp(zvrf, fec, old_label); + fec_del(fec); + } - return 0; + return 0; } /* * Cleanup any FECs registered by this client. */ -int -zebra_mpls_cleanup_fecs_for_client (struct zebra_vrf *zvrf, struct zserv *client) -{ - struct route_node *rn; - zebra_fec_t *fec; - struct listnode *node; - struct zserv *fec_client; - int af; - - for (af = AFI_IP; af < AFI_MAX; af++) - { - if (zvrf->fec_table[af] == NULL) - continue; - - for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn)) - { - fec = rn->info; - if (!fec || list_isempty(fec->client_list)) - continue; - - for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, fec_client)) - { - if (fec_client == client) - { - listnode_delete(fec->client_list, fec_client); - if (!(fec->flags & FEC_FLAG_CONFIGURED) && - list_isempty(fec->client_list)) - fec_del (fec); - break; - } - } - } - } +int zebra_mpls_cleanup_fecs_for_client(struct zebra_vrf *zvrf, + struct zserv *client) +{ + struct route_node *rn; + zebra_fec_t *fec; + struct listnode *node; + struct zserv *fec_client; + int af; + + for (af = AFI_IP; af < AFI_MAX; af++) { + if (zvrf->fec_table[af] == NULL) + continue; + + for (rn = route_top(zvrf->fec_table[af]); rn; + rn = route_next(rn)) { + fec = rn->info; + if (!fec || list_isempty(fec->client_list)) + continue; + + for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, + fec_client)) { + if (fec_client == client) { + listnode_delete(fec->client_list, + fec_client); + if (!(fec->flags & FEC_FLAG_CONFIGURED) + && list_isempty(fec->client_list)) + fec_del(fec); + break; + } + } + } + } - return 0; + return 0; } /* @@ -2058,38 +1929,36 @@ zebra_mpls_cleanup_fecs_for_client (struct zebra_vrf *zvrf, struct zserv *client * TODO: Currently walks entire table, can optimize later with another * hash.. */ -zebra_fec_t * -zebra_mpls_fec_for_label (struct zebra_vrf *zvrf, mpls_label_t label) -{ - struct route_node *rn; - zebra_fec_t *fec; - int af; - - for (af = AFI_IP; af < AFI_MAX; af++) - { - if (zvrf->fec_table[af] == NULL) - continue; - - for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn)) - { - if (!rn->info) - continue; - fec = rn->info; - if (fec->label == label) - return fec; - } - } +zebra_fec_t *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf, + mpls_label_t label) +{ + struct route_node *rn; + zebra_fec_t *fec; + int af; + + for (af = AFI_IP; af < AFI_MAX; af++) { + if (zvrf->fec_table[af] == NULL) + continue; + + for (rn = route_top(zvrf->fec_table[af]); rn; + rn = route_next(rn)) { + if (!rn->info) + continue; + fec = rn->info; + if (fec->label == label) + return fec; + } + } - return NULL; + return NULL; } /* * Inform if specified label is currently bound to a FEC or not. */ -int -zebra_mpls_label_already_bound (struct zebra_vrf *zvrf, mpls_label_t label) +int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, mpls_label_t label) { - return (zebra_mpls_fec_for_label (zvrf, label) ? 1 : 0); + return (zebra_mpls_fec_for_label(zvrf, label) ? 1 : 0); } /* @@ -2097,59 +1966,54 @@ zebra_mpls_label_already_bound (struct zebra_vrf *zvrf, mpls_label_t label) * FEC, notify them. If there are labeled routes for this FEC, install the * label forwarding entry. */ -int -zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p, - mpls_label_t in_label) -{ - struct route_table *table; - zebra_fec_t *fec; - char buf[BUFSIZ]; - mpls_label_t old_label; - int ret = 0; - - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; - if (!table) - return -1; - - if (IS_ZEBRA_DEBUG_MPLS) - prefix2str(p, buf, BUFSIZ); - - /* Update existing FEC or create a new one. */ - fec = fec_find (table, p); - if (!fec) - { - fec = fec_add (table, p, in_label, FEC_FLAG_CONFIGURED, - MPLS_INVALID_LABEL_INDEX); - if (!fec) - { - prefix2str(p, buf, BUFSIZ); - zlog_err ("Failed to add FEC %s upon config", buf); - return -1; - } - - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Add fec %s label %u", buf, in_label); - } - else - { - fec->flags |= FEC_FLAG_CONFIGURED; - if (fec->label == in_label) - /* Duplicate config */ - return 0; - - /* Label change, update clients. */ - old_label = fec->label; - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Update fec %s new label %u", buf, in_label); - - fec->label = in_label; - fec_update_clients (fec); - - /* Update label forwarding entries appropriately */ - ret = fec_change_update_lsp (zvrf, fec, old_label); - } - - return ret; +int zebra_mpls_static_fec_add(struct zebra_vrf *zvrf, struct prefix *p, + mpls_label_t in_label) +{ + struct route_table *table; + zebra_fec_t *fec; + char buf[BUFSIZ]; + mpls_label_t old_label; + int ret = 0; + + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; + if (!table) + return -1; + + if (IS_ZEBRA_DEBUG_MPLS) + prefix2str(p, buf, BUFSIZ); + + /* Update existing FEC or create a new one. */ + fec = fec_find(table, p); + if (!fec) { + fec = fec_add(table, p, in_label, FEC_FLAG_CONFIGURED, + MPLS_INVALID_LABEL_INDEX); + if (!fec) { + prefix2str(p, buf, BUFSIZ); + zlog_err("Failed to add FEC %s upon config", buf); + return -1; + } + + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Add fec %s label %u", buf, in_label); + } else { + fec->flags |= FEC_FLAG_CONFIGURED; + if (fec->label == in_label) + /* Duplicate config */ + return 0; + + /* Label change, update clients. */ + old_label = fec->label; + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Update fec %s new label %u", buf, in_label); + + fec->label = in_label; + fec_update_clients(fec); + + /* Update label forwarding entries appropriately */ + ret = fec_change_update_lsp(zvrf, fec, old_label); + } + + return ret; } /* @@ -2158,218 +2022,210 @@ zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p, * Note: Upon delete of static binding, if label index exists for this FEC, * client may need to be updated with derived label. */ -int -zebra_mpls_static_fec_del (struct zebra_vrf *zvrf, struct prefix *p) -{ - struct route_table *table; - zebra_fec_t *fec; - mpls_label_t old_label; - char buf[BUFSIZ]; - - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; - if (!table) - return -1; - - fec = fec_find (table, p); - if (!fec) - { - prefix2str(p, buf, BUFSIZ); - zlog_err("Failed to find FEC %s upon delete", buf); - return -1; - } - - if (IS_ZEBRA_DEBUG_MPLS) - { - prefix2str(p, buf, BUFSIZ); - zlog_debug ("Delete fec %s label index %u", - buf, fec->label_index); - } - - old_label = fec->label; - fec->flags &= ~FEC_FLAG_CONFIGURED; - fec->label = MPLS_INVALID_LABEL; - - /* If no client exists, just delete the FEC. */ - if (list_isempty(fec->client_list)) - { - fec_del (fec); - return 0; - } - - /* Derive the local label (from label index) or reset it. */ - fec_derive_label_from_index (zvrf, fec); - - /* If there is a label change, update clients. */ - if (fec->label == old_label) - return 0; - fec_update_clients (fec); - - /* Update label forwarding entries appropriately */ - return fec_change_update_lsp (zvrf, fec, old_label); +int zebra_mpls_static_fec_del(struct zebra_vrf *zvrf, struct prefix *p) +{ + struct route_table *table; + zebra_fec_t *fec; + mpls_label_t old_label; + char buf[BUFSIZ]; + + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; + if (!table) + return -1; + + fec = fec_find(table, p); + if (!fec) { + prefix2str(p, buf, BUFSIZ); + zlog_err("Failed to find FEC %s upon delete", buf); + return -1; + } + + if (IS_ZEBRA_DEBUG_MPLS) { + prefix2str(p, buf, BUFSIZ); + zlog_debug("Delete fec %s label index %u", buf, + fec->label_index); + } + + old_label = fec->label; + fec->flags &= ~FEC_FLAG_CONFIGURED; + fec->label = MPLS_INVALID_LABEL; + + /* If no client exists, just delete the FEC. */ + if (list_isempty(fec->client_list)) { + fec_del(fec); + return 0; + } + + /* Derive the local label (from label index) or reset it. */ + fec_derive_label_from_index(zvrf, fec); + + /* If there is a label change, update clients. */ + if (fec->label == old_label) + return 0; + fec_update_clients(fec); + + /* Update label forwarding entries appropriately */ + return fec_change_update_lsp(zvrf, fec, old_label); } /* * Display MPLS FEC to label binding configuration (VTY command handler). */ -int -zebra_mpls_write_fec_config (struct vty *vty, struct zebra_vrf *zvrf) +int zebra_mpls_write_fec_config(struct vty *vty, struct zebra_vrf *zvrf) { - struct route_node *rn; - int af; - zebra_fec_t *fec; - char buf[BUFSIZ]; - int write = 0; + struct route_node *rn; + int af; + zebra_fec_t *fec; + char buf[BUFSIZ]; + int write = 0; - for (af = AFI_IP; af < AFI_MAX; af++) - { - if (zvrf->fec_table[af] == NULL) - continue; + for (af = AFI_IP; af < AFI_MAX; af++) { + if (zvrf->fec_table[af] == NULL) + continue; - for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn)) - { - if (!rn->info) - continue; + for (rn = route_top(zvrf->fec_table[af]); rn; + rn = route_next(rn)) { + if (!rn->info) + continue; - char lstr[BUFSIZ]; - fec = rn->info; + char lstr[BUFSIZ]; + fec = rn->info; - if (!(fec->flags & FEC_FLAG_CONFIGURED)) - continue; + if (!(fec->flags & FEC_FLAG_CONFIGURED)) + continue; - write = 1; - prefix2str(&rn->p, buf, BUFSIZ); - vty_out (vty, "mpls label bind %s %s\n", buf, - label2str(fec->label, lstr, BUFSIZ)); - } - } + write = 1; + prefix2str(&rn->p, buf, BUFSIZ); + vty_out(vty, "mpls label bind %s %s\n", buf, + label2str(fec->label, lstr, BUFSIZ)); + } + } - return write; + return write; } /* * Display MPLS FEC to label binding (VTY command handler). */ -void -zebra_mpls_print_fec_table (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_mpls_print_fec_table(struct vty *vty, struct zebra_vrf *zvrf) { - struct route_node *rn; - int af; + struct route_node *rn; + int af; - for (af = AFI_IP; af < AFI_MAX; af++) - { - if (zvrf->fec_table[af] == NULL) - continue; + for (af = AFI_IP; af < AFI_MAX; af++) { + if (zvrf->fec_table[af] == NULL) + continue; - for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn)) - { - if (!rn->info) - continue; - fec_print (rn->info, vty); - } - } + for (rn = route_top(zvrf->fec_table[af]); rn; + rn = route_next(rn)) { + if (!rn->info) + continue; + fec_print(rn->info, vty); + } + } } /* * Display MPLS FEC to label binding for a specific FEC (VTY command handler). */ -void -zebra_mpls_print_fec (struct vty *vty, struct zebra_vrf *zvrf, struct prefix *p) +void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf, + struct prefix *p) { - struct route_table *table; - struct route_node *rn; + struct route_table *table; + struct route_node *rn; - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; - if (!table) - return; + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; + if (!table) + return; - apply_mask (p); - rn = route_node_lookup(table, p); - if (!rn) - return; + apply_mask(p); + rn = route_node_lookup(table, p); + if (!rn) + return; - route_unlock_node(rn); - if (!rn->info) - return; + route_unlock_node(rn); + if (!rn->info) + return; - fec_print (rn->info, vty); + fec_print(rn->info, vty); } /* * Install/uninstall a FEC-To-NHLFE (FTN) binding. */ -int -mpls_ftn_update (int add, struct zebra_vrf *zvrf, enum lsp_types_t type, - struct prefix *prefix, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex, u_int8_t distance, - mpls_label_t out_label) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - struct nexthop *nexthop; - - /* Lookup table. */ - table = zebra_vrf_table (family2afi(prefix->family), SAFI_UNICAST, zvrf_id (zvrf)); - if (! table) - return -1; - - /* Lookup existing route */ - rn = route_node_get (table, prefix); - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - if (re->distance == distance) - break; - } - - if (re == NULL) - return -1; - - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - { - switch (nexthop->type) +int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, + struct prefix *prefix, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex, u_int8_t distance, + mpls_label_t out_label) +{ + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + struct nexthop *nexthop; + + /* Lookup table. */ + table = zebra_vrf_table(family2afi(prefix->family), SAFI_UNICAST, + zvrf_id(zvrf)); + if (!table) + return -1; + + /* Lookup existing route */ + rn = route_node_get(table, prefix); + RNODE_FOREACH_RE(rn, re) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (gtype != NEXTHOP_TYPE_IPV4 && gtype != NEXTHOP_TYPE_IPV4_IFINDEX) - continue; - if (! IPV4_ADDR_SAME (&nexthop->gate.ipv4, &gate->ipv4)) - continue; - if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX && - nexthop->ifindex != ifindex) - continue; - goto found; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (gtype != NEXTHOP_TYPE_IPV6 && gtype != NEXTHOP_TYPE_IPV6_IFINDEX) - continue; - if (! IPV6_ADDR_SAME (&nexthop->gate.ipv6, &gate->ipv6)) - continue; - if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX && - nexthop->ifindex != ifindex) - continue; - goto found; - default: - break; + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + if (re->distance == distance) + break; } - } - /* nexthop not found */ - return -1; - found: - if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE) - nexthop_add_labels (nexthop, type, 1, &out_label); - else if (!add && nexthop->nh_label_type == type) - nexthop_del_labels (nexthop); - else - return 0; + if (re == NULL) + return -1; + + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (gtype != NEXTHOP_TYPE_IPV4 + && gtype != NEXTHOP_TYPE_IPV4_IFINDEX) + continue; + if (!IPV4_ADDR_SAME(&nexthop->gate.ipv4, &gate->ipv4)) + continue; + if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX + && nexthop->ifindex != ifindex) + continue; + goto found; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (gtype != NEXTHOP_TYPE_IPV6 + && gtype != NEXTHOP_TYPE_IPV6_IFINDEX) + continue; + if (!IPV6_ADDR_SAME(&nexthop->gate.ipv6, &gate->ipv6)) + continue; + if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX + && nexthop->ifindex != ifindex) + continue; + goto found; + default: + break; + } + } + /* nexthop not found */ + return -1; + +found: + if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE) + nexthop_add_labels(nexthop, type, 1, &out_label); + else if (!add && nexthop->nh_label_type == type) + nexthop_del_labels(nexthop); + else + return 0; - SET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - SET_FLAG (re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - rib_queue_add (rn); + SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); + SET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); + rib_queue_add(rn); - return 0; + return 0; } /* @@ -2377,197 +2233,185 @@ mpls_ftn_update (int add, struct zebra_vrf *zvrf, enum lsp_types_t type, * a new LSP entry or a new NHLFE for an existing in-label or an update of * the out-label for an existing NHLFE (update case). */ -int -mpls_lsp_install (struct zebra_vrf *zvrf, enum lsp_types_t type, - mpls_label_t in_label, mpls_label_t out_label, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex) -{ - struct hash *lsp_table; - zebra_ile_t tmp_ile; - zebra_lsp_t *lsp; - zebra_nhlfe_t *nhlfe; - char buf[BUFSIZ]; - - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return -1; - - /* If entry is present, exit. */ - tmp_ile.in_label = in_label; - lsp = hash_get (lsp_table, &tmp_ile, lsp_alloc); - if (!lsp) - return -1; - nhlfe = nhlfe_find (lsp, type, gtype, gate, ifindex); - if (nhlfe) - { - struct nexthop *nh = nhlfe->nexthop; - - assert (nh); - assert (nh->nh_label); - - /* Clear deleted flag (in case it was set) */ - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED); - if (nh->nh_label->label[0] == out_label) - /* No change */ - return 0; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("LSP in-label %u type %d nexthop %s " - "out-label changed to %u (old %u)", - in_label, type, buf, - out_label, nh->nh_label->label[0]); - } - - /* Update out label, trigger processing. */ - nh->nh_label->label[0] = out_label; - } - else - { - /* Add LSP entry to this nexthop */ - nhlfe = nhlfe_add (lsp, type, gtype, gate, ifindex, out_label); - if (!nhlfe) - return -1; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("Add LSP in-label %u type %d nexthop %s " - "out-label %u", in_label, type, buf, out_label); - } - - lsp->addr_family = NHLFE_FAMILY (nhlfe); - } - - /* Mark NHLFE, queue LSP for processing. */ - SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); - if (lsp_processq_add (lsp)) - return -1; - - return 0; +int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type, + mpls_label_t in_label, mpls_label_t out_label, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex) +{ + struct hash *lsp_table; + zebra_ile_t tmp_ile; + zebra_lsp_t *lsp; + zebra_nhlfe_t *nhlfe; + char buf[BUFSIZ]; + + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return -1; + + /* If entry is present, exit. */ + tmp_ile.in_label = in_label; + lsp = hash_get(lsp_table, &tmp_ile, lsp_alloc); + if (!lsp) + return -1; + nhlfe = nhlfe_find(lsp, type, gtype, gate, ifindex); + if (nhlfe) { + struct nexthop *nh = nhlfe->nexthop; + + assert(nh); + assert(nh->nh_label); + + /* Clear deleted flag (in case it was set) */ + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); + if (nh->nh_label->label[0] == out_label) + /* No change */ + return 0; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "LSP in-label %u type %d nexthop %s " + "out-label changed to %u (old %u)", + in_label, type, buf, out_label, + nh->nh_label->label[0]); + } + + /* Update out label, trigger processing. */ + nh->nh_label->label[0] = out_label; + } else { + /* Add LSP entry to this nexthop */ + nhlfe = nhlfe_add(lsp, type, gtype, gate, ifindex, out_label); + if (!nhlfe) + return -1; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "Add LSP in-label %u type %d nexthop %s " + "out-label %u", + in_label, type, buf, out_label); + } + + lsp->addr_family = NHLFE_FAMILY(nhlfe); + } + + /* Mark NHLFE, queue LSP for processing. */ + SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + if (lsp_processq_add(lsp)) + return -1; + + return 0; } /* * Uninstall a particular NHLFE in the forwarding table. If this is * the only NHLFE, the entire LSP forwarding entry has to be deleted. */ -int -mpls_lsp_uninstall (struct zebra_vrf *zvrf, enum lsp_types_t type, - mpls_label_t in_label, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex) -{ - struct hash *lsp_table; - zebra_ile_t tmp_ile; - zebra_lsp_t *lsp; - zebra_nhlfe_t *nhlfe; - char buf[BUFSIZ]; - - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return -1; - - /* If entry is not present, exit. */ - tmp_ile.in_label = in_label; - lsp = hash_lookup (lsp_table, &tmp_ile); - if (!lsp) - return 0; - nhlfe = nhlfe_find (lsp, type, gtype, gate, ifindex); - if (!nhlfe) - return 0; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x", - in_label, type, buf, nhlfe->flags); - } - - /* Mark NHLFE for delete or directly delete, as appropriate. */ - if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED); - if (lsp_processq_add (lsp)) - return -1; - } - else - { - nhlfe_del (nhlfe); - - /* Free LSP entry if no other NHLFEs and not scheduled. */ - if (!lsp->nhlfe_list && - !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Free LSP in-label %u flags 0x%x", - lsp->ile.in_label, lsp->flags); - - lsp = hash_release(lsp_table, &lsp->ile); - if (lsp) - XFREE(MTYPE_LSP, lsp); - } - } - return 0; +int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, + mpls_label_t in_label, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex) +{ + struct hash *lsp_table; + zebra_ile_t tmp_ile; + zebra_lsp_t *lsp; + zebra_nhlfe_t *nhlfe; + char buf[BUFSIZ]; + + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return -1; + + /* If entry is not present, exit. */ + tmp_ile.in_label = in_label; + lsp = hash_lookup(lsp_table, &tmp_ile); + if (!lsp) + return 0; + nhlfe = nhlfe_find(lsp, type, gtype, gate, ifindex); + if (!nhlfe) + return 0; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug("Del LSP in-label %u type %d nexthop %s flags 0x%x", + in_label, type, buf, nhlfe->flags); + } + + /* Mark NHLFE for delete or directly delete, as appropriate. */ + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) { + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); + if (lsp_processq_add(lsp)) + return -1; + } else { + nhlfe_del(nhlfe); + + /* Free LSP entry if no other NHLFEs and not scheduled. */ + if (!lsp->nhlfe_list + && !CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Free LSP in-label %u flags 0x%x", + lsp->ile.in_label, lsp->flags); + + lsp = hash_release(lsp_table, &lsp->ile); + if (lsp) + XFREE(MTYPE_LSP, lsp); + } + } + return 0; } /* * Uninstall all LDP NHLFEs for a particular LSP forwarding entry. * If no other NHLFEs exist, the entry would be deleted. */ -void -mpls_ldp_lsp_uninstall_all (struct hash_backet *backet, void *ctxt) +void mpls_ldp_lsp_uninstall_all(struct hash_backet *backet, void *ctxt) { - zebra_lsp_t *lsp; - struct hash *lsp_table; + zebra_lsp_t *lsp; + struct hash *lsp_table; - lsp = (zebra_lsp_t *) backet->data; - if (!lsp || !lsp->nhlfe_list) - return; + lsp = (zebra_lsp_t *)backet->data; + if (!lsp || !lsp->nhlfe_list) + return; - lsp_table = ctxt; - if (!lsp_table) - return; + lsp_table = ctxt; + if (!lsp_table) + return; - mpls_lsp_uninstall_all (lsp_table, lsp, ZEBRA_LSP_LDP); + mpls_lsp_uninstall_all(lsp_table, lsp, ZEBRA_LSP_LDP); } /* * Uninstall all LDP FEC-To-NHLFE (FTN) bindings of the given address-family. */ -void -mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - struct nexthop *nexthop; - int update; - - /* Process routes of interested address-families. */ - table = zebra_vrf_table (afi, SAFI_UNICAST, zvrf_id (zvrf)); - if (!table) - return; - - for (rn = route_top (table); rn; rn = route_next (rn)) - { - update = 0; - RNODE_FOREACH_RE (rn, re) - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - if (nexthop->nh_label_type == ZEBRA_LSP_LDP) - { - nexthop_del_labels (nexthop); - SET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - SET_FLAG (re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - update = 1; - } - - if (update) - rib_queue_add (rn); - } +void mpls_ldp_ftn_uninstall_all(struct zebra_vrf *zvrf, int afi) +{ + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + struct nexthop *nexthop; + int update; + + /* Process routes of interested address-families. */ + table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf)); + if (!table) + return; + + for (rn = route_top(table); rn; rn = route_next(rn)) { + update = 0; + RNODE_FOREACH_RE(rn, re) + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) + if (nexthop->nh_label_type == ZEBRA_LSP_LDP) { + nexthop_del_labels(nexthop); + SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); + SET_FLAG(re->status, + ROUTE_ENTRY_NEXTHOPS_CHANGED); + update = 1; + } + + if (update) + rib_queue_add(rn); + } } #if defined(HAVE_CUMULUS) @@ -2577,54 +2421,51 @@ mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi) * be consistent - i.e., all paths either do a swap or do PHP. This is due * to current HW restrictions. */ -int -zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label, - mpls_label_t out_label, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex) -{ - struct hash *slsp_table; - zebra_ile_t tmp_ile; - zebra_slsp_t *slsp; - zebra_snhlfe_t *snhlfe; - - /* Lookup table. */ - slsp_table = zvrf->slsp_table; - if (!slsp_table) - return 0; - - /* If entry is not present, exit. */ - tmp_ile.in_label = in_label; - slsp = hash_lookup (slsp_table, &tmp_ile); - if (!slsp) - return 1; - - snhlfe = snhlfe_find (slsp, gtype, gate, ifindex); - if (snhlfe) - { - if (snhlfe->out_label == out_label) - return 1; - - /* If not only NHLFE, cannot allow label change. */ - if (snhlfe != slsp->snhlfe_list || - snhlfe->next) - return 0; - } - else - { - /* If other NHLFEs exist, label operation must match. */ - if (slsp->snhlfe_list) - { - int cur_op, new_op; - - cur_op = (slsp->snhlfe_list->out_label == MPLS_IMP_NULL_LABEL); - new_op = (out_label == MPLS_IMP_NULL_LABEL); - if (cur_op != new_op) - return 0; - } - } - - /* Label values are good. */ - return 1; +int zebra_mpls_lsp_label_consistent(struct zebra_vrf *zvrf, + mpls_label_t in_label, + mpls_label_t out_label, + enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex) +{ + struct hash *slsp_table; + zebra_ile_t tmp_ile; + zebra_slsp_t *slsp; + zebra_snhlfe_t *snhlfe; + + /* Lookup table. */ + slsp_table = zvrf->slsp_table; + if (!slsp_table) + return 0; + + /* If entry is not present, exit. */ + tmp_ile.in_label = in_label; + slsp = hash_lookup(slsp_table, &tmp_ile); + if (!slsp) + return 1; + + snhlfe = snhlfe_find(slsp, gtype, gate, ifindex); + if (snhlfe) { + if (snhlfe->out_label == out_label) + return 1; + + /* If not only NHLFE, cannot allow label change. */ + if (snhlfe != slsp->snhlfe_list || snhlfe->next) + return 0; + } else { + /* If other NHLFEs exist, label operation must match. */ + if (slsp->snhlfe_list) { + int cur_op, new_op; + + cur_op = (slsp->snhlfe_list->out_label + == MPLS_IMP_NULL_LABEL); + new_op = (out_label == MPLS_IMP_NULL_LABEL); + if (cur_op != new_op) + return 0; + } + } + + /* Label values are good. */ + return 1; } #endif /* HAVE_CUMULUS */ @@ -2635,64 +2476,61 @@ zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label, * Note: The label operation (swap or PHP) is common for the LSP entry (all * NHLFEs). */ -int -zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label, - mpls_label_t out_label, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex) -{ - struct hash *slsp_table; - zebra_ile_t tmp_ile; - zebra_slsp_t *slsp; - zebra_snhlfe_t *snhlfe; - char buf[BUFSIZ]; - - /* Lookup table. */ - slsp_table = zvrf->slsp_table; - if (!slsp_table) - return -1; - - /* If entry is present, exit. */ - tmp_ile.in_label = in_label; - slsp = hash_get (slsp_table, &tmp_ile, slsp_alloc); - if (!slsp) - return -1; - snhlfe = snhlfe_find (slsp, gtype, gate, ifindex); - if (snhlfe) - { - if (snhlfe->out_label == out_label) - /* No change */ - return 0; - - if (IS_ZEBRA_DEBUG_MPLS) - { - snhlfe2str (snhlfe, buf, BUFSIZ); - zlog_debug ("Upd static LSP in-label %u nexthop %s " - "out-label %u (old %u)", - in_label, buf, out_label, snhlfe->out_label); - } - snhlfe->out_label = out_label; - } - else - { - /* Add static LSP entry to this nexthop */ - snhlfe = snhlfe_add (slsp, gtype, gate, ifindex, out_label); - if (!snhlfe) - return -1; - - if (IS_ZEBRA_DEBUG_MPLS) - { - snhlfe2str (snhlfe, buf, BUFSIZ); - zlog_debug ("Add static LSP in-label %u nexthop %s out-label %u", - in_label, buf, out_label); - } - } - - /* (Re)Install LSP in the main table. */ - if (mpls_lsp_install (zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype, - gate, ifindex)) - return -1; - - return 0; +int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label, + mpls_label_t out_label, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex) +{ + struct hash *slsp_table; + zebra_ile_t tmp_ile; + zebra_slsp_t *slsp; + zebra_snhlfe_t *snhlfe; + char buf[BUFSIZ]; + + /* Lookup table. */ + slsp_table = zvrf->slsp_table; + if (!slsp_table) + return -1; + + /* If entry is present, exit. */ + tmp_ile.in_label = in_label; + slsp = hash_get(slsp_table, &tmp_ile, slsp_alloc); + if (!slsp) + return -1; + snhlfe = snhlfe_find(slsp, gtype, gate, ifindex); + if (snhlfe) { + if (snhlfe->out_label == out_label) + /* No change */ + return 0; + + if (IS_ZEBRA_DEBUG_MPLS) { + snhlfe2str(snhlfe, buf, BUFSIZ); + zlog_debug( + "Upd static LSP in-label %u nexthop %s " + "out-label %u (old %u)", + in_label, buf, out_label, snhlfe->out_label); + } + snhlfe->out_label = out_label; + } else { + /* Add static LSP entry to this nexthop */ + snhlfe = snhlfe_add(slsp, gtype, gate, ifindex, out_label); + if (!snhlfe) + return -1; + + if (IS_ZEBRA_DEBUG_MPLS) { + snhlfe2str(snhlfe, buf, BUFSIZ); + zlog_debug( + "Add static LSP in-label %u nexthop %s out-label %u", + in_label, buf, out_label); + } + } + + /* (Re)Install LSP in the main table. */ + if (mpls_lsp_install(zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype, + gate, ifindex)) + return -1; + + return 0; } /* @@ -2702,71 +2540,66 @@ zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label, * NOTE: Delete of the only NHLFE will also end up deleting the entire * LSP configuration. */ -int -zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex) -{ - struct hash *slsp_table; - zebra_ile_t tmp_ile; - zebra_slsp_t *slsp; - zebra_snhlfe_t *snhlfe; - - /* Lookup table. */ - slsp_table = zvrf->slsp_table; - if (!slsp_table) - return -1; - - /* If entry is not present, exit. */ - tmp_ile.in_label = in_label; - slsp = hash_lookup (slsp_table, &tmp_ile); - if (!slsp) - return 0; - - /* Is it delete of entire LSP or a specific NHLFE? */ - if (gtype == NEXTHOP_TYPE_BLACKHOLE) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Del static LSP in-label %u", in_label); - - /* Uninstall entire LSP from the main table. */ - mpls_static_lsp_uninstall_all (zvrf, in_label); - - /* Delete all static NHLFEs */ - snhlfe_del_all (slsp); - } - else - { - /* Find specific NHLFE, exit if not found. */ - snhlfe = snhlfe_find (slsp, gtype, gate, ifindex); - if (!snhlfe) - return 0; - - if (IS_ZEBRA_DEBUG_MPLS) - { - char buf[BUFSIZ]; - snhlfe2str (snhlfe, buf, BUFSIZ); - zlog_debug ("Del static LSP in-label %u nexthop %s", - in_label, buf); - } - - /* Uninstall LSP from the main table. */ - mpls_lsp_uninstall (zvrf, ZEBRA_LSP_STATIC, in_label, gtype, gate, - ifindex); - - /* Delete static LSP NHLFE */ - snhlfe_del (snhlfe); - } - - /* Remove entire static LSP entry if no NHLFE - valid in either case above. */ - if (!slsp->snhlfe_list) - { - slsp = hash_release(slsp_table, &tmp_ile); - if (slsp) - XFREE(MTYPE_SLSP, slsp); - } - - return 0; +int zebra_mpls_static_lsp_del(struct zebra_vrf *zvrf, mpls_label_t in_label, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex) +{ + struct hash *slsp_table; + zebra_ile_t tmp_ile; + zebra_slsp_t *slsp; + zebra_snhlfe_t *snhlfe; + + /* Lookup table. */ + slsp_table = zvrf->slsp_table; + if (!slsp_table) + return -1; + + /* If entry is not present, exit. */ + tmp_ile.in_label = in_label; + slsp = hash_lookup(slsp_table, &tmp_ile); + if (!slsp) + return 0; + + /* Is it delete of entire LSP or a specific NHLFE? */ + if (gtype == NEXTHOP_TYPE_BLACKHOLE) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Del static LSP in-label %u", in_label); + + /* Uninstall entire LSP from the main table. */ + mpls_static_lsp_uninstall_all(zvrf, in_label); + + /* Delete all static NHLFEs */ + snhlfe_del_all(slsp); + } else { + /* Find specific NHLFE, exit if not found. */ + snhlfe = snhlfe_find(slsp, gtype, gate, ifindex); + if (!snhlfe) + return 0; + + if (IS_ZEBRA_DEBUG_MPLS) { + char buf[BUFSIZ]; + snhlfe2str(snhlfe, buf, BUFSIZ); + zlog_debug("Del static LSP in-label %u nexthop %s", + in_label, buf); + } + + /* Uninstall LSP from the main table. */ + mpls_lsp_uninstall(zvrf, ZEBRA_LSP_STATIC, in_label, gtype, + gate, ifindex); + + /* Delete static LSP NHLFE */ + snhlfe_del(snhlfe); + } + + /* Remove entire static LSP entry if no NHLFE - valid in either case + * above. */ + if (!slsp->snhlfe_list) { + slsp = hash_release(slsp_table, &tmp_ile); + if (slsp) + XFREE(MTYPE_SLSP, slsp); + } + + return 0; } /* @@ -2774,200 +2607,192 @@ zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label, * Called upon changes that may affect one or more of them such as * interface or nexthop state changes. */ -void -zebra_mpls_lsp_schedule (struct zebra_vrf *zvrf) +void zebra_mpls_lsp_schedule(struct zebra_vrf *zvrf) { - if (!zvrf) - return; - hash_iterate(zvrf->lsp_table, lsp_schedule, NULL); + if (!zvrf) + return; + hash_iterate(zvrf->lsp_table, lsp_schedule, NULL); } /* * Display MPLS label forwarding table for a specific LSP * (VTY command handler). */ -void -zebra_mpls_print_lsp (struct vty *vty, struct zebra_vrf *zvrf, mpls_label_t label, - u_char use_json) +void zebra_mpls_print_lsp(struct vty *vty, struct zebra_vrf *zvrf, + mpls_label_t label, u_char use_json) { - struct hash *lsp_table; - zebra_lsp_t *lsp; - zebra_ile_t tmp_ile; - json_object *json = NULL; + struct hash *lsp_table; + zebra_lsp_t *lsp; + zebra_ile_t tmp_ile; + json_object *json = NULL; - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return; + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return; - /* If entry is not present, exit. */ - tmp_ile.in_label = label; - lsp = hash_lookup (lsp_table, &tmp_ile); - if (!lsp) - return; + /* If entry is not present, exit. */ + tmp_ile.in_label = label; + lsp = hash_lookup(lsp_table, &tmp_ile); + if (!lsp) + return; - if (use_json) - { - json = lsp_json(lsp); - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - lsp_print (lsp, (void *)vty); + if (use_json) { + json = lsp_json(lsp); + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + lsp_print(lsp, (void *)vty); } /* * Display MPLS label forwarding table (VTY command handler). */ -void -zebra_mpls_print_lsp_table (struct vty *vty, struct zebra_vrf *zvrf, - u_char use_json) -{ - char buf[BUFSIZ]; - json_object *json = NULL; - zebra_lsp_t *lsp = NULL; - zebra_nhlfe_t *nhlfe = NULL; - struct nexthop *nexthop = NULL; - struct listnode *node = NULL; - struct list *lsp_list = hash_get_sorted_list(zvrf->lsp_table, lsp_cmp); - - if (use_json) - { - json = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) - json_object_object_add(json, label2str(lsp->ile.in_label, buf, BUFSIZ), - lsp_json(lsp)); - - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - { - vty_out (vty, " Inbound Outbound\n"); - vty_out (vty, " Label Type Nexthop Label\n"); - vty_out (vty, "-------- ------- --------------- --------\n"); - - for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) - { - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - vty_out (vty, "%8d %7s ", lsp->ile.in_label, nhlfe_type2str(nhlfe->type)); - nexthop = nhlfe->nexthop; - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, "%15s", inet_ntoa (nexthop->gate.ipv4)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out (vty, "%15s", inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); - break; - default: - break; - } - - vty_out (vty, " %8d\n", nexthop->nh_label->label[0]); - } - } - - vty_out (vty, "\n"); - } - - list_delete (lsp_list); +void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf, + u_char use_json) +{ + char buf[BUFSIZ]; + json_object *json = NULL; + zebra_lsp_t *lsp = NULL; + zebra_nhlfe_t *nhlfe = NULL; + struct nexthop *nexthop = NULL; + struct listnode *node = NULL; + struct list *lsp_list = hash_get_sorted_list(zvrf->lsp_table, lsp_cmp); + + if (use_json) { + json = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) + json_object_object_add( + json, label2str(lsp->ile.in_label, buf, BUFSIZ), + lsp_json(lsp)); + + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + vty_out(vty, " Inbound Outbound\n"); + vty_out(vty, " Label Type Nexthop Label\n"); + vty_out(vty, "-------- ------- --------------- --------\n"); + + for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) { + for (nhlfe = lsp->nhlfe_list; nhlfe; + nhlfe = nhlfe->next) { + vty_out(vty, "%8d %7s ", lsp->ile.in_label, + nhlfe_type2str(nhlfe->type)); + nexthop = nhlfe->nexthop; + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, "%15s", + inet_ntoa(nexthop->gate.ipv4)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, "%15s", + inet_ntop(AF_INET6, + &nexthop->gate.ipv6, + buf, BUFSIZ)); + break; + default: + break; + } + + vty_out(vty, " %8d\n", + nexthop->nh_label->label[0]); + } + } + + vty_out(vty, "\n"); + } + + list_delete(lsp_list); } /* * Display MPLS LSP configuration of all static LSPs (VTY command handler). */ -int -zebra_mpls_write_lsp_config (struct vty *vty, struct zebra_vrf *zvrf) -{ - zebra_slsp_t *slsp; - zebra_snhlfe_t *snhlfe; - struct listnode *node; - struct list *slsp_list = hash_get_sorted_list(zvrf->slsp_table, slsp_cmp); - - for (ALL_LIST_ELEMENTS_RO(slsp_list, node, slsp)) - { - for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe->next) - { - char buf[INET6_ADDRSTRLEN]; - char lstr[30]; - - snhlfe2str (snhlfe, buf, BUFSIZ); - switch (snhlfe->out_label) { - case MPLS_V4_EXP_NULL_LABEL: - case MPLS_V6_EXP_NULL_LABEL: - strlcpy(lstr, "explicit-null", sizeof(lstr)); - break; - case MPLS_IMP_NULL_LABEL: - strlcpy(lstr, "implicit-null", sizeof(lstr)); - break; - default: - sprintf(lstr, "%u", snhlfe->out_label); - break; - } - - vty_out (vty, "mpls lsp %u %s %s\n", - slsp->ile.in_label, buf, lstr); - } - } +int zebra_mpls_write_lsp_config(struct vty *vty, struct zebra_vrf *zvrf) +{ + zebra_slsp_t *slsp; + zebra_snhlfe_t *snhlfe; + struct listnode *node; + struct list *slsp_list = + hash_get_sorted_list(zvrf->slsp_table, slsp_cmp); + + for (ALL_LIST_ELEMENTS_RO(slsp_list, node, slsp)) { + for (snhlfe = slsp->snhlfe_list; snhlfe; + snhlfe = snhlfe->next) { + char buf[INET6_ADDRSTRLEN]; + char lstr[30]; + + snhlfe2str(snhlfe, buf, BUFSIZ); + switch (snhlfe->out_label) { + case MPLS_V4_EXP_NULL_LABEL: + case MPLS_V6_EXP_NULL_LABEL: + strlcpy(lstr, "explicit-null", sizeof(lstr)); + break; + case MPLS_IMP_NULL_LABEL: + strlcpy(lstr, "implicit-null", sizeof(lstr)); + break; + default: + sprintf(lstr, "%u", snhlfe->out_label); + break; + } + + vty_out(vty, "mpls lsp %u %s %s\n", slsp->ile.in_label, + buf, lstr); + } + } - list_delete (slsp_list); - return (zvrf->slsp_table->count ? 1 : 0); + list_delete(slsp_list); + return (zvrf->slsp_table->count ? 1 : 0); } /* * Add/update global label block. */ -int -zebra_mpls_label_block_add (struct zebra_vrf *zvrf, u_int32_t start_label, - u_int32_t end_label) +int zebra_mpls_label_block_add(struct zebra_vrf *zvrf, u_int32_t start_label, + u_int32_t end_label) { - zvrf->mpls_srgb.start_label = start_label; - zvrf->mpls_srgb.end_label = end_label; + zvrf->mpls_srgb.start_label = start_label; + zvrf->mpls_srgb.end_label = end_label; - /* Evaluate registered FECs to see if any get a label or not. */ - fec_evaluate (zvrf); - return 0; + /* Evaluate registered FECs to see if any get a label or not. */ + fec_evaluate(zvrf); + return 0; } /* * Delete global label block. */ -int -zebra_mpls_label_block_del (struct zebra_vrf *zvrf) +int zebra_mpls_label_block_del(struct zebra_vrf *zvrf) { - zvrf->mpls_srgb.start_label = MPLS_DEFAULT_MIN_SRGB_LABEL; - zvrf->mpls_srgb.end_label = MPLS_DEFAULT_MAX_SRGB_LABEL; + zvrf->mpls_srgb.start_label = MPLS_DEFAULT_MIN_SRGB_LABEL; + zvrf->mpls_srgb.end_label = MPLS_DEFAULT_MAX_SRGB_LABEL; - /* Process registered FECs to clear their local label, if needed. */ - fec_evaluate (zvrf); - return 0; + /* Process registered FECs to clear their local label, if needed. */ + fec_evaluate(zvrf); + return 0; } /* * Display MPLS global label block configuration (VTY command handler). */ -int -zebra_mpls_write_label_block_config (struct vty *vty, struct zebra_vrf *zvrf) +int zebra_mpls_write_label_block_config(struct vty *vty, struct zebra_vrf *zvrf) { - if (zvrf->mpls_srgb.start_label == 0) - return 0; + if (zvrf->mpls_srgb.start_label == 0) + return 0; - if ((zvrf->mpls_srgb.start_label != MPLS_DEFAULT_MIN_SRGB_LABEL) || - (zvrf->mpls_srgb.end_label != MPLS_DEFAULT_MAX_SRGB_LABEL)) - { - vty_out (vty, "mpls label global-block %u %u\n", - zvrf->mpls_srgb.start_label,zvrf->mpls_srgb.end_label); - } + if ((zvrf->mpls_srgb.start_label != MPLS_DEFAULT_MIN_SRGB_LABEL) + || (zvrf->mpls_srgb.end_label != MPLS_DEFAULT_MAX_SRGB_LABEL)) { + vty_out(vty, "mpls label global-block %u %u\n", + zvrf->mpls_srgb.start_label, zvrf->mpls_srgb.end_label); + } - return 1; + return 1; } /* @@ -2975,48 +2800,44 @@ zebra_mpls_write_label_block_config (struct vty *vty, struct zebra_vrf *zvrf) * entries from the kernel. * NOTE: Currently supported only for default VRF. */ -void -zebra_mpls_close_tables (struct zebra_vrf *zvrf) +void zebra_mpls_close_tables(struct zebra_vrf *zvrf) { - hash_iterate(zvrf->lsp_table, lsp_uninstall_from_kernel, NULL); - hash_clean(zvrf->lsp_table, NULL); - hash_free(zvrf->lsp_table); - hash_clean(zvrf->slsp_table, NULL); - hash_free(zvrf->slsp_table); + hash_iterate(zvrf->lsp_table, lsp_uninstall_from_kernel, NULL); + hash_clean(zvrf->lsp_table, NULL); + hash_free(zvrf->lsp_table); + hash_clean(zvrf->slsp_table, NULL); + hash_free(zvrf->slsp_table); } /* * Allocate MPLS tables for this VRF and do other initialization. * NOTE: Currently supported only for default VRF. */ -void -zebra_mpls_init_tables (struct zebra_vrf *zvrf) +void zebra_mpls_init_tables(struct zebra_vrf *zvrf) { - if (!zvrf) - return; - zvrf->slsp_table = hash_create(label_hash, label_cmp, NULL); - zvrf->lsp_table = hash_create(label_hash, label_cmp, NULL); - zvrf->fec_table[AFI_IP] = route_table_init(); - zvrf->fec_table[AFI_IP6] = route_table_init(); - zvrf->mpls_flags = 0; - zvrf->mpls_srgb.start_label = MPLS_DEFAULT_MIN_SRGB_LABEL; - zvrf->mpls_srgb.end_label = MPLS_DEFAULT_MAX_SRGB_LABEL; + if (!zvrf) + return; + zvrf->slsp_table = hash_create(label_hash, label_cmp, NULL); + zvrf->lsp_table = hash_create(label_hash, label_cmp, NULL); + zvrf->fec_table[AFI_IP] = route_table_init(); + zvrf->fec_table[AFI_IP6] = route_table_init(); + zvrf->mpls_flags = 0; + zvrf->mpls_srgb.start_label = MPLS_DEFAULT_MIN_SRGB_LABEL; + zvrf->mpls_srgb.end_label = MPLS_DEFAULT_MAX_SRGB_LABEL; } /* * Global MPLS initialization. */ -void -zebra_mpls_init (void) +void zebra_mpls_init(void) { - mpls_enabled = 0; + mpls_enabled = 0; - if (mpls_kernel_init () < 0) - { - zlog_warn ("Disabling MPLS support (no kernel support)"); - return; - } + if (mpls_kernel_init() < 0) { + zlog_warn("Disabling MPLS support (no kernel support)"); + return; + } - if (! mpls_processq_init (&zebrad)) - mpls_enabled = 1; + if (!mpls_processq_init(&zebrad)) + mpls_enabled = 1; } diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index 52b947c06..c8dab3921 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -39,12 +39,15 @@ #define MPLS_MAX_LABELS 2 /* Maximum # labels that can be pushed. */ -#define NHLFE_FAMILY(nhlfe) \ - (((nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6 || \ - (nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) ? AF_INET6 : AF_INET) +#define NHLFE_FAMILY(nhlfe) \ + (((nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6 \ + || (nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) \ + ? AF_INET6 \ + : AF_INET) -#define MPLS_LABEL_HELPSTR "Specify label(s) for this route\nOne or more " \ - "labels in the range (16-1048575) separated by '/'\n" +#define MPLS_LABEL_HELPSTR \ + "Specify label(s) for this route\nOne or more " \ + "labels in the range (16-1048575) separated by '/'\n" /* Typedefs */ @@ -58,117 +61,110 @@ typedef struct zebra_fec_t_ zebra_fec_t; /* * (Outgoing) nexthop label forwarding entry configuration */ -struct zebra_snhlfe_t_ -{ - /* Nexthop information */ - enum nexthop_types_t gtype; - union g_addr gate; - char *ifname; - ifindex_t ifindex; +struct zebra_snhlfe_t_ { + /* Nexthop information */ + enum nexthop_types_t gtype; + union g_addr gate; + char *ifname; + ifindex_t ifindex; - /* Out label. */ - mpls_label_t out_label; + /* Out label. */ + mpls_label_t out_label; - /* Backpointer to base entry. */ - zebra_slsp_t *slsp; + /* Backpointer to base entry. */ + zebra_slsp_t *slsp; - /* Pointers to more outgoing information for same in-label */ - zebra_snhlfe_t *next; - zebra_snhlfe_t *prev; + /* Pointers to more outgoing information for same in-label */ + zebra_snhlfe_t *next; + zebra_snhlfe_t *prev; }; /* * (Outgoing) nexthop label forwarding entry */ -struct zebra_nhlfe_t_ -{ - /* Type of entry - static etc. */ - enum lsp_types_t type; +struct zebra_nhlfe_t_ { + /* Type of entry - static etc. */ + enum lsp_types_t type; - /* Nexthop information (with outgoing label) */ - struct nexthop *nexthop; + /* Nexthop information (with outgoing label) */ + struct nexthop *nexthop; - /* Backpointer to base entry. */ - zebra_lsp_t *lsp; + /* Backpointer to base entry. */ + zebra_lsp_t *lsp; - /* Runtime info - flags, pointers etc. */ - u_int32_t flags; + /* Runtime info - flags, pointers etc. */ + u_int32_t flags; #define NHLFE_FLAG_CHANGED (1 << 0) #define NHLFE_FLAG_SELECTED (1 << 1) #define NHLFE_FLAG_MULTIPATH (1 << 2) #define NHLFE_FLAG_DELETED (1 << 3) #define NHLFE_FLAG_INSTALLED (1 << 4) - zebra_nhlfe_t *next; - zebra_nhlfe_t *prev; - u_char distance; + zebra_nhlfe_t *next; + zebra_nhlfe_t *prev; + u_char distance; }; /* * Incoming label entry */ -struct zebra_ile_t_ -{ - mpls_label_t in_label; +struct zebra_ile_t_ { + mpls_label_t in_label; }; /* * Label swap entry static configuration. */ -struct zebra_slsp_t_ -{ - /* Incoming label */ - zebra_ile_t ile; - - /* List of outgoing nexthop static configuration */ - zebra_snhlfe_t *snhlfe_list; +struct zebra_slsp_t_ { + /* Incoming label */ + zebra_ile_t ile; + /* List of outgoing nexthop static configuration */ + zebra_snhlfe_t *snhlfe_list; }; /* * Label swap entry (ile -> list of nhlfes) */ -struct zebra_lsp_t_ -{ - /* Incoming label */ - zebra_ile_t ile; +struct zebra_lsp_t_ { + /* Incoming label */ + zebra_ile_t ile; - /* List of NHLFE, pointer to best and num equal-cost. */ - zebra_nhlfe_t *nhlfe_list; - zebra_nhlfe_t *best_nhlfe; - u_int32_t num_ecmp; + /* List of NHLFE, pointer to best and num equal-cost. */ + zebra_nhlfe_t *nhlfe_list; + zebra_nhlfe_t *best_nhlfe; + u_int32_t num_ecmp; - /* Flags */ - u_int32_t flags; + /* Flags */ + u_int32_t flags; #define LSP_FLAG_SCHEDULED (1 << 0) #define LSP_FLAG_INSTALLED (1 << 1) #define LSP_FLAG_CHANGED (1 << 2) - /* Address-family of NHLFE - saved here for delete. All NHLFEs */ - /* have to be of the same AF */ - u_char addr_family; + /* Address-family of NHLFE - saved here for delete. All NHLFEs */ + /* have to be of the same AF */ + u_char addr_family; }; /* * FEC to label binding. */ -struct zebra_fec_t_ -{ - /* FEC (prefix) */ - struct route_node *rn; +struct zebra_fec_t_ { + /* FEC (prefix) */ + struct route_node *rn; - /* In-label - either statically bound or derived from label block. */ - mpls_label_t label; + /* In-label - either statically bound or derived from label block. */ + mpls_label_t label; - /* Label index (into global label block), if valid */ - u_int32_t label_index; + /* Label index (into global label block), if valid */ + u_int32_t label_index; - /* Flags. */ - u_int32_t flags; + /* Flags. */ + u_int32_t flags; #define FEC_FLAG_CONFIGURED (1 << 0) - /* Clients interested in this FEC. */ - struct list *client_list; + /* Clients interested in this FEC. */ + struct list *client_list; }; /* Function declarations. */ @@ -176,47 +172,42 @@ struct zebra_fec_t_ /* * String to label conversion, labels separated by '/'. */ -int -mpls_str2label (const char *label_str, u_int8_t *num_labels, - mpls_label_t *labels); +int mpls_str2label(const char *label_str, u_int8_t *num_labels, + mpls_label_t *labels); /* * Label to string conversion, labels in string separated by '/'. */ -char * -mpls_label2str (u_int8_t num_labels, mpls_label_t *labels, - char *buf, int len, int pretty); +char *mpls_label2str(u_int8_t num_labels, mpls_label_t *labels, char *buf, + int len, int pretty); /* * Add/update global label block. */ -int -zebra_mpls_label_block_add (struct zebra_vrf *zvrf, u_int32_t start_label, - u_int32_t end_label); +int zebra_mpls_label_block_add(struct zebra_vrf *zvrf, u_int32_t start_label, + u_int32_t end_label); /* * Delete global label block. */ -int -zebra_mpls_label_block_del (struct zebra_vrf *vrf); +int zebra_mpls_label_block_del(struct zebra_vrf *vrf); /* * Display MPLS global label block configuration (VTY command handler). */ -int -zebra_mpls_write_label_block_config (struct vty *vty, struct zebra_vrf *vrf); +int zebra_mpls_write_label_block_config(struct vty *vty, struct zebra_vrf *vrf); /* * Install dynamic LSP entry. */ -int -zebra_mpls_lsp_install (struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *re); +int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn, + struct route_entry *re); /* - * Uninstall dynamic LSP entry, if any. + * Uninstall dynamic LSP entry, if any. */ -int -zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *re); +int zebra_mpls_lsp_uninstall(struct zebra_vrf *zvrf, struct route_node *rn, + struct route_entry *re); /* * Registration from a client for the label binding for a FEC. If a binding @@ -226,24 +217,22 @@ zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct * label from a locally configured label block (SRGB), if one exists and index * is acceptable. */ -int -zebra_mpls_fec_register (struct zebra_vrf *zvrf, struct prefix *p, - u_int32_t label_index, struct zserv *client); +int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p, + u_int32_t label_index, struct zserv *client); /* * Deregistration from a client for the label binding for a FEC. The FEC * itself is deleted if no other registered clients exist and there is no * label bound to the FEC. */ -int -zebra_mpls_fec_unregister (struct zebra_vrf *zvrf, struct prefix *p, - struct zserv *client); +int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p, + struct zserv *client); /* * Cleanup any FECs registered by this client. */ -int -zebra_mpls_cleanup_fecs_for_client (struct zebra_vrf *zvrf, struct zserv *client); +int zebra_mpls_cleanup_fecs_for_client(struct zebra_vrf *zvrf, + struct zserv *client); /* * Return FEC (if any) to which this label is bound. @@ -252,23 +241,21 @@ zebra_mpls_cleanup_fecs_for_client (struct zebra_vrf *zvrf, struct zserv *client * TODO: Currently walks entire table, can optimize later with another * hash.. */ -zebra_fec_t * -zebra_mpls_fec_for_label (struct zebra_vrf *zvrf, mpls_label_t label); +zebra_fec_t *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf, + mpls_label_t label); /* * Inform if specified label is currently bound to a FEC or not. */ -int -zebra_mpls_label_already_bound (struct zebra_vrf *zvrf, mpls_label_t label); +int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, mpls_label_t label); /* * Add static FEC to label binding. If there are clients registered for this * FEC, notify them. If there are labeled routes for this FEC, install the * label forwarding entry. */ -int -zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p, - mpls_label_t in_label); +int zebra_mpls_static_fec_add(struct zebra_vrf *zvrf, struct prefix *p, + mpls_label_t in_label); /* * Remove static FEC to label binding. If there are no clients registered @@ -276,68 +263,60 @@ zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p, * Note: Upon delete of static binding, if label index exists for this FEC, * client may need to be updated with derived label. */ -int -zebra_mpls_static_fec_del (struct zebra_vrf *zvrf, struct prefix *p); +int zebra_mpls_static_fec_del(struct zebra_vrf *zvrf, struct prefix *p); /* * Display MPLS FEC to label binding configuration (VTY command handler). */ -int -zebra_mpls_write_fec_config (struct vty *vty, struct zebra_vrf *zvrf); +int zebra_mpls_write_fec_config(struct vty *vty, struct zebra_vrf *zvrf); /* * Display MPLS FEC to label binding (VTY command handler). */ -void -zebra_mpls_print_fec_table (struct vty *vty, struct zebra_vrf *zvrf); +void zebra_mpls_print_fec_table(struct vty *vty, struct zebra_vrf *zvrf); /* * Display MPLS FEC to label binding for a specific FEC (VTY command handler). */ -void -zebra_mpls_print_fec (struct vty *vty, struct zebra_vrf *zvrf, struct prefix *p); +void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf, + struct prefix *p); /* * Install/uninstall a FEC-To-NHLFE (FTN) binding. */ -int -mpls_ftn_update (int add, struct zebra_vrf *zvrf, enum lsp_types_t type, - struct prefix *prefix, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex, u_int8_t distance, - mpls_label_t out_label); +int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, + struct prefix *prefix, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex, u_int8_t distance, + mpls_label_t out_label); /* * Install/update a NHLFE for an LSP in the forwarding table. This may be * a new LSP entry or a new NHLFE for an existing in-label or an update of * the out-label for an existing NHLFE (update case). */ -int -mpls_lsp_install (struct zebra_vrf *zvrf, enum lsp_types_t type, - mpls_label_t in_label, mpls_label_t out_label, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex); +int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type, + mpls_label_t in_label, mpls_label_t out_label, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex); /* * Uninstall a particular NHLFE in the forwarding table. If this is * the only NHLFE, the entire LSP forwarding entry has to be deleted. */ -int -mpls_lsp_uninstall (struct zebra_vrf *zvrf, enum lsp_types_t type, - mpls_label_t in_label, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex); +int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, + mpls_label_t in_label, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex); /* * Uninstall all LDP NHLFEs for a particular LSP forwarding entry. * If no other NHLFEs exist, the entry would be deleted. */ -void -mpls_ldp_lsp_uninstall_all (struct hash_backet *backet, void *ctxt); +void mpls_ldp_lsp_uninstall_all(struct hash_backet *backet, void *ctxt); /* * Uninstall all LDP FEC-To-NHLFE (FTN) bindings of the given address-family. */ -void -mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi); +void mpls_ldp_ftn_uninstall_all(struct zebra_vrf *zvrf, int afi); #if defined(HAVE_CUMULUS) /* @@ -346,10 +325,11 @@ mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi); * be consistent - i.e., all paths either do a swap or do PHP. This is due * to current HW restrictions. */ -int -zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label, - mpls_label_t out_label, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex); +int zebra_mpls_lsp_label_consistent(struct zebra_vrf *zvrf, + mpls_label_t in_label, + mpls_label_t out_label, + enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex); #endif /* HAVE_CUMULUS */ /* @@ -359,10 +339,10 @@ zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label, * Note: The label operation (swap or PHP) is common for the LSP entry (all * NHLFEs). */ -int -zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label, - mpls_label_t out_label, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex); +int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label, + mpls_label_t out_label, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex); /* * Delete static LSP entry. This may be the delete of one particular @@ -371,141 +351,124 @@ zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label, * NOTE: Delete of the only NHLFE will also end up deleting the entire * LSP configuration. */ -int -zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex); +int zebra_mpls_static_lsp_del(struct zebra_vrf *zvrf, mpls_label_t in_label, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex); /* * Schedule all MPLS label forwarding entries for processing. * Called upon changes that may affect one or more of them such as * interface or nexthop state changes. */ -void -zebra_mpls_lsp_schedule (struct zebra_vrf *zvrf); +void zebra_mpls_lsp_schedule(struct zebra_vrf *zvrf); /* * Display MPLS label forwarding table for a specific LSP * (VTY command handler). */ -void -zebra_mpls_print_lsp (struct vty *vty, struct zebra_vrf *zvrf, mpls_label_t label, - u_char use_json); +void zebra_mpls_print_lsp(struct vty *vty, struct zebra_vrf *zvrf, + mpls_label_t label, u_char use_json); /* * Display MPLS label forwarding table (VTY command handler). */ -void -zebra_mpls_print_lsp_table (struct vty *vty, struct zebra_vrf *zvrf, - u_char use_json); +void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf, + u_char use_json); /* * Display MPLS LSP configuration of all static LSPs (VTY command handler). */ -int -zebra_mpls_write_lsp_config (struct vty *vty, struct zebra_vrf *zvrf); +int zebra_mpls_write_lsp_config(struct vty *vty, struct zebra_vrf *zvrf); /* * Called upon process exiting, need to delete LSP forwarding * entries from the kernel. * NOTE: Currently supported only for default VRF. */ -void -zebra_mpls_close_tables (struct zebra_vrf *zvrf); +void zebra_mpls_close_tables(struct zebra_vrf *zvrf); /* * Allocate MPLS tables for this VRF. * NOTE: Currently supported only for default VRF. */ -void -zebra_mpls_init_tables (struct zebra_vrf *zvrf); +void zebra_mpls_init_tables(struct zebra_vrf *zvrf); /* * Global MPLS initialization. */ -void -zebra_mpls_init (void); +void zebra_mpls_init(void); /* * MPLS VTY. */ -void -zebra_mpls_vty_init (void); +void zebra_mpls_vty_init(void); /* Inline functions. */ /* * Distance (priority) definition for LSP NHLFE. */ -static inline u_char -lsp_distance (enum lsp_types_t type) +static inline u_char lsp_distance(enum lsp_types_t type) { - if (type == ZEBRA_LSP_STATIC) - return (route_distance (ZEBRA_ROUTE_STATIC)); + if (type == ZEBRA_LSP_STATIC) + return (route_distance(ZEBRA_ROUTE_STATIC)); - return 150; + return 150; } /* * Map RIB type to LSP type. Used when labeled-routes from BGP * are converted into LSPs. */ -static inline enum lsp_types_t -lsp_type_from_re_type (int re_type) +static inline enum lsp_types_t lsp_type_from_re_type(int re_type) { - switch (re_type) - { - case ZEBRA_ROUTE_STATIC: - return ZEBRA_LSP_STATIC; - case ZEBRA_ROUTE_BGP: - return ZEBRA_LSP_BGP; - default: - return ZEBRA_LSP_NONE; - } + switch (re_type) { + case ZEBRA_ROUTE_STATIC: + return ZEBRA_LSP_STATIC; + case ZEBRA_ROUTE_BGP: + return ZEBRA_LSP_BGP; + default: + return ZEBRA_LSP_NONE; + } } /* NHLFE type as printable string. */ -static inline const char * -nhlfe_type2str(enum lsp_types_t lsp_type) +static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type) { - switch (lsp_type) - { - case ZEBRA_LSP_STATIC: - return "Static"; - case ZEBRA_LSP_LDP: - return "LDP"; - case ZEBRA_LSP_BGP: - return "BGP"; - default: - return "Unknown"; - } + switch (lsp_type) { + case ZEBRA_LSP_STATIC: + return "Static"; + case ZEBRA_LSP_LDP: + return "LDP"; + case ZEBRA_LSP_BGP: + return "BGP"; + default: + return "Unknown"; + } } -static inline void -mpls_mark_lsps_for_processing(struct zebra_vrf *zvrf) +static inline void mpls_mark_lsps_for_processing(struct zebra_vrf *zvrf) { - if (!zvrf) - return; + if (!zvrf) + return; - zvrf->mpls_flags |= MPLS_FLAG_SCHEDULE_LSPS; + zvrf->mpls_flags |= MPLS_FLAG_SCHEDULE_LSPS; } -static inline void -mpls_unmark_lsps_for_processing(struct zebra_vrf *zvrf) +static inline void mpls_unmark_lsps_for_processing(struct zebra_vrf *zvrf) { - if (!zvrf) - return; + if (!zvrf) + return; - zvrf->mpls_flags &= ~MPLS_FLAG_SCHEDULE_LSPS; + zvrf->mpls_flags &= ~MPLS_FLAG_SCHEDULE_LSPS; } -static inline int -mpls_should_lsps_be_processed(struct zebra_vrf *zvrf) +static inline int mpls_should_lsps_be_processed(struct zebra_vrf *zvrf) { - if (!zvrf) - return 0; + if (!zvrf) + return 0; - return ((zvrf->mpls_flags & MPLS_FLAG_SCHEDULE_LSPS) ? 1 : 0); + return ((zvrf->mpls_flags & MPLS_FLAG_SCHEDULE_LSPS) ? 1 : 0); } /* Global variables. */ diff --git a/zebra/zebra_mpls_netlink.c b/zebra/zebra_mpls_netlink.c index d0c4acb37..c5053563b 100644 --- a/zebra/zebra_mpls_netlink.c +++ b/zebra/zebra_mpls_netlink.c @@ -26,22 +26,21 @@ /* * Install Label Forwarding entry into the kernel. */ -int -kernel_add_lsp (zebra_lsp_t *lsp) +int kernel_add_lsp(zebra_lsp_t *lsp) { - int ret; + int ret; - if (!lsp || !lsp->best_nhlfe) // unexpected - return -1; + if (!lsp || !lsp->best_nhlfe) // unexpected + return -1; - UNSET_FLAG (lsp->flags, LSP_FLAG_CHANGED); - ret = netlink_mpls_multipath (RTM_NEWROUTE, lsp); - if (!ret) - SET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); - else - clear_nhlfe_installed (lsp); + UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); + ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp); + if (!ret) + SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + else + clear_nhlfe_installed(lsp); - return ret; + return ret; } /* @@ -55,58 +54,54 @@ kernel_add_lsp (zebra_lsp_t *lsp) * through the metric field (before kernel-MPLS). This shouldn't be an issue * any longer, so REPLACE can be reintroduced. */ -int -kernel_upd_lsp (zebra_lsp_t *lsp) +int kernel_upd_lsp(zebra_lsp_t *lsp) { - int ret; + int ret; - if (!lsp || !lsp->best_nhlfe) // unexpected - return -1; + if (!lsp || !lsp->best_nhlfe) // unexpected + return -1; - UNSET_FLAG (lsp->flags, LSP_FLAG_CHANGED); + UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); - /* First issue a DEL and clear the installed flag. */ - netlink_mpls_multipath (RTM_DELROUTE, lsp); - UNSET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); + /* First issue a DEL and clear the installed flag. */ + netlink_mpls_multipath(RTM_DELROUTE, lsp); + UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - /* Then issue an ADD. */ - ret = netlink_mpls_multipath (RTM_NEWROUTE, lsp); - if (!ret) - SET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); - else - clear_nhlfe_installed (lsp); + /* Then issue an ADD. */ + ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp); + if (!ret) + SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + else + clear_nhlfe_installed(lsp); - return ret; + return ret; } /* * Delete Label Forwarding entry from the kernel. */ -int -kernel_del_lsp (zebra_lsp_t *lsp) +int kernel_del_lsp(zebra_lsp_t *lsp) { - if (!lsp) // unexpected - return -1; + if (!lsp) // unexpected + return -1; - if (CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED)) - { - netlink_mpls_multipath (RTM_DELROUTE, lsp); - UNSET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); - } + if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) { + netlink_mpls_multipath(RTM_DELROUTE, lsp); + UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + } - return 0; + return 0; } -int -mpls_kernel_init (void) +int mpls_kernel_init(void) { - struct stat st; + struct stat st; - /* - * Check if the MPLS module is loaded in the kernel. - */ - if (stat ("/proc/sys/net/mpls", &st) != 0) - return -1; + /* + * Check if the MPLS module is loaded in the kernel. + */ + if (stat("/proc/sys/net/mpls", &st) != 0) + return -1; - return 0; + return 0; }; diff --git a/zebra/zebra_mpls_null.c b/zebra/zebra_mpls_null.c index a8acdb19f..a9da5c29c 100644 --- a/zebra/zebra_mpls_null.c +++ b/zebra/zebra_mpls_null.c @@ -22,7 +22,19 @@ #include "zebra/rt.h" #include "zebra/zebra_mpls.h" -int kernel_add_lsp (zebra_lsp_t *lsp) { return 0; } -int kernel_upd_lsp (zebra_lsp_t *lsp) { return 0; } -int kernel_del_lsp (zebra_lsp_t *lsp) { return 0; } -int mpls_kernel_init (void) { return -1; }; +int kernel_add_lsp(zebra_lsp_t *lsp) +{ + return 0; +} +int kernel_upd_lsp(zebra_lsp_t *lsp) +{ + return 0; +} +int kernel_del_lsp(zebra_lsp_t *lsp) +{ + return 0; +} +int mpls_kernel_init(void) +{ + return -1; +}; diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c index 45e4435ee..fc1df9227 100644 --- a/zebra/zebra_mpls_openbsd.c +++ b/zebra/zebra_mpls_openbsd.c @@ -32,336 +32,329 @@ extern struct zebra_privs_t zserv_privs; struct { - u_int32_t rtseq; - int fd; + u_int32_t rtseq; + int fd; } kr_state; -static int -kernel_send_rtmsg_v4 (int action, mpls_label_t in_label, zebra_nhlfe_t *nhlfe) +static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label, + zebra_nhlfe_t *nhlfe) { - struct iovec iov[5]; - struct rt_msghdr hdr; - struct sockaddr_mpls sa_label_in, sa_label_out; - struct sockaddr_in nexthop; - int iovcnt = 0; - int ret; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: 0x%x, label=%u", __func__, action, in_label); - - /* initialize header */ - memset (&hdr, 0, sizeof (hdr)); - hdr.rtm_version = RTM_VERSION; - - hdr.rtm_type = action; - hdr.rtm_flags = RTF_UP; - hdr.rtm_fmask = RTF_MPLS; - hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ - hdr.rtm_msglen = sizeof (hdr); - hdr.rtm_hdrlen = sizeof (struct rt_msghdr); - hdr.rtm_priority = 0; - /* adjust iovec */ - iov[iovcnt].iov_base = &hdr; - iov[iovcnt++].iov_len = sizeof (hdr); - - /* in label */ - memset (&sa_label_in, 0, sizeof (sa_label_in)); - sa_label_in.smpls_len = sizeof (sa_label_in); - sa_label_in.smpls_family = AF_MPLS; - sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); - /* adjust header */ - hdr.rtm_flags |= RTF_MPLS | RTF_MPATH; - hdr.rtm_addrs |= RTA_DST; - hdr.rtm_msglen += sizeof (sa_label_in); - /* adjust iovec */ - iov[iovcnt].iov_base = &sa_label_in; - iov[iovcnt++].iov_len = sizeof (sa_label_in); - - /* nexthop */ - memset (&nexthop, 0, sizeof (nexthop)); - nexthop.sin_len = sizeof (nexthop); - nexthop.sin_family = AF_INET; - nexthop.sin_addr = nhlfe->nexthop->gate.ipv4; - /* adjust header */ - hdr.rtm_flags |= RTF_GATEWAY; - hdr.rtm_addrs |= RTA_GATEWAY; - hdr.rtm_msglen += sizeof (nexthop); - /* adjust iovec */ - iov[iovcnt].iov_base = &nexthop; - iov[iovcnt++].iov_len = sizeof (nexthop); - - /* If action is RTM_DELETE we have to get rid of MPLS infos */ - if (action != RTM_DELETE) - { - memset (&sa_label_out, 0, sizeof (sa_label_out)); - sa_label_out.smpls_len = sizeof (sa_label_out); - sa_label_out.smpls_family = AF_MPLS; - sa_label_out.smpls_label = - htonl(nhlfe->nexthop->nh_label->label[0] << MPLS_LABEL_OFFSET); - /* adjust header */ - hdr.rtm_addrs |= RTA_SRC; - hdr.rtm_flags |= RTF_MPLS; - hdr.rtm_msglen += sizeof (sa_label_out); - /* adjust iovec */ - iov[iovcnt].iov_base = &sa_label_out; - iov[iovcnt++].iov_len = sizeof (sa_label_out); - - if (nhlfe->nexthop->nh_label->label[0] == MPLS_LABEL_IMPLNULL) - hdr.rtm_mpls = MPLS_OP_POP; - else - hdr.rtm_mpls = MPLS_OP_SWAP; - } - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err ("Can't raise privileges"); - ret = writev (kr_state.fd, iov, iovcnt); - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err ("Can't lower privileges"); - - if (ret == -1) - zlog_err ("%s: %s", __func__, safe_strerror (errno)); - - return ret; + struct iovec iov[5]; + struct rt_msghdr hdr; + struct sockaddr_mpls sa_label_in, sa_label_out; + struct sockaddr_in nexthop; + int iovcnt = 0; + int ret; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: 0x%x, label=%u", __func__, action, in_label); + + /* initialize header */ + memset(&hdr, 0, sizeof(hdr)); + hdr.rtm_version = RTM_VERSION; + + hdr.rtm_type = action; + hdr.rtm_flags = RTF_UP; + hdr.rtm_fmask = RTF_MPLS; + hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ + hdr.rtm_msglen = sizeof(hdr); + hdr.rtm_hdrlen = sizeof(struct rt_msghdr); + hdr.rtm_priority = 0; + /* adjust iovec */ + iov[iovcnt].iov_base = &hdr; + iov[iovcnt++].iov_len = sizeof(hdr); + + /* in label */ + memset(&sa_label_in, 0, sizeof(sa_label_in)); + sa_label_in.smpls_len = sizeof(sa_label_in); + sa_label_in.smpls_family = AF_MPLS; + sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); + /* adjust header */ + hdr.rtm_flags |= RTF_MPLS | RTF_MPATH; + hdr.rtm_addrs |= RTA_DST; + hdr.rtm_msglen += sizeof(sa_label_in); + /* adjust iovec */ + iov[iovcnt].iov_base = &sa_label_in; + iov[iovcnt++].iov_len = sizeof(sa_label_in); + + /* nexthop */ + memset(&nexthop, 0, sizeof(nexthop)); + nexthop.sin_len = sizeof(nexthop); + nexthop.sin_family = AF_INET; + nexthop.sin_addr = nhlfe->nexthop->gate.ipv4; + /* adjust header */ + hdr.rtm_flags |= RTF_GATEWAY; + hdr.rtm_addrs |= RTA_GATEWAY; + hdr.rtm_msglen += sizeof(nexthop); + /* adjust iovec */ + iov[iovcnt].iov_base = &nexthop; + iov[iovcnt++].iov_len = sizeof(nexthop); + + /* If action is RTM_DELETE we have to get rid of MPLS infos */ + if (action != RTM_DELETE) { + memset(&sa_label_out, 0, sizeof(sa_label_out)); + sa_label_out.smpls_len = sizeof(sa_label_out); + sa_label_out.smpls_family = AF_MPLS; + sa_label_out.smpls_label = + htonl(nhlfe->nexthop->nh_label->label[0] + << MPLS_LABEL_OFFSET); + /* adjust header */ + hdr.rtm_addrs |= RTA_SRC; + hdr.rtm_flags |= RTF_MPLS; + hdr.rtm_msglen += sizeof(sa_label_out); + /* adjust iovec */ + iov[iovcnt].iov_base = &sa_label_out; + iov[iovcnt++].iov_len = sizeof(sa_label_out); + + if (nhlfe->nexthop->nh_label->label[0] == MPLS_LABEL_IMPLNULL) + hdr.rtm_mpls = MPLS_OP_POP; + else + hdr.rtm_mpls = MPLS_OP_SWAP; + } + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + ret = writev(kr_state.fd, iov, iovcnt); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + if (ret == -1) + zlog_err("%s: %s", __func__, safe_strerror(errno)); + + return ret; } #if !defined(ROUNDUP) -#define ROUNDUP(a) \ - (((a) & (sizeof(long) - 1)) ? (1 + ((a) | (sizeof(long) - 1))) : (a)) +#define ROUNDUP(a) \ + (((a) & (sizeof(long) - 1)) ? (1 + ((a) | (sizeof(long) - 1))) : (a)) #endif -static int -kernel_send_rtmsg_v6 (int action, mpls_label_t in_label, zebra_nhlfe_t *nhlfe) +static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label, + zebra_nhlfe_t *nhlfe) { - struct iovec iov[5]; - struct rt_msghdr hdr; - struct sockaddr_mpls sa_label_in, sa_label_out; - struct pad { - struct sockaddr_in6 addr; - char pad[sizeof(long)]; /* thank you IPv6 */ - } nexthop; - int iovcnt = 0; - int ret; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: 0x%x, label=%u", __func__, action, in_label); - - /* initialize header */ - memset (&hdr, 0, sizeof (hdr)); - hdr.rtm_version = RTM_VERSION; - - hdr.rtm_type = action; - hdr.rtm_flags = RTF_UP; - hdr.rtm_fmask = RTF_MPLS; - hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ - hdr.rtm_msglen = sizeof (hdr); - hdr.rtm_hdrlen = sizeof (struct rt_msghdr); - hdr.rtm_priority = 0; - /* adjust iovec */ - iov[iovcnt].iov_base = &hdr; - iov[iovcnt++].iov_len = sizeof (hdr); - - /* in label */ - memset (&sa_label_in, 0, sizeof (sa_label_in)); - sa_label_in.smpls_len = sizeof (sa_label_in); - sa_label_in.smpls_family = AF_MPLS; - sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); - /* adjust header */ - hdr.rtm_flags |= RTF_MPLS | RTF_MPATH; - hdr.rtm_addrs |= RTA_DST; - hdr.rtm_msglen += sizeof (sa_label_in); - /* adjust iovec */ - iov[iovcnt].iov_base = &sa_label_in; - iov[iovcnt++].iov_len = sizeof (sa_label_in); - - /* nexthop */ - memset (&nexthop, 0, sizeof (nexthop)); - nexthop.addr.sin6_len = sizeof (struct sockaddr_in6); - nexthop.addr.sin6_family = AF_INET6; - nexthop.addr.sin6_addr = nhlfe->nexthop->gate.ipv6; - if (IN6_IS_ADDR_LINKLOCAL (&nexthop.addr.sin6_addr)) - { - uint16_t tmp16; - struct sockaddr_in6 *sin6 = &nexthop.addr; - - nexthop.addr.sin6_scope_id = nhlfe->nexthop->ifindex; - - memcpy (&tmp16, &sin6->sin6_addr.s6_addr[2], sizeof (tmp16)); - tmp16 = htons (sin6->sin6_scope_id); - memcpy (&sin6->sin6_addr.s6_addr[2], &tmp16, sizeof (tmp16)); - sin6->sin6_scope_id = 0; - } - - /* adjust header */ - hdr.rtm_flags |= RTF_GATEWAY; - hdr.rtm_addrs |= RTA_GATEWAY; - hdr.rtm_msglen += ROUNDUP (sizeof (struct sockaddr_in6)); - /* adjust iovec */ - iov[iovcnt].iov_base = &nexthop; - iov[iovcnt++].iov_len = ROUNDUP (sizeof (struct sockaddr_in6)); - - /* If action is RTM_DELETE we have to get rid of MPLS infos */ - if (action != RTM_DELETE) - { - memset (&sa_label_out, 0, sizeof (sa_label_out)); - sa_label_out.smpls_len = sizeof (sa_label_out); - sa_label_out.smpls_family = AF_MPLS; - sa_label_out.smpls_label = - htonl(nhlfe->nexthop->nh_label->label[0] << MPLS_LABEL_OFFSET); - /* adjust header */ - hdr.rtm_addrs |= RTA_SRC; - hdr.rtm_flags |= RTF_MPLS; - hdr.rtm_msglen += sizeof (sa_label_out); - /* adjust iovec */ - iov[iovcnt].iov_base = &sa_label_out; - iov[iovcnt++].iov_len = sizeof (sa_label_out); - - if (nhlfe->nexthop->nh_label->label[0] == MPLS_LABEL_IMPLNULL) - hdr.rtm_mpls = MPLS_OP_POP; - else - hdr.rtm_mpls = MPLS_OP_SWAP; - } - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err ("Can't raise privileges"); - ret = writev (kr_state.fd, iov, iovcnt); - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err ("Can't lower privileges"); - - if (ret == -1) - zlog_err ("%s: %s", __func__, safe_strerror (errno)); - - return ret; + struct iovec iov[5]; + struct rt_msghdr hdr; + struct sockaddr_mpls sa_label_in, sa_label_out; + struct pad { + struct sockaddr_in6 addr; + char pad[sizeof(long)]; /* thank you IPv6 */ + } nexthop; + int iovcnt = 0; + int ret; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: 0x%x, label=%u", __func__, action, in_label); + + /* initialize header */ + memset(&hdr, 0, sizeof(hdr)); + hdr.rtm_version = RTM_VERSION; + + hdr.rtm_type = action; + hdr.rtm_flags = RTF_UP; + hdr.rtm_fmask = RTF_MPLS; + hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ + hdr.rtm_msglen = sizeof(hdr); + hdr.rtm_hdrlen = sizeof(struct rt_msghdr); + hdr.rtm_priority = 0; + /* adjust iovec */ + iov[iovcnt].iov_base = &hdr; + iov[iovcnt++].iov_len = sizeof(hdr); + + /* in label */ + memset(&sa_label_in, 0, sizeof(sa_label_in)); + sa_label_in.smpls_len = sizeof(sa_label_in); + sa_label_in.smpls_family = AF_MPLS; + sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); + /* adjust header */ + hdr.rtm_flags |= RTF_MPLS | RTF_MPATH; + hdr.rtm_addrs |= RTA_DST; + hdr.rtm_msglen += sizeof(sa_label_in); + /* adjust iovec */ + iov[iovcnt].iov_base = &sa_label_in; + iov[iovcnt++].iov_len = sizeof(sa_label_in); + + /* nexthop */ + memset(&nexthop, 0, sizeof(nexthop)); + nexthop.addr.sin6_len = sizeof(struct sockaddr_in6); + nexthop.addr.sin6_family = AF_INET6; + nexthop.addr.sin6_addr = nhlfe->nexthop->gate.ipv6; + if (IN6_IS_ADDR_LINKLOCAL(&nexthop.addr.sin6_addr)) { + uint16_t tmp16; + struct sockaddr_in6 *sin6 = &nexthop.addr; + + nexthop.addr.sin6_scope_id = nhlfe->nexthop->ifindex; + + memcpy(&tmp16, &sin6->sin6_addr.s6_addr[2], sizeof(tmp16)); + tmp16 = htons(sin6->sin6_scope_id); + memcpy(&sin6->sin6_addr.s6_addr[2], &tmp16, sizeof(tmp16)); + sin6->sin6_scope_id = 0; + } + + /* adjust header */ + hdr.rtm_flags |= RTF_GATEWAY; + hdr.rtm_addrs |= RTA_GATEWAY; + hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6)); + /* adjust iovec */ + iov[iovcnt].iov_base = &nexthop; + iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6)); + + /* If action is RTM_DELETE we have to get rid of MPLS infos */ + if (action != RTM_DELETE) { + memset(&sa_label_out, 0, sizeof(sa_label_out)); + sa_label_out.smpls_len = sizeof(sa_label_out); + sa_label_out.smpls_family = AF_MPLS; + sa_label_out.smpls_label = + htonl(nhlfe->nexthop->nh_label->label[0] + << MPLS_LABEL_OFFSET); + /* adjust header */ + hdr.rtm_addrs |= RTA_SRC; + hdr.rtm_flags |= RTF_MPLS; + hdr.rtm_msglen += sizeof(sa_label_out); + /* adjust iovec */ + iov[iovcnt].iov_base = &sa_label_out; + iov[iovcnt++].iov_len = sizeof(sa_label_out); + + if (nhlfe->nexthop->nh_label->label[0] == MPLS_LABEL_IMPLNULL) + hdr.rtm_mpls = MPLS_OP_POP; + else + hdr.rtm_mpls = MPLS_OP_SWAP; + } + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + ret = writev(kr_state.fd, iov, iovcnt); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + if (ret == -1) + zlog_err("%s: %s", __func__, safe_strerror(errno)); + + return ret; } -static int -kernel_lsp_cmd (int action, zebra_lsp_t *lsp) +static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp) { - zebra_nhlfe_t *nhlfe; - struct nexthop *nexthop = NULL; - unsigned int nexthop_num = 0; - - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - nexthop = nhlfe->nexthop; - if (!nexthop) - continue; - - if (nexthop_num >= multipath_num) - break; - - if (((action == RTM_ADD || action == RTM_CHANGE) && - (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) || - (action == RTM_DELETE && - (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))) - { - nexthop_num++; - - switch (NHLFE_FAMILY(nhlfe)) - { - case AF_INET: - kernel_send_rtmsg_v4 (action, lsp->ile.in_label, nhlfe); - break; - case AF_INET6: - kernel_send_rtmsg_v6 (action, lsp->ile.in_label, nhlfe); - break; - default: - break; - } - if (action == RTM_ADD || action == RTM_CHANGE) - { - SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - else - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - } - } - - return (0); + zebra_nhlfe_t *nhlfe; + struct nexthop *nexthop = NULL; + unsigned int nexthop_num = 0; + + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + nexthop = nhlfe->nexthop; + if (!nexthop) + continue; + + if (nexthop_num >= multipath_num) + break; + + if (((action == RTM_ADD || action == RTM_CHANGE) + && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))) + || (action == RTM_DELETE + && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)))) { + nexthop_num++; + + switch (NHLFE_FAMILY(nhlfe)) { + case AF_INET: + kernel_send_rtmsg_v4(action, lsp->ile.in_label, + nhlfe); + break; + case AF_INET6: + kernel_send_rtmsg_v6(action, lsp->ile.in_label, + nhlfe); + break; + default: + break; + } + if (action == RTM_ADD || action == RTM_CHANGE) { + SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } else { + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } + } + } + + return (0); } -int -kernel_add_lsp (zebra_lsp_t *lsp) +int kernel_add_lsp(zebra_lsp_t *lsp) { - int ret; + int ret; - if (!lsp || !lsp->best_nhlfe) // unexpected - return -1; + if (!lsp || !lsp->best_nhlfe) // unexpected + return -1; - UNSET_FLAG (lsp->flags, LSP_FLAG_CHANGED); - ret = kernel_lsp_cmd (RTM_ADD, lsp); - if (!ret) - SET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); + UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); + ret = kernel_lsp_cmd(RTM_ADD, lsp); + if (!ret) + SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - return ret; + return ret; } -int -kernel_upd_lsp (zebra_lsp_t *lsp) +int kernel_upd_lsp(zebra_lsp_t *lsp) { - int ret; + int ret; - if (!lsp || !lsp->best_nhlfe) // unexpected - return -1; + if (!lsp || !lsp->best_nhlfe) // unexpected + return -1; - UNSET_FLAG (lsp->flags, LSP_FLAG_CHANGED); - UNSET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); - ret = kernel_lsp_cmd (RTM_CHANGE, lsp); - if (!ret) - SET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); + UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); + UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + ret = kernel_lsp_cmd(RTM_CHANGE, lsp); + if (!ret) + SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - return ret; + return ret; } -int -kernel_del_lsp (zebra_lsp_t *lsp) +int kernel_del_lsp(zebra_lsp_t *lsp) { - int ret; + int ret; - if (!lsp) // unexpected - return -1; + if (!lsp) // unexpected + return -1; - if (! CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED)) - return -1; + if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) + return -1; - ret = kernel_lsp_cmd (RTM_DELETE, lsp); - if (!ret) - UNSET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); + ret = kernel_lsp_cmd(RTM_DELETE, lsp); + if (!ret) + UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - return ret; + return ret; } #define MAX_RTSOCK_BUF 128 * 1024 -int -mpls_kernel_init (void) +int mpls_kernel_init(void) { - int rcvbuf, default_rcvbuf; - socklen_t optlen; - - if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) { - zlog_warn("%s: socket", __func__); - return -1; - } - - /* grow receive buffer, don't wanna miss messages */ - optlen = sizeof (default_rcvbuf); - if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, - &default_rcvbuf, &optlen) == -1) - zlog_warn("kr_init getsockopt SOL_SOCKET SO_RCVBUF"); - else - for (rcvbuf = MAX_RTSOCK_BUF; - rcvbuf > default_rcvbuf && - setsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, - &rcvbuf, sizeof (rcvbuf)) == -1 && errno == ENOBUFS; - rcvbuf /= 2) - ; /* nothing */ - - kr_state.rtseq = 1; - - return 0; + int rcvbuf, default_rcvbuf; + socklen_t optlen; + + if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) { + zlog_warn("%s: socket", __func__); + return -1; + } + + /* grow receive buffer, don't wanna miss messages */ + optlen = sizeof(default_rcvbuf); + if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, &default_rcvbuf, + &optlen) + == -1) + zlog_warn("kr_init getsockopt SOL_SOCKET SO_RCVBUF"); + else + for (rcvbuf = MAX_RTSOCK_BUF; + rcvbuf > default_rcvbuf + && setsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, + sizeof(rcvbuf)) + == -1 + && errno == ENOBUFS; + rcvbuf /= 2) + ; /* nothing */ + + kr_state.rtseq = 1; + + return 0; } diff --git a/zebra/zebra_mpls_vty.c b/zebra/zebra_mpls_vty.c index 938e8ef7c..ed34831f8 100644 --- a/zebra/zebra_mpls_vty.c +++ b/zebra/zebra_mpls_vty.c @@ -39,119 +39,106 @@ #include "zebra/zebra_routemap.h" #include "zebra/zebra_static.h" -static int -zebra_mpls_transit_lsp (struct vty *vty, int add_cmd, const char *inlabel_str, - const char *gate_str, const char *outlabel_str, - const char *flag_str) +static int zebra_mpls_transit_lsp(struct vty *vty, int add_cmd, + const char *inlabel_str, const char *gate_str, + const char *outlabel_str, + const char *flag_str) { - struct zebra_vrf *zvrf; - int ret; - enum nexthop_types_t gtype; - union g_addr gate; - mpls_label_t label; - mpls_label_t in_label, out_label; - - if (!mpls_enabled) - { - vty_out (vty,"%% MPLS not turned on in kernel, ignoring command\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - { - vty_out (vty, "%% Default VRF does not exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!inlabel_str) - { - vty_out (vty, "%% No Label Information\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - out_label = MPLS_IMP_NULL_LABEL; /* as initialization */ - label = atoi(inlabel_str); - if (!IS_MPLS_UNRESERVED_LABEL(label)) - { - vty_out (vty, "%% Invalid label\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (add_cmd) - { - if (!gate_str) - { - vty_out (vty, "%% No Nexthop Information\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (!outlabel_str) - { - vty_out (vty, "%% No Outgoing label Information\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - in_label = label; - gtype = NEXTHOP_TYPE_BLACKHOLE; /* as initialization */ - - if (gate_str) - { - /* Gateway is a IPv4 or IPv6 nexthop. */ - ret = inet_pton (AF_INET6, gate_str, &gate.ipv6); - if (ret) - gtype = NEXTHOP_TYPE_IPV6; - else - { - ret = inet_pton (AF_INET, gate_str, &gate.ipv4); - if (ret) - gtype = NEXTHOP_TYPE_IPV4; - else - { - vty_out (vty, "%% Invalid nexthop\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - } - - if (outlabel_str) - { - if (outlabel_str[0] == 'i') - out_label = MPLS_IMP_NULL_LABEL; - else if (outlabel_str[0] == 'e' && gtype == NEXTHOP_TYPE_IPV4) - out_label = MPLS_V4_EXP_NULL_LABEL; - else if (outlabel_str[0] == 'e' && gtype == NEXTHOP_TYPE_IPV6) - out_label = MPLS_V6_EXP_NULL_LABEL; - else - out_label = atoi(outlabel_str); - } - - if (add_cmd) - { + struct zebra_vrf *zvrf; + int ret; + enum nexthop_types_t gtype; + union g_addr gate; + mpls_label_t label; + mpls_label_t in_label, out_label; + + if (!mpls_enabled) { + vty_out(vty, + "%% MPLS not turned on in kernel, ignoring command\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) { + vty_out(vty, "%% Default VRF does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (!inlabel_str) { + vty_out(vty, "%% No Label Information\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + out_label = MPLS_IMP_NULL_LABEL; /* as initialization */ + label = atoi(inlabel_str); + if (!IS_MPLS_UNRESERVED_LABEL(label)) { + vty_out(vty, "%% Invalid label\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (add_cmd) { + if (!gate_str) { + vty_out(vty, "%% No Nexthop Information\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (!outlabel_str) { + vty_out(vty, "%% No Outgoing label Information\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + in_label = label; + gtype = NEXTHOP_TYPE_BLACKHOLE; /* as initialization */ + + if (gate_str) { + /* Gateway is a IPv4 or IPv6 nexthop. */ + ret = inet_pton(AF_INET6, gate_str, &gate.ipv6); + if (ret) + gtype = NEXTHOP_TYPE_IPV6; + else { + ret = inet_pton(AF_INET, gate_str, &gate.ipv4); + if (ret) + gtype = NEXTHOP_TYPE_IPV4; + else { + vty_out(vty, "%% Invalid nexthop\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + } + + if (outlabel_str) { + if (outlabel_str[0] == 'i') + out_label = MPLS_IMP_NULL_LABEL; + else if (outlabel_str[0] == 'e' && gtype == NEXTHOP_TYPE_IPV4) + out_label = MPLS_V4_EXP_NULL_LABEL; + else if (outlabel_str[0] == 'e' && gtype == NEXTHOP_TYPE_IPV6) + out_label = MPLS_V6_EXP_NULL_LABEL; + else + out_label = atoi(outlabel_str); + } + + if (add_cmd) { #if defined(HAVE_CUMULUS) - /* Check that label value is consistent. */ - if (!zebra_mpls_lsp_label_consistent (zvrf, in_label, out_label, gtype, - &gate, 0)) - { - vty_out (vty,"%% Label value not consistent\n"); - return CMD_WARNING_CONFIG_FAILED; - } + /* Check that label value is consistent. */ + if (!zebra_mpls_lsp_label_consistent(zvrf, in_label, out_label, + gtype, &gate, 0)) { + vty_out(vty, "%% Label value not consistent\n"); + return CMD_WARNING_CONFIG_FAILED; + } #endif /* HAVE_CUMULUS */ - ret = zebra_mpls_static_lsp_add (zvrf, in_label, out_label, gtype, - &gate, 0); - } - else - ret = zebra_mpls_static_lsp_del (zvrf, in_label, gtype, &gate, 0); + ret = zebra_mpls_static_lsp_add(zvrf, in_label, out_label, + gtype, &gate, 0); + } else + ret = zebra_mpls_static_lsp_del(zvrf, in_label, gtype, &gate, + 0); - if (ret) - { - vty_out (vty, "%% LSP cannot be %s\n", - add_cmd ? "added" : "deleted"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret) { + vty_out(vty, "%% LSP cannot be %s\n", + add_cmd ? "added" : "deleted"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (mpls_transit_lsp, @@ -166,7 +153,8 @@ DEFUN (mpls_transit_lsp, "Use Explicit-Null label\n" "Use Implicit-Null label\n") { - return zebra_mpls_transit_lsp (vty, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL); + return zebra_mpls_transit_lsp(vty, 1, argv[2]->arg, argv[3]->arg, + argv[4]->arg, NULL); } DEFUN (no_mpls_transit_lsp, @@ -179,22 +167,21 @@ DEFUN (no_mpls_transit_lsp, "IPv4 gateway address\n" "IPv6 gateway address\n") { - return zebra_mpls_transit_lsp (vty, 0, argv[3]->arg, argv[4]->arg, NULL, NULL); + return zebra_mpls_transit_lsp(vty, 0, argv[3]->arg, argv[4]->arg, NULL, + NULL); } -ALIAS (no_mpls_transit_lsp, - no_mpls_transit_lsp_out_label_cmd, - "no mpls lsp (16-1048575) <A.B.C.D|X:X::X:X> <(16-1048575)|explicit-null|implicit-null>", - NO_STR - MPLS_STR - "Establish label switched path\n" - "Incoming MPLS label\n" - "IPv4 gateway address\n" - "IPv6 gateway address\n" - "Outgoing MPLS label\n" - "Use Explicit-Null label\n" - "Use Implicit-Null label\n") - +ALIAS(no_mpls_transit_lsp, no_mpls_transit_lsp_out_label_cmd, + "no mpls lsp (16-1048575) <A.B.C.D|X:X::X:X> <(16-1048575)|explicit-null|implicit-null>", + NO_STR MPLS_STR + "Establish label switched path\n" + "Incoming MPLS label\n" + "IPv4 gateway address\n" + "IPv6 gateway address\n" + "Outgoing MPLS label\n" + "Use Explicit-Null label\n" + "Use Implicit-Null label\n") + DEFUN (no_mpls_transit_lsp_all, no_mpls_transit_lsp_all_cmd, "no mpls lsp (16-1048575)", @@ -203,78 +190,67 @@ DEFUN (no_mpls_transit_lsp_all, "Establish label switched path\n" "Incoming MPLS label\n") { - return zebra_mpls_transit_lsp (vty, 0, argv[3]->arg, NULL, NULL, NULL); + return zebra_mpls_transit_lsp(vty, 0, argv[3]->arg, NULL, NULL, NULL); } -static int -zebra_mpls_bind (struct vty *vty, int add_cmd, const char *prefix, - const char *label_str) +static int zebra_mpls_bind(struct vty *vty, int add_cmd, const char *prefix, + const char *label_str) { - struct zebra_vrf *zvrf; - struct prefix p; - u_int32_t label; - int ret; - - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - { - vty_out (vty, "%% Default VRF does not exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - memset(&p, 0, sizeof(struct prefix)); - ret = str2prefix(prefix, &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (add_cmd) - { - if (!label_str) - { - vty_out (vty, "%% No label binding specified\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!strcmp(label_str, "implicit-null")) - label = MPLS_IMP_NULL_LABEL; - else if (!strcmp(label_str, "explicit-null")) - { - if (p.family == AF_INET) - label = MPLS_V4_EXP_NULL_LABEL; - else - label = MPLS_V6_EXP_NULL_LABEL; - } - else - { - label = atoi(label_str); - if (!IS_MPLS_UNRESERVED_LABEL(label)) - { - vty_out (vty, "%% Invalid label\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (zebra_mpls_label_already_bound (zvrf, label)) - { - vty_out (vty,"%% Label already bound to a FEC\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - ret = zebra_mpls_static_fec_add (zvrf, &p, label); - } - else - ret = zebra_mpls_static_fec_del (zvrf, &p); - - if (ret) - { - vty_out (vty, "%% FEC to label binding cannot be %s\n", - add_cmd ? "added" : "deleted"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + struct zebra_vrf *zvrf; + struct prefix p; + u_int32_t label; + int ret; + + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) { + vty_out(vty, "%% Default VRF does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + memset(&p, 0, sizeof(struct prefix)); + ret = str2prefix(prefix, &p); + if (ret <= 0) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (add_cmd) { + if (!label_str) { + vty_out(vty, "%% No label binding specified\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (!strcmp(label_str, "implicit-null")) + label = MPLS_IMP_NULL_LABEL; + else if (!strcmp(label_str, "explicit-null")) { + if (p.family == AF_INET) + label = MPLS_V4_EXP_NULL_LABEL; + else + label = MPLS_V6_EXP_NULL_LABEL; + } else { + label = atoi(label_str); + if (!IS_MPLS_UNRESERVED_LABEL(label)) { + vty_out(vty, "%% Invalid label\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (zebra_mpls_label_already_bound(zvrf, label)) { + vty_out(vty, + "%% Label already bound to a FEC\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + ret = zebra_mpls_static_fec_add(zvrf, &p, label); + } else + ret = zebra_mpls_static_fec_del(zvrf, &p); + + if (ret) { + vty_out(vty, "%% FEC to label binding cannot be %s\n", + add_cmd ? "added" : "deleted"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (mpls_label_bind, @@ -289,7 +265,7 @@ DEFUN (mpls_label_bind, "Use Implicit-Null Label\n" "Use Explicit-Null Label\n") { - return zebra_mpls_bind (vty, 1, argv[3]->arg, argv[4]->arg); + return zebra_mpls_bind(vty, 1, argv[3]->arg, argv[4]->arg); } DEFUN (no_mpls_label_bind, @@ -303,9 +279,8 @@ DEFUN (no_mpls_label_bind, "IPv6 prefix\n" "MPLS Label to bind\n" "Use Implicit-Null Label\n") - { - return zebra_mpls_bind (vty, 0, argv[4]->arg, NULL); + return zebra_mpls_bind(vty, 0, argv[4]->arg, NULL); } /* Static route configuration. */ @@ -320,8 +295,9 @@ DEFUN (ip_route_label, "Null interface\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, - NULL, NULL, argv[5]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, + argv[3]->arg, NULL, NULL, NULL, NULL, + argv[5]->arg); } DEFUN (ip_route_tag_label, @@ -337,8 +313,9 @@ DEFUN (ip_route_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, argv[5]->arg, - NULL, NULL, argv[7]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, + argv[3]->arg, NULL, argv[5]->arg, NULL, NULL, + argv[7]->arg); } /* Mask as A.B.C.D format. */ @@ -354,8 +331,9 @@ DEFUN (ip_route_mask_label, "Null interface\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL, NULL, - NULL, NULL, argv[6]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, + argv[3]->arg, argv[4]->arg, NULL, NULL, NULL, + NULL, argv[6]->arg); } DEFUN (ip_route_mask_tag_label, @@ -371,10 +349,10 @@ DEFUN (ip_route_mask_tag_label, "Set tag for this route\n" "Tag value\n" MPLS_LABEL_HELPSTR) - { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, - NULL, NULL, argv[8]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, + argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, + NULL, NULL, argv[8]->arg); } /* Distance option value. */ @@ -390,8 +368,9 @@ DEFUN (ip_route_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, - argv[4]->arg, NULL, argv[6]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, + argv[3]->arg, NULL, NULL, argv[4]->arg, NULL, + argv[6]->arg); } DEFUN (ip_route_tag_distance_label, @@ -407,10 +386,10 @@ DEFUN (ip_route_tag_distance_label, "Tag value\n" "Distance value for this route\n" MPLS_LABEL_HELPSTR) - { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, argv[5]->arg, - argv[6]->arg, NULL, argv[8]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, + argv[3]->arg, NULL, argv[5]->arg, argv[6]->arg, + NULL, argv[8]->arg); } DEFUN (ip_route_mask_distance_label, @@ -426,8 +405,9 @@ DEFUN (ip_route_mask_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL, NULL, - argv[5]->arg, NULL, argv[7]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, + argv[3]->arg, argv[4]->arg, NULL, NULL, + argv[5]->arg, NULL, argv[7]->arg); } DEFUN (ip_route_mask_tag_distance_label, @@ -445,8 +425,9 @@ DEFUN (ip_route_mask_tag_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, - argv[7]->arg, NULL, argv[9]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, + argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, + argv[7]->arg, NULL, argv[9]->arg); } DEFUN (no_ip_route_label, @@ -461,8 +442,9 @@ DEFUN (no_ip_route_label, "Null interface\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, - NULL, NULL, argv[6]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, + argv[4]->arg, NULL, NULL, NULL, NULL, + argv[6]->arg); } DEFUN (no_ip_route_tag_label, @@ -479,8 +461,9 @@ DEFUN (no_ip_route_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, argv[6]->arg, - NULL, NULL, argv[8]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, + argv[4]->arg, NULL, argv[6]->arg, NULL, NULL, + argv[8]->arg); } DEFUN (no_ip_route_mask_label, @@ -496,8 +479,9 @@ DEFUN (no_ip_route_mask_label, "Null interface\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, argv[4]->arg, argv[5]->arg, NULL, NULL, - NULL, NULL, argv[7]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, + argv[4]->arg, argv[5]->arg, NULL, NULL, NULL, + NULL, argv[7]->arg); } DEFUN (no_ip_route_mask_tag_label, @@ -515,8 +499,9 @@ DEFUN (no_ip_route_mask_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, - NULL, NULL, argv[9]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, + argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, + NULL, NULL, argv[9]->arg); } DEFUN (no_ip_route_distance_label, @@ -532,8 +517,9 @@ DEFUN (no_ip_route_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, - argv[5]->arg, NULL, argv[7]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, + argv[4]->arg, NULL, NULL, argv[5]->arg, NULL, + argv[7]->arg); } DEFUN (no_ip_route_tag_distance_label, @@ -551,8 +537,9 @@ DEFUN (no_ip_route_tag_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, argv[6]->arg, - argv[7]->arg, NULL, argv[9]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, + argv[4]->arg, NULL, argv[6]->arg, argv[7]->arg, + NULL, argv[9]->arg); } DEFUN (no_ip_route_mask_distance_label, @@ -569,8 +556,9 @@ DEFUN (no_ip_route_mask_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, argv[4]->arg, argv[5]->arg, NULL, NULL, - argv[6]->arg, NULL, argv[8]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, + argv[4]->arg, argv[5]->arg, NULL, NULL, + argv[6]->arg, NULL, argv[8]->arg); } DEFUN (no_ip_route_mask_tag_distance_label, @@ -589,8 +577,9 @@ DEFUN (no_ip_route_mask_tag_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, - argv[8]->arg, NULL, argv[10]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, + argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, + argv[8]->arg, NULL, argv[10]->arg); } DEFUN (ipv6_route_label, @@ -603,7 +592,8 @@ DEFUN (ipv6_route_label, "IPv6 gateway interface name\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, NULL, NULL, NULL, argv[5]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, + NULL, NULL, NULL, NULL, argv[5]->arg); } DEFUN (ipv6_route_tag_label, @@ -618,7 +608,8 @@ DEFUN (ipv6_route_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, argv[5]->arg, NULL, NULL, argv[7]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, + NULL, argv[5]->arg, NULL, NULL, argv[7]->arg); } DEFUN (ipv6_route_ifname_label, @@ -631,7 +622,9 @@ DEFUN (ipv6_route_ifname_label, "IPv6 gateway interface name\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, argv[4]->arg, NULL, NULL, NULL, NULL, argv[6]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, + argv[4]->arg, NULL, NULL, NULL, NULL, + argv[6]->arg); } DEFUN (ipv6_route_ifname_tag_label, ipv6_route_ifname_tag_label_cmd, @@ -645,7 +638,9 @@ DEFUN (ipv6_route_ifname_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, NULL, NULL, argv[8]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, + argv[4]->arg, NULL, argv[6]->arg, NULL, NULL, + argv[8]->arg); } DEFUN (ipv6_route_pref_label, @@ -659,7 +654,8 @@ DEFUN (ipv6_route_pref_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, NULL, argv[4]->arg, NULL, argv[6]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, + NULL, NULL, argv[4]->arg, NULL, argv[6]->arg); } DEFUN (ipv6_route_pref_tag_label, @@ -675,7 +671,9 @@ DEFUN (ipv6_route_pref_tag_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, argv[5]->arg, argv[6]->arg, NULL, argv[8]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, + NULL, argv[5]->arg, argv[6]->arg, NULL, + argv[8]->arg); } DEFUN (ipv6_route_ifname_pref_label, @@ -689,7 +687,9 @@ DEFUN (ipv6_route_ifname_pref_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, argv[4]->arg, NULL, NULL, argv[5]->arg, NULL, argv[7]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, + argv[4]->arg, NULL, NULL, argv[5]->arg, NULL, + argv[7]->arg); } DEFUN (ipv6_route_ifname_pref_tag_label, @@ -705,7 +705,9 @@ DEFUN (ipv6_route_ifname_pref_tag_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, argv[7]->arg, NULL, argv[9]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, + argv[4]->arg, NULL, argv[6]->arg, argv[7]->arg, + NULL, argv[9]->arg); } DEFUN (no_ipv6_route_label, @@ -719,7 +721,8 @@ DEFUN (no_ipv6_route_label, "IPv6 gateway interface name\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, NULL, NULL, NULL, argv[6]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, + NULL, NULL, NULL, NULL, argv[6]->arg); } DEFUN (no_ipv6_route_tag_label, @@ -735,7 +738,8 @@ DEFUN (no_ipv6_route_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, argv[6]->arg, NULL, NULL, argv[8]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, + NULL, argv[6]->arg, NULL, NULL, argv[8]->arg); } DEFUN (no_ipv6_route_ifname_label, @@ -749,7 +753,9 @@ DEFUN (no_ipv6_route_ifname_label, "IPv6 gateway interface name\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, argv[5]->arg, NULL, NULL, NULL, NULL, argv[7]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, + argv[5]->arg, NULL, NULL, NULL, NULL, + argv[7]->arg); } DEFUN (no_ipv6_route_ifname_tag_label, @@ -765,7 +771,9 @@ DEFUN (no_ipv6_route_ifname_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, NULL, NULL, argv[9]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, + argv[5]->arg, NULL, argv[7]->arg, NULL, NULL, + argv[9]->arg); } DEFUN (no_ipv6_route_pref_label, @@ -780,7 +788,8 @@ DEFUN (no_ipv6_route_pref_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, NULL, argv[5]->arg, NULL, argv[7]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, + NULL, NULL, argv[5]->arg, NULL, argv[7]->arg); } DEFUN (no_ipv6_route_pref_tag_label, @@ -797,7 +806,9 @@ DEFUN (no_ipv6_route_pref_tag_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, argv[6]->arg, argv[7]->arg, NULL, argv[9]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, + NULL, argv[6]->arg, argv[7]->arg, NULL, + argv[9]->arg); } DEFUN (no_ipv6_route_ifname_pref_label, @@ -812,7 +823,9 @@ DEFUN (no_ipv6_route_ifname_pref_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, argv[5]->arg, NULL, NULL, argv[6]->arg, NULL, argv[8]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, + argv[5]->arg, NULL, NULL, argv[6]->arg, NULL, + argv[8]->arg); } DEFUN (no_ipv6_route_ifname_pref_tag_label, @@ -829,24 +842,25 @@ DEFUN (no_ipv6_route_ifname_pref_tag_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, argv[8]->arg, NULL, argv[10]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, + argv[5]->arg, NULL, argv[7]->arg, argv[8]->arg, + NULL, argv[10]->arg); } /* MPLS LSP configuration write function. */ -static int -zebra_mpls_config (struct vty *vty) +static int zebra_mpls_config(struct vty *vty) { - int write = 0; - struct zebra_vrf *zvrf; + int write = 0; + struct zebra_vrf *zvrf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - return 0; + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) + return 0; - write += zebra_mpls_write_lsp_config(vty, zvrf); - write += zebra_mpls_write_fec_config(vty, zvrf); - write += zebra_mpls_write_label_block_config (vty, zvrf); - return write; + write += zebra_mpls_write_lsp_config(vty, zvrf); + write += zebra_mpls_write_fec_config(vty, zvrf); + write += zebra_mpls_write_label_block_config(vty, zvrf); + return write; } DEFUN (show_mpls_fec, @@ -858,29 +872,27 @@ DEFUN (show_mpls_fec, "FEC to display information about\n" "FEC to display information about\n") { - struct zebra_vrf *zvrf; - struct prefix p; - int ret; - - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - return 0; - - if (argc == 3) - zebra_mpls_print_fec_table(vty, zvrf); - else - { - memset(&p, 0, sizeof(struct prefix)); - ret = str2prefix(argv[3]->arg, &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING; - } - zebra_mpls_print_fec (vty, zvrf, &p); - } - - return CMD_SUCCESS; + struct zebra_vrf *zvrf; + struct prefix p; + int ret; + + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) + return 0; + + if (argc == 3) + zebra_mpls_print_fec_table(vty, zvrf); + else { + memset(&p, 0, sizeof(struct prefix)); + ret = str2prefix(argv[3]->arg, &p); + if (ret <= 0) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING; + } + zebra_mpls_print_fec(vty, zvrf, &p); + } + + return CMD_SUCCESS; } DEFUN (show_mpls_table, @@ -891,12 +903,12 @@ DEFUN (show_mpls_table, "MPLS table\n" JSON_STR) { - struct zebra_vrf *zvrf; - u_char uj = use_json (argc, argv); + struct zebra_vrf *zvrf; + u_char uj = use_json(argc, argv); - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_mpls_print_lsp_table(vty, zvrf, uj); - return CMD_SUCCESS; + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_mpls_print_lsp_table(vty, zvrf, uj); + return CMD_SUCCESS; } DEFUN (show_mpls_table_lsp, @@ -908,14 +920,14 @@ DEFUN (show_mpls_table_lsp, "LSP to display information about\n" JSON_STR) { - u_int32_t label; - struct zebra_vrf *zvrf; - u_char uj = use_json (argc, argv); - - zvrf = vrf_info_lookup(VRF_DEFAULT); - label = atoi(argv[3]->arg); - zebra_mpls_print_lsp (vty, zvrf, label, uj); - return CMD_SUCCESS; + u_int32_t label; + struct zebra_vrf *zvrf; + u_char uj = use_json(argc, argv); + + zvrf = vrf_info_lookup(VRF_DEFAULT); + label = atoi(argv[3]->arg); + zebra_mpls_print_lsp(vty, zvrf, label, uj); + return CMD_SUCCESS; } DEFUN (show_mpls_status, @@ -925,62 +937,56 @@ DEFUN (show_mpls_status, "MPLS information\n" "MPLS status\n") { - vty_out (vty, "MPLS support enabled: %s\n", - (mpls_enabled) ? "yes" : "no (mpls kernel extensions not detected)"); - return CMD_SUCCESS; + vty_out(vty, "MPLS support enabled: %s\n", + (mpls_enabled) ? "yes" + : "no (mpls kernel extensions not detected)"); + return CMD_SUCCESS; } -static int -zebra_mpls_global_block (struct vty *vty, int add_cmd, - const char *start_label_str, const char *end_label_str) +static int zebra_mpls_global_block(struct vty *vty, int add_cmd, + const char *start_label_str, + const char *end_label_str) { - int ret; - u_int32_t start_label; - u_int32_t end_label; - struct zebra_vrf *zvrf; - - zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); - if (!zvrf) - { - vty_out (vty, "%% Default VRF does not exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (add_cmd) - { - if (!start_label_str || !end_label_str) - { - vty_out (vty, "%% Labels not specified\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - start_label = atoi(start_label_str); - end_label = atoi(end_label_str); - if (!IS_MPLS_UNRESERVED_LABEL(start_label) || - !IS_MPLS_UNRESERVED_LABEL(end_label)) - { - vty_out (vty, "%% Invalid label\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (end_label < start_label) - { - vty_out (vty,"%% End label is less than Start label\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = zebra_mpls_label_block_add (zvrf, start_label, end_label); - } - else - ret = zebra_mpls_label_block_del (zvrf); - - if (ret) - { - vty_out (vty, "%% Global label block could not be %s\n", - add_cmd ? "added" : "deleted"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + int ret; + u_int32_t start_label; + u_int32_t end_label; + struct zebra_vrf *zvrf; + + zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); + if (!zvrf) { + vty_out(vty, "%% Default VRF does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (add_cmd) { + if (!start_label_str || !end_label_str) { + vty_out(vty, "%% Labels not specified\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + start_label = atoi(start_label_str); + end_label = atoi(end_label_str); + if (!IS_MPLS_UNRESERVED_LABEL(start_label) + || !IS_MPLS_UNRESERVED_LABEL(end_label)) { + vty_out(vty, "%% Invalid label\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (end_label < start_label) { + vty_out(vty, "%% End label is less than Start label\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = zebra_mpls_label_block_add(zvrf, start_label, end_label); + } else + ret = zebra_mpls_label_block_del(zvrf); + + if (ret) { + vty_out(vty, "%% Global label block could not be %s\n", + add_cmd ? "added" : "deleted"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (mpls_label_global_block, @@ -992,7 +998,7 @@ DEFUN (mpls_label_global_block, "Start label\n" "End label\n") { - return zebra_mpls_global_block (vty, 1, argv[3]->arg, argv[4]->arg); + return zebra_mpls_global_block(vty, 1, argv[3]->arg, argv[4]->arg); } DEFUN (no_mpls_label_global_block, @@ -1005,65 +1011,64 @@ DEFUN (no_mpls_label_global_block, "Start label\n" "End label\n") { - return zebra_mpls_global_block (vty, 0, NULL, NULL); + return zebra_mpls_global_block(vty, 0, NULL, NULL); } /* MPLS node for MPLS LSP. */ -static struct cmd_node mpls_node = { MPLS_NODE, "", 1 }; +static struct cmd_node mpls_node = {MPLS_NODE, "", 1}; /* MPLS VTY. */ -void -zebra_mpls_vty_init (void) +void zebra_mpls_vty_init(void) { - install_element (VIEW_NODE, &show_mpls_status_cmd); - - install_node (&mpls_node, zebra_mpls_config); - - install_element (CONFIG_NODE, &ip_route_label_cmd); - install_element (CONFIG_NODE, &ip_route_tag_label_cmd); - install_element (CONFIG_NODE, &ip_route_mask_label_cmd); - install_element (CONFIG_NODE, &ip_route_mask_tag_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_tag_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_mask_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_mask_tag_label_cmd); - install_element (CONFIG_NODE, &ip_route_distance_label_cmd); - install_element (CONFIG_NODE, &ip_route_tag_distance_label_cmd); - install_element (CONFIG_NODE, &ip_route_mask_distance_label_cmd); - install_element (CONFIG_NODE, &ip_route_mask_tag_distance_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_distance_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_tag_distance_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_mask_distance_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_mask_tag_distance_label_cmd); - - install_element (CONFIG_NODE, &ipv6_route_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_pref_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_pref_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_pref_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_tag_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_tag_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_pref_tag_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_pref_tag_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_tag_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_tag_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_pref_tag_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_tag_label_cmd); - - install_element (CONFIG_NODE, &mpls_transit_lsp_cmd); - install_element (CONFIG_NODE, &no_mpls_transit_lsp_cmd); - install_element (CONFIG_NODE, &no_mpls_transit_lsp_out_label_cmd); - install_element (CONFIG_NODE, &no_mpls_transit_lsp_all_cmd); - install_element (CONFIG_NODE, &mpls_label_bind_cmd); - install_element (CONFIG_NODE, &no_mpls_label_bind_cmd); - - install_element (CONFIG_NODE, &mpls_label_global_block_cmd); - install_element (CONFIG_NODE, &no_mpls_label_global_block_cmd); - - install_element (VIEW_NODE, &show_mpls_table_cmd); - install_element (VIEW_NODE, &show_mpls_table_lsp_cmd); - install_element (VIEW_NODE, &show_mpls_fec_cmd); + install_element(VIEW_NODE, &show_mpls_status_cmd); + + install_node(&mpls_node, zebra_mpls_config); + + install_element(CONFIG_NODE, &ip_route_label_cmd); + install_element(CONFIG_NODE, &ip_route_tag_label_cmd); + install_element(CONFIG_NODE, &ip_route_mask_label_cmd); + install_element(CONFIG_NODE, &ip_route_mask_tag_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_tag_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_mask_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_mask_tag_label_cmd); + install_element(CONFIG_NODE, &ip_route_distance_label_cmd); + install_element(CONFIG_NODE, &ip_route_tag_distance_label_cmd); + install_element(CONFIG_NODE, &ip_route_mask_distance_label_cmd); + install_element(CONFIG_NODE, &ip_route_mask_tag_distance_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_distance_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_tag_distance_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_mask_distance_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_mask_tag_distance_label_cmd); + + install_element(CONFIG_NODE, &ipv6_route_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_ifname_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_ifname_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_pref_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_ifname_pref_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_pref_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_ifname_pref_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_tag_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_ifname_tag_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_pref_tag_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_ifname_pref_tag_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_tag_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_ifname_tag_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_pref_tag_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_ifname_pref_tag_label_cmd); + + install_element(CONFIG_NODE, &mpls_transit_lsp_cmd); + install_element(CONFIG_NODE, &no_mpls_transit_lsp_cmd); + install_element(CONFIG_NODE, &no_mpls_transit_lsp_out_label_cmd); + install_element(CONFIG_NODE, &no_mpls_transit_lsp_all_cmd); + install_element(CONFIG_NODE, &mpls_label_bind_cmd); + install_element(CONFIG_NODE, &no_mpls_label_bind_cmd); + + install_element(CONFIG_NODE, &mpls_label_global_block_cmd); + install_element(CONFIG_NODE, &no_mpls_label_global_block_cmd); + + install_element(VIEW_NODE, &show_mpls_table_cmd); + install_element(VIEW_NODE, &show_mpls_table_lsp_cmd); + install_element(VIEW_NODE, &show_mpls_fec_cmd); } diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c index 82c7f404b..c00498171 100644 --- a/zebra/zebra_mroute.c +++ b/zebra/zebra_mroute.c @@ -31,37 +31,37 @@ #include "zebra/zebra_mroute.h" #include "zebra/rt.h" -int -zebra_ipmr_route_stats (struct zserv *client, int fd, u_short length, struct zebra_vrf *zvrf) +int zebra_ipmr_route_stats(struct zserv *client, int fd, u_short length, + struct zebra_vrf *zvrf) { - struct mcast_route_data mroute; - struct stream *s; - int suc; + struct mcast_route_data mroute; + struct stream *s; + int suc; - char sbuf[40]; - char gbuf[40]; + char sbuf[40]; + char gbuf[40]; - memset (&mroute, 0, sizeof (mroute)); - stream_get (&mroute.sg.src, client->ibuf, 4); - stream_get (&mroute.sg.grp, client->ibuf, 4); - mroute.ifindex = stream_getl (client->ibuf); + memset(&mroute, 0, sizeof(mroute)); + stream_get(&mroute.sg.src, client->ibuf, 4); + stream_get(&mroute.sg.grp, client->ibuf, 4); + mroute.ifindex = stream_getl(client->ibuf); - strcpy (sbuf, inet_ntoa (mroute.sg.src)); - strcpy (gbuf, inet_ntoa (mroute.sg.grp)); + strcpy(sbuf, inet_ntoa(mroute.sg.src)); + strcpy(gbuf, inet_ntoa(mroute.sg.grp)); - suc = kernel_get_ipmr_sg_stats (&mroute); + suc = kernel_get_ipmr_sg_stats(&mroute); - s = client->obuf; + s = client->obuf; - stream_reset (s); + stream_reset(s); - zserv_create_header (s, ZEBRA_IPMR_ROUTE_STATS, zvrf_id (zvrf)); - stream_put_in_addr (s, &mroute.sg.src); - stream_put_in_addr (s, &mroute.sg.grp); - stream_put (s, &mroute.lastused, sizeof (mroute.lastused)); - stream_putl (s, suc); + zserv_create_header(s, ZEBRA_IPMR_ROUTE_STATS, zvrf_id(zvrf)); + stream_put_in_addr(s, &mroute.sg.src); + stream_put_in_addr(s, &mroute.sg.grp); + stream_put(s, &mroute.lastused, sizeof(mroute.lastused)); + stream_putl(s, suc); - stream_putw_at (s, 0, stream_get_endp (s)); - zebra_server_send_message (client); - return 0; + stream_putw_at(s, 0, stream_get_endp(s)); + zebra_server_send_message(client); + return 0; } diff --git a/zebra/zebra_mroute.h b/zebra/zebra_mroute.h index eeaf9caf1..fda97e80d 100644 --- a/zebra/zebra_mroute.h +++ b/zebra/zebra_mroute.h @@ -23,12 +23,12 @@ #define __ZEBRA_MROUTE_H__ struct mcast_route_data { - struct prefix_sg sg; - unsigned int ifindex; - unsigned long long lastused; + struct prefix_sg sg; + unsigned int ifindex; + unsigned long long lastused; }; -int zebra_ipmr_route_stats (struct zserv *client, int sock, u_short length, struct zebra_vrf *zvf); +int zebra_ipmr_route_stats(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvf); #endif - diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index a5869585d..7014731e0 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -30,58 +30,54 @@ #include "zebra_vrf.h" #include "zebra_memory.h" -DEFINE_MTYPE(ZEBRA, ZEBRA_NS, "Zebra Name Space") +DEFINE_MTYPE(ZEBRA, ZEBRA_NS, "Zebra Name Space") struct zebra_ns *dzns; -struct zebra_ns * -zebra_ns_lookup (ns_id_t ns_id) +struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id) { - return dzns; + return dzns; } -int -zebra_ns_enable (ns_id_t ns_id, void **info) +int zebra_ns_enable(ns_id_t ns_id, void **info) { - struct zebra_ns *zns = (struct zebra_ns *) (*info); + struct zebra_ns *zns = (struct zebra_ns *)(*info); -#if defined (HAVE_RTADV) - rtadv_init (zns); +#if defined(HAVE_RTADV) + rtadv_init(zns); #endif - zns->if_table = route_table_init (); - kernel_init (zns); - interface_list (zns); - route_read (zns); + zns->if_table = route_table_init(); + kernel_init(zns); + interface_list(zns); + route_read(zns); - return 0; + return 0; } -int -zebra_ns_disable (ns_id_t ns_id, void **info) +int zebra_ns_disable(ns_id_t ns_id, void **info) { - struct zebra_ns *zns = (struct zebra_ns *) (*info); + struct zebra_ns *zns = (struct zebra_ns *)(*info); - route_table_finish (zns->if_table); -#if defined (HAVE_RTADV) - rtadv_terminate (zns); + route_table_finish(zns->if_table); +#if defined(HAVE_RTADV) + rtadv_terminate(zns); #endif - kernel_terminate (zns); + kernel_terminate(zns); - return 0; + return 0; } -int -zebra_ns_init (void) +int zebra_ns_init(void) { - dzns = XCALLOC (MTYPE_ZEBRA_NS, sizeof (struct zebra_ns)); + dzns = XCALLOC(MTYPE_ZEBRA_NS, sizeof(struct zebra_ns)); - ns_init (); + ns_init(); - zebra_vrf_init (); + zebra_vrf_init(); - zebra_ns_enable (0, (void **)&dzns); + zebra_ns_enable(0, (void **)&dzns); - return 0; + return 0; } diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h index 721b6c818..6cfba93e5 100644 --- a/zebra/zebra_ns.h +++ b/zebra/zebra_ns.h @@ -26,42 +26,40 @@ #ifdef HAVE_NETLINK /* Socket interface to kernel */ -struct nlsock -{ - int sock; - int seq; - struct sockaddr_nl snl; - char name[64]; +struct nlsock { + int sock; + int seq; + struct sockaddr_nl snl; + char name[64]; }; #endif -struct zebra_ns -{ - /* net-ns name. */ - char name[VRF_NAMSIZ]; +struct zebra_ns { + /* net-ns name. */ + char name[VRF_NAMSIZ]; - /* Identifier. */ - ns_id_t ns_id; + /* Identifier. */ + ns_id_t ns_id; #ifdef HAVE_NETLINK - struct nlsock netlink; /* kernel messages */ - struct nlsock netlink_cmd; /* command channel */ - struct thread *t_netlink; + struct nlsock netlink; /* kernel messages */ + struct nlsock netlink_cmd; /* command channel */ + struct thread *t_netlink; #endif - struct route_table *if_table; + struct route_table *if_table; -#if defined (HAVE_RTADV) - struct rtadv rtadv; +#if defined(HAVE_RTADV) + struct rtadv rtadv; #endif /* HAVE_RTADV */ }; #define NS_DEFAULT 0 #define NS_UNKNOWN UINT16_MAX -struct zebra_ns *zebra_ns_lookup (ns_id_t ns_id); +struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id); -int zebra_ns_init (void); -int zebra_ns_enable (ns_id_t ns_id, void **info); -int zebra_ns_disable (ns_id_t ns_id, void **info); +int zebra_ns_init(void); +int zebra_ns_enable(ns_id_t ns_id, void **info); +int zebra_ns_disable(ns_id_t ns_id, void **info); #endif diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 39779793f..1bf672d4a 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -19,7 +19,7 @@ */ #include <zebra.h> -#include <sys/un.h> /* for sockaddr_un */ +#include <sys/un.h> /* for sockaddr_un */ #include <net/if.h> #include "vty.h" #include "zebra/zserv.h" @@ -86,176 +86,169 @@ struct zebra_ptm_cb ptm_cb; static int zebra_ptm_socket_init(void); int zebra_ptm_sock_read(struct thread *); -static void zebra_ptm_install_commands (void); +static void zebra_ptm_install_commands(void); static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt); -void zebra_bfd_peer_replay_req (void); +void zebra_bfd_peer_replay_req(void); void zebra_ptm_send_status_req(void); void zebra_ptm_reset_status(int ptm_disable); const char ZEBRA_PTM_SOCK_NAME[] = "\0/var/run/ptmd.socket"; -void -zebra_ptm_init (void) +void zebra_ptm_init(void) { - char buf[64]; + char buf[64]; - memset(&ptm_cb, 0, sizeof(struct zebra_ptm_cb)); + memset(&ptm_cb, 0, sizeof(struct zebra_ptm_cb)); - ptm_cb.out_data = calloc(1, ZEBRA_PTM_SEND_MAX_SOCKBUF); - if (!ptm_cb.out_data) - { - zlog_warn("%s: Allocation of send data failed", __func__); - return; - } + ptm_cb.out_data = calloc(1, ZEBRA_PTM_SEND_MAX_SOCKBUF); + if (!ptm_cb.out_data) { + zlog_warn("%s: Allocation of send data failed", __func__); + return; + } - ptm_cb.in_data = calloc(1, ZEBRA_PTM_MAX_SOCKBUF); - if (!ptm_cb.in_data) - { - zlog_warn("%s: Allocation of recv data failed", __func__); - free(ptm_cb.out_data); - return; - } + ptm_cb.in_data = calloc(1, ZEBRA_PTM_MAX_SOCKBUF); + if (!ptm_cb.in_data) { + zlog_warn("%s: Allocation of recv data failed", __func__); + free(ptm_cb.out_data); + return; + } - ptm_cb.pid = getpid(); - zebra_ptm_install_commands(); + ptm_cb.pid = getpid(); + zebra_ptm_install_commands(); - sprintf(buf, "%s", FRR_PTM_NAME); - ptm_hdl = ptm_lib_register(buf, NULL, zebra_ptm_handle_msg_cb, - zebra_ptm_handle_msg_cb); - ptm_cb.wb = buffer_new(0); + sprintf(buf, "%s", FRR_PTM_NAME); + ptm_hdl = ptm_lib_register(buf, NULL, zebra_ptm_handle_msg_cb, + zebra_ptm_handle_msg_cb); + ptm_cb.wb = buffer_new(0); - ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; + ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; - ptm_cb.ptm_sock = -1; + ptm_cb.ptm_sock = -1; } -void -zebra_ptm_finish(void) +void zebra_ptm_finish(void) { - int proto; + int proto; - for (proto = 0; proto < ZEBRA_ROUTE_MAX; proto++) - if (CHECK_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG)) - zebra_ptm_bfd_client_deregister(proto); + for (proto = 0; proto < ZEBRA_ROUTE_MAX; proto++) + if (CHECK_FLAG(ptm_cb.client_flags[proto], + ZEBRA_PTM_BFD_CLIENT_FLAG_REG)) + zebra_ptm_bfd_client_deregister(proto); - buffer_flush_all(ptm_cb.wb, ptm_cb.ptm_sock); + buffer_flush_all(ptm_cb.wb, ptm_cb.ptm_sock); - free (ptm_hdl); + free(ptm_hdl); - if (ptm_cb.out_data) - free(ptm_cb.out_data); + if (ptm_cb.out_data) + free(ptm_cb.out_data); - if (ptm_cb.in_data) - free(ptm_cb.in_data); + if (ptm_cb.in_data) + free(ptm_cb.in_data); - /* Release threads. */ - if (ptm_cb.t_read) - thread_cancel (ptm_cb.t_read); - if (ptm_cb.t_write) - thread_cancel (ptm_cb.t_write); - if (ptm_cb.t_timer) - thread_cancel (ptm_cb.t_timer); + /* Release threads. */ + if (ptm_cb.t_read) + thread_cancel(ptm_cb.t_read); + if (ptm_cb.t_write) + thread_cancel(ptm_cb.t_write); + if (ptm_cb.t_timer) + thread_cancel(ptm_cb.t_timer); - if (ptm_cb.wb) - buffer_free(ptm_cb.wb); + if (ptm_cb.wb) + buffer_free(ptm_cb.wb); - if (ptm_cb.ptm_sock != -1) - close(ptm_cb.ptm_sock); + if (ptm_cb.ptm_sock != -1) + close(ptm_cb.ptm_sock); } -static int -zebra_ptm_flush_messages (struct thread *thread) +static int zebra_ptm_flush_messages(struct thread *thread) { - ptm_cb.t_write = NULL; - - if (ptm_cb.ptm_sock == -1) - return -1; - - errno = 0; - - switch (buffer_flush_available(ptm_cb.wb, ptm_cb.ptm_sock)) - { - case BUFFER_ERROR: - zlog_warn ("%s ptm socket error: %s", __func__, - safe_strerror (errno)); - close(ptm_cb.ptm_sock); - ptm_cb.ptm_sock = -1; - zebra_ptm_reset_status(0); - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return (-1); - case BUFFER_PENDING: - ptm_cb.t_write = NULL; - thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL, ptm_cb.ptm_sock, - &ptm_cb.t_write); - break; - case BUFFER_EMPTY: - break; - } - - return(0); + ptm_cb.t_write = NULL; + + if (ptm_cb.ptm_sock == -1) + return -1; + + errno = 0; + + switch (buffer_flush_available(ptm_cb.wb, ptm_cb.ptm_sock)) { + case BUFFER_ERROR: + zlog_warn("%s ptm socket error: %s", __func__, + safe_strerror(errno)); + close(ptm_cb.ptm_sock); + ptm_cb.ptm_sock = -1; + zebra_ptm_reset_status(0); + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + return (-1); + case BUFFER_PENDING: + ptm_cb.t_write = NULL; + thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL, + ptm_cb.ptm_sock, &ptm_cb.t_write); + break; + case BUFFER_EMPTY: + break; + } + + return (0); } -static int -zebra_ptm_send_message(char *data, int size) +static int zebra_ptm_send_message(char *data, int size) { - errno = 0; - switch (buffer_write(ptm_cb.wb, ptm_cb.ptm_sock, data, size)) - { - case BUFFER_ERROR: - zlog_warn ("%s ptm socket error: %s", __func__, safe_strerror (errno)); - close(ptm_cb.ptm_sock); - ptm_cb.ptm_sock = -1; - zebra_ptm_reset_status(0); - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return -1; - case BUFFER_EMPTY: - THREAD_OFF(ptm_cb.t_write); - break; - case BUFFER_PENDING: - thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL, - ptm_cb.ptm_sock, &ptm_cb.t_write); - break; - } - - return 0; + errno = 0; + switch (buffer_write(ptm_cb.wb, ptm_cb.ptm_sock, data, size)) { + case BUFFER_ERROR: + zlog_warn("%s ptm socket error: %s", __func__, + safe_strerror(errno)); + close(ptm_cb.ptm_sock); + ptm_cb.ptm_sock = -1; + zebra_ptm_reset_status(0); + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + return -1; + case BUFFER_EMPTY: + THREAD_OFF(ptm_cb.t_write); + break; + case BUFFER_PENDING: + thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL, + ptm_cb.ptm_sock, &ptm_cb.t_write); + break; + } + + return 0; } -int -zebra_ptm_connect (struct thread *t) +int zebra_ptm_connect(struct thread *t) { - int init = 0; - - if (ptm_cb.ptm_sock == -1) { - zebra_ptm_socket_init(); - init = 1; - } - - if (ptm_cb.ptm_sock != -1) { - if (init) { - ptm_cb.t_read = NULL; - thread_add_read(zebrad.master, zebra_ptm_sock_read, NULL, ptm_cb.ptm_sock, - &ptm_cb.t_read); - zebra_bfd_peer_replay_req(); - } - zebra_ptm_send_status_req(); - ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; - } else if (ptm_cb.reconnect_time < ZEBRA_PTM_RECONNECT_TIME_MAX){ - ptm_cb.reconnect_time *= 2; - if (ptm_cb.reconnect_time > ZEBRA_PTM_RECONNECT_TIME_MAX) - ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_MAX; - - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - } else if (ptm_cb.reconnect_time >= ZEBRA_PTM_RECONNECT_TIME_MAX){ - ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; - } - - return(errno); + int init = 0; + + if (ptm_cb.ptm_sock == -1) { + zebra_ptm_socket_init(); + init = 1; + } + + if (ptm_cb.ptm_sock != -1) { + if (init) { + ptm_cb.t_read = NULL; + thread_add_read(zebrad.master, zebra_ptm_sock_read, + NULL, ptm_cb.ptm_sock, &ptm_cb.t_read); + zebra_bfd_peer_replay_req(); + } + zebra_ptm_send_status_req(); + ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; + } else if (ptm_cb.reconnect_time < ZEBRA_PTM_RECONNECT_TIME_MAX) { + ptm_cb.reconnect_time *= 2; + if (ptm_cb.reconnect_time > ZEBRA_PTM_RECONNECT_TIME_MAX) + ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_MAX; + + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + } else if (ptm_cb.reconnect_time >= ZEBRA_PTM_RECONNECT_TIME_MAX) { + ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; + } + + return (errno); } DEFUN (zebra_ptm_enable, @@ -263,30 +256,28 @@ DEFUN (zebra_ptm_enable, "ptm-enable", "Enable neighbor check with specified topology\n") { - struct vrf *vrf; - struct listnode *i; - struct interface *ifp; - struct zebra_if *if_data; - - ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_ON; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, i, ifp)) - if (!ifp->ptm_enable) - { - if_data = (struct zebra_if *)ifp->info; - if (if_data && - (if_data->ptm_enable == ZEBRA_IF_PTM_ENABLE_UNSPEC)) - { - ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_ON; - } - /* Assign a default unknown status */ - ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; - } - - zebra_ptm_connect(NULL); - - return CMD_SUCCESS; + struct vrf *vrf; + struct listnode *i; + struct interface *ifp; + struct zebra_if *if_data; + + ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_ON; + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, i, ifp)) + if (!ifp->ptm_enable) { + if_data = (struct zebra_if *)ifp->info; + if (if_data && (if_data->ptm_enable + == ZEBRA_IF_PTM_ENABLE_UNSPEC)) { + ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_ON; + } + /* Assign a default unknown status */ + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + } + + zebra_ptm_connect(NULL); + + return CMD_SUCCESS; } DEFUN (no_zebra_ptm_enable, @@ -295,9 +286,9 @@ DEFUN (no_zebra_ptm_enable, NO_STR "Enable neighbor check with specified topology\n") { - ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; - zebra_ptm_reset_status(1); - return CMD_SUCCESS; + ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; + zebra_ptm_reset_status(1); + return CMD_SUCCESS; } DEFUN (zebra_ptm_enable_if, @@ -305,37 +296,34 @@ DEFUN (zebra_ptm_enable_if, "ptm-enable", "Enable neighbor check with specified topology\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *if_data; - int old_ptm_enable; - int send_linkdown = 0; - - if (ifp->ifindex == IFINDEX_INTERNAL) - { - return CMD_SUCCESS; - } - - old_ptm_enable = ifp->ptm_enable; - ifp->ptm_enable = ptm_cb.ptm_enable; - - if (if_is_no_ptm_operative(ifp)) - send_linkdown = 1; - - if (!old_ptm_enable && ptm_cb.ptm_enable) - { - if (!if_is_operative (ifp) && send_linkdown) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("%s: Bringing down interface %s\n", __func__, - ifp->name); - if_down (ifp); - } - } - - if_data = ifp->info; - if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC; - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *if_data; + int old_ptm_enable; + int send_linkdown = 0; + + if (ifp->ifindex == IFINDEX_INTERNAL) { + return CMD_SUCCESS; + } + + old_ptm_enable = ifp->ptm_enable; + ifp->ptm_enable = ptm_cb.ptm_enable; + + if (if_is_no_ptm_operative(ifp)) + send_linkdown = 1; + + if (!old_ptm_enable && ptm_cb.ptm_enable) { + if (!if_is_operative(ifp) && send_linkdown) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: Bringing down interface %s\n", + __func__, ifp->name); + if_down(ifp); + } + } + + if_data = ifp->info; + if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC; + + return CMD_SUCCESS; } DEFUN (no_zebra_ptm_enable_if, @@ -344,227 +332,224 @@ DEFUN (no_zebra_ptm_enable_if, NO_STR "Enable neighbor check with specified topology\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int send_linkup = 0; - struct zebra_if *if_data; - - if ((ifp->ifindex != IFINDEX_INTERNAL) && (ifp->ptm_enable)) - { - if (!if_is_operative(ifp)) - send_linkup = 1; - - ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; - if (if_is_no_ptm_operative (ifp) && send_linkup) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("%s: Bringing up interface %s\n", __func__, - ifp->name); - if_up (ifp); - } - } - - if_data = ifp->info; - if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int send_linkup = 0; + struct zebra_if *if_data; + + if ((ifp->ifindex != IFINDEX_INTERNAL) && (ifp->ptm_enable)) { + if (!if_is_operative(ifp)) + send_linkup = 1; + + ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; + if (if_is_no_ptm_operative(ifp) && send_linkup) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: Bringing up interface %s\n", + __func__, ifp->name); + if_up(ifp); + } + } + + if_data = ifp->info; + if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; + + return CMD_SUCCESS; } -void -zebra_ptm_write (struct vty *vty) +void zebra_ptm_write(struct vty *vty) { - if (ptm_cb.ptm_enable) - vty_out (vty, "ptm-enable\n"); + if (ptm_cb.ptm_enable) + vty_out(vty, "ptm-enable\n"); - return; + return; } -static int -zebra_ptm_socket_init (void) +static int zebra_ptm_socket_init(void) { - int ret; - int sock; - struct sockaddr_un addr; - - ptm_cb.ptm_sock = -1; - - sock = socket (PF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - return -1; - if (set_nonblocking(sock) < 0) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("%s: Unable to set socket non blocking[%s]", - __PRETTY_FUNCTION__, safe_strerror (errno)); - close (sock); - return -1; - } - - /* Make server socket. */ - memset (&addr, 0, sizeof (struct sockaddr_un)); - addr.sun_family = AF_UNIX; - memcpy (&addr.sun_path, ZEBRA_PTM_SOCK_NAME, - sizeof(ZEBRA_PTM_SOCK_NAME)); - - ret = connect(sock, (struct sockaddr *) &addr, - sizeof (addr.sun_family)+sizeof (ZEBRA_PTM_SOCK_NAME)-1); - if (ret < 0) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: Unable to connect to socket %s [%s]", - __func__, ZEBRA_PTM_SOCK_NAME, safe_strerror(errno)); - close (sock); - return -1; - } - ptm_cb.ptm_sock = sock; - return sock; + int ret; + int sock; + struct sockaddr_un addr; + + ptm_cb.ptm_sock = -1; + + sock = socket(PF_UNIX, SOCK_STREAM, 0); + if (sock < 0) + return -1; + if (set_nonblocking(sock) < 0) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: Unable to set socket non blocking[%s]", + __PRETTY_FUNCTION__, safe_strerror(errno)); + close(sock); + return -1; + } + + /* Make server socket. */ + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + memcpy(&addr.sun_path, ZEBRA_PTM_SOCK_NAME, + sizeof(ZEBRA_PTM_SOCK_NAME)); + + ret = connect(sock, (struct sockaddr *)&addr, + sizeof(addr.sun_family) + sizeof(ZEBRA_PTM_SOCK_NAME) + - 1); + if (ret < 0) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: Unable to connect to socket %s [%s]", + __func__, ZEBRA_PTM_SOCK_NAME, + safe_strerror(errno)); + close(sock); + return -1; + } + ptm_cb.ptm_sock = sock; + return sock; } -static void -zebra_ptm_install_commands (void) +static void zebra_ptm_install_commands(void) { - install_element (CONFIG_NODE, &zebra_ptm_enable_cmd); - install_element (CONFIG_NODE, &no_zebra_ptm_enable_cmd); - install_element (INTERFACE_NODE, &zebra_ptm_enable_if_cmd); - install_element (INTERFACE_NODE, &no_zebra_ptm_enable_if_cmd); + install_element(CONFIG_NODE, &zebra_ptm_enable_cmd); + install_element(CONFIG_NODE, &no_zebra_ptm_enable_cmd); + install_element(INTERFACE_NODE, &zebra_ptm_enable_if_cmd); + install_element(INTERFACE_NODE, &no_zebra_ptm_enable_if_cmd); } /* BFD session goes down, send message to the protocols. */ -static void -if_bfd_session_update (struct interface *ifp, struct prefix *dp, - struct prefix *sp, int status, vrf_id_t vrf_id) +static void if_bfd_session_update(struct interface *ifp, struct prefix *dp, + struct prefix *sp, int status, + vrf_id_t vrf_id) { - if (IS_ZEBRA_DEBUG_EVENT) - { - char buf[2][INET6_ADDRSTRLEN]; - - if (ifp) - { - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d on %s" - " %s event", - inet_ntop (dp->family, &dp->u.prefix, buf[0], - INET6_ADDRSTRLEN), dp->prefixlen, ifp->name, - bfd_get_status_str(status)); - } - else - { - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d " - "with src %s/%d and vrf %d %s event", - inet_ntop (dp->family, &dp->u.prefix, buf[0], INET6_ADDRSTRLEN), - dp->prefixlen, - inet_ntop (sp->family, &sp->u.prefix, buf[1], INET6_ADDRSTRLEN), - sp->prefixlen, vrf_id, bfd_get_status_str(status)); - } - } - - zebra_interface_bfd_update (ifp, dp, sp, status, vrf_id); + if (IS_ZEBRA_DEBUG_EVENT) { + char buf[2][INET6_ADDRSTRLEN]; + + if (ifp) { + zlog_debug( + "MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d on %s" + " %s event", + inet_ntop(dp->family, &dp->u.prefix, buf[0], + INET6_ADDRSTRLEN), + dp->prefixlen, ifp->name, + bfd_get_status_str(status)); + } else { + zlog_debug( + "MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d " + "with src %s/%d and vrf %d %s event", + inet_ntop(dp->family, &dp->u.prefix, buf[0], + INET6_ADDRSTRLEN), + dp->prefixlen, + inet_ntop(sp->family, &sp->u.prefix, buf[1], + INET6_ADDRSTRLEN), + sp->prefixlen, vrf_id, + bfd_get_status_str(status)); + } + } + + zebra_interface_bfd_update(ifp, dp, sp, status, vrf_id); } -static int -zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt, struct interface *ifp) +static int zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt, + struct interface *ifp) { - char bfdst_str[32]; - char dest_str[64]; - char src_str[64]; - char vrf_str[64]; - struct prefix dest_prefix; - struct prefix src_prefix; - vrf_id_t vrf_id; - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSTATUS_STR, bfdst_str); - - if (bfdst_str[0] == '\0') { - return -1; - } - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDDEST_STR, dest_str); - - if (dest_str[0] == '\0') { - zlog_debug("%s: Key %s not found in PTM msg", __func__, - ZEBRA_PTM_BFDDEST_STR); - return -1; - } - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSRC_STR, src_str); - - if (src_str[0] == '\0') { - zlog_debug("%s: Key %s not found in PTM msg", __func__, - ZEBRA_PTM_BFDSRC_STR); - return -1; - } - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDVRF_STR, vrf_str); - - if (vrf_str[0] == '\0') { - zlog_debug("%s: Key %s not found in PTM msg", __func__, - ZEBRA_PTM_BFDVRF_STR); - return -1; - } - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: Recv Port [%s] bfd status [%s] vrf [%s]" - " peer [%s] local [%s]", - __func__, ifp ? ifp->name : "N/A", bfdst_str, - vrf_str, dest_str, src_str); - - if (str2prefix(dest_str, &dest_prefix) == 0) { - zlog_err("%s: Peer addr %s not found", __func__, - dest_str); - return -1; - } - - memset(&src_prefix, 0, sizeof(struct prefix)); - if (strcmp(ZEBRA_PTM_INVALID_SRC_IP, src_str)) { - if (str2prefix(src_str, &src_prefix) == 0) { - zlog_err("%s: Local addr %s not found", __func__, - src_str); - return -1; - } - } - - if (!strcmp(ZEBRA_PTM_INVALID_VRF, vrf_str) && ifp) { - vrf_id = ifp->vrf_id; - } else { - vrf_id = vrf_name_to_id(vrf_str); - } - - if (!strcmp (bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) { - if_bfd_session_update(ifp, &dest_prefix, &src_prefix, BFD_STATUS_DOWN, - vrf_id); - } else { - if_bfd_session_update(ifp, &dest_prefix, &src_prefix, BFD_STATUS_UP, - vrf_id); - } - - return 0; + char bfdst_str[32]; + char dest_str[64]; + char src_str[64]; + char vrf_str[64]; + struct prefix dest_prefix; + struct prefix src_prefix; + vrf_id_t vrf_id; + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSTATUS_STR, bfdst_str); + + if (bfdst_str[0] == '\0') { + return -1; + } + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDDEST_STR, dest_str); + + if (dest_str[0] == '\0') { + zlog_debug("%s: Key %s not found in PTM msg", __func__, + ZEBRA_PTM_BFDDEST_STR); + return -1; + } + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSRC_STR, src_str); + + if (src_str[0] == '\0') { + zlog_debug("%s: Key %s not found in PTM msg", __func__, + ZEBRA_PTM_BFDSRC_STR); + return -1; + } + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDVRF_STR, vrf_str); + + if (vrf_str[0] == '\0') { + zlog_debug("%s: Key %s not found in PTM msg", __func__, + ZEBRA_PTM_BFDVRF_STR); + return -1; + } + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s: Recv Port [%s] bfd status [%s] vrf [%s]" + " peer [%s] local [%s]", + __func__, ifp ? ifp->name : "N/A", bfdst_str, vrf_str, + dest_str, src_str); + + if (str2prefix(dest_str, &dest_prefix) == 0) { + zlog_err("%s: Peer addr %s not found", __func__, dest_str); + return -1; + } + + memset(&src_prefix, 0, sizeof(struct prefix)); + if (strcmp(ZEBRA_PTM_INVALID_SRC_IP, src_str)) { + if (str2prefix(src_str, &src_prefix) == 0) { + zlog_err("%s: Local addr %s not found", __func__, + src_str); + return -1; + } + } + + if (!strcmp(ZEBRA_PTM_INVALID_VRF, vrf_str) && ifp) { + vrf_id = ifp->vrf_id; + } else { + vrf_id = vrf_name_to_id(vrf_str); + } + + if (!strcmp(bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) { + if_bfd_session_update(ifp, &dest_prefix, &src_prefix, + BFD_STATUS_DOWN, vrf_id); + } else { + if_bfd_session_update(ifp, &dest_prefix, &src_prefix, + BFD_STATUS_UP, vrf_id); + } + + return 0; } -static int -zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt, struct interface *ifp, - char *cbl_str) +static int zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt, + struct interface *ifp, char *cbl_str) { - int send_linkup = 0; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: Recv Port [%s] cbl status [%s]", __func__, - ifp->name, cbl_str); - - if (!strcmp(cbl_str, ZEBRA_PTM_PASS_STR) && - (ifp->ptm_status != ZEBRA_PTM_STATUS_UP)) { - - if (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN) - send_linkup = 1; - ifp->ptm_status = ZEBRA_PTM_STATUS_UP; - if (ifp->ptm_enable && if_is_no_ptm_operative (ifp) && send_linkup) - if_up (ifp); - } else if (!strcmp (cbl_str, ZEBRA_PTM_FAIL_STR) && - (ifp->ptm_status != ZEBRA_PTM_STATUS_DOWN)) { - ifp->ptm_status = ZEBRA_PTM_STATUS_DOWN; - if (ifp->ptm_enable && if_is_no_ptm_operative (ifp)) - if_down (ifp); - } - - return 0; + int send_linkup = 0; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: Recv Port [%s] cbl status [%s]", __func__, + ifp->name, cbl_str); + + if (!strcmp(cbl_str, ZEBRA_PTM_PASS_STR) + && (ifp->ptm_status != ZEBRA_PTM_STATUS_UP)) { + + if (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN) + send_linkup = 1; + ifp->ptm_status = ZEBRA_PTM_STATUS_UP; + if (ifp->ptm_enable && if_is_no_ptm_operative(ifp) + && send_linkup) + if_up(ifp); + } else if (!strcmp(cbl_str, ZEBRA_PTM_FAIL_STR) + && (ifp->ptm_status != ZEBRA_PTM_STATUS_DOWN)) { + ifp->ptm_status = ZEBRA_PTM_STATUS_DOWN; + if (ifp->ptm_enable && if_is_no_ptm_operative(ifp)) + if_down(ifp); + } + + return 0; } /* @@ -584,582 +569,563 @@ zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt, struct interface *ifp, * processing all the notifications from the PTM. * */ -static int -zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt) +static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt) { - struct interface *ifp = NULL; - char port_str[128]; - char cbl_str[32]; - char cmd_status_str[32]; - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CMD_STATUS_STR, cmd_status_str); - - /* Drop command response messages */ - if (cmd_status_str[0] != '\0') { - return 0; - } - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_PORT_STR, port_str); - - if (port_str[0] == '\0') { - zlog_debug("%s: Key %s not found in PTM msg", __func__, - ZEBRA_PTM_PORT_STR); - return -1; - } - - if (strcmp(ZEBRA_PTM_INVALID_PORT_NAME, port_str)) { - ifp = if_lookup_by_name_all_vrf(port_str); - - if (!ifp) { - zlog_err("%s: %s not found in interface list", __func__, port_str); - return -1; - } - } - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CBL_STR, cbl_str); - - if (cbl_str[0] == '\0') { - return zebra_ptm_handle_bfd_msg(arg, in_ctxt, ifp); - } else { - if (ifp) { - return zebra_ptm_handle_cbl_msg(arg, in_ctxt, ifp, cbl_str); - } else { - return -1; - } - } + struct interface *ifp = NULL; + char port_str[128]; + char cbl_str[32]; + char cmd_status_str[32]; + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CMD_STATUS_STR, + cmd_status_str); + + /* Drop command response messages */ + if (cmd_status_str[0] != '\0') { + return 0; + } + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_PORT_STR, port_str); + + if (port_str[0] == '\0') { + zlog_debug("%s: Key %s not found in PTM msg", __func__, + ZEBRA_PTM_PORT_STR); + return -1; + } + + if (strcmp(ZEBRA_PTM_INVALID_PORT_NAME, port_str)) { + ifp = if_lookup_by_name_all_vrf(port_str); + + if (!ifp) { + zlog_err("%s: %s not found in interface list", __func__, + port_str); + return -1; + } + } + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CBL_STR, cbl_str); + + if (cbl_str[0] == '\0') { + return zebra_ptm_handle_bfd_msg(arg, in_ctxt, ifp); + } else { + if (ifp) { + return zebra_ptm_handle_cbl_msg(arg, in_ctxt, ifp, + cbl_str); + } else { + return -1; + } + } } -int -zebra_ptm_sock_read (struct thread *thread) +int zebra_ptm_sock_read(struct thread *thread) { - int sock, done = 0; - int rc; - - errno = 0; - sock = THREAD_FD (thread); - - if (sock == -1) - return -1; - - /* PTM communicates in CSV format */ - while(!done) { - rc = ptm_lib_process_msg(ptm_hdl, sock, ptm_cb.in_data, ZEBRA_PTM_MAX_SOCKBUF, - NULL); - if (rc <= 0) - break; - } - - if (rc <= 0) { - if (((rc == 0) && !errno) || (errno && (errno != EWOULDBLOCK) && (errno != EAGAIN))) { - zlog_warn ("%s routing socket error: %s(%d) bytes %d", __func__, - safe_strerror (errno), errno, rc); - - close (ptm_cb.ptm_sock); - ptm_cb.ptm_sock = -1; - zebra_ptm_reset_status(0); - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return (-1); - } - } - - ptm_cb.t_read = NULL; - thread_add_read(zebrad.master, zebra_ptm_sock_read, NULL, ptm_cb.ptm_sock, - &ptm_cb.t_read); - - return 0; + int sock, done = 0; + int rc; + + errno = 0; + sock = THREAD_FD(thread); + + if (sock == -1) + return -1; + + /* PTM communicates in CSV format */ + while (!done) { + rc = ptm_lib_process_msg(ptm_hdl, sock, ptm_cb.in_data, + ZEBRA_PTM_MAX_SOCKBUF, NULL); + if (rc <= 0) + break; + } + + if (rc <= 0) { + if (((rc == 0) && !errno) + || (errno && (errno != EWOULDBLOCK) && (errno != EAGAIN))) { + zlog_warn("%s routing socket error: %s(%d) bytes %d", + __func__, safe_strerror(errno), errno, rc); + + close(ptm_cb.ptm_sock); + ptm_cb.ptm_sock = -1; + zebra_ptm_reset_status(0); + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, + &ptm_cb.t_timer); + return (-1); + } + } + + ptm_cb.t_read = NULL; + thread_add_read(zebrad.master, zebra_ptm_sock_read, NULL, + ptm_cb.ptm_sock, &ptm_cb.t_read); + + return 0; } /* BFD peer/dst register/update */ -int -zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length, - int command, struct zebra_vrf *zvrf) +int zebra_ptm_bfd_dst_register(struct zserv *client, int sock, u_short length, + int command, struct zebra_vrf *zvrf) { - struct stream *s; - struct prefix src_p; - struct prefix dst_p; - u_char multi_hop; - u_char multi_hop_cnt; - u_char detect_mul; - unsigned int min_rx_timer; - unsigned int min_tx_timer; - char if_name[INTERFACE_NAMSIZ]; - u_char len; - void *out_ctxt; - char buf[INET6_ADDRSTRLEN]; - char tmp_buf[64]; - int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; - unsigned int pid; - - if (command == ZEBRA_BFD_DEST_UPDATE) - client->bfd_peer_upd8_cnt++; - else - client->bfd_peer_add_cnt++; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("bfd_dst_register msg from client %s: length=%d", - zebra_route_string(client->proto), length); - - if (ptm_cb.ptm_sock == -1) - { - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return -1; - } - - ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); - sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_START_CMD); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); - sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, - tmp_buf); - - s = client->ibuf; - - pid = stream_getl(s); - sprintf(tmp_buf, "%d", pid); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, tmp_buf); - - dst_p.family = stream_getw(s); - - if (dst_p.family == AF_INET) - dst_p.prefixlen = IPV4_MAX_BYTELEN; - else - dst_p.prefixlen = IPV6_MAX_BYTELEN; - - stream_get(&dst_p.u.prefix, s, dst_p.prefixlen); - if (dst_p.family == AF_INET) - { - inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DST_IP_FIELD, buf); - } - else - { - inet_ntop(AF_INET6, &dst_p.u.prefix6, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DST_IP_FIELD, buf); - } - - min_rx_timer = stream_getl(s); - sprintf(tmp_buf, "%d", min_rx_timer); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_RX_FIELD, - tmp_buf); - min_tx_timer = stream_getl(s); - sprintf(tmp_buf, "%d", min_tx_timer); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_TX_FIELD, - tmp_buf); - detect_mul = stream_getc(s); - sprintf(tmp_buf, "%d", detect_mul); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DETECT_MULT_FIELD, - tmp_buf); - - multi_hop = stream_getc(s); - if (multi_hop) - { - sprintf(tmp_buf, "%d", 1); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MULTI_HOP_FIELD, - tmp_buf); - src_p.family = stream_getw(s); - - if (src_p.family == AF_INET) - src_p.prefixlen = IPV4_MAX_BYTELEN; - else - src_p.prefixlen = IPV6_MAX_BYTELEN; - - stream_get(&src_p.u.prefix, s, src_p.prefixlen); - if (src_p.family == AF_INET) - { - inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - } - else - { - inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - } - - multi_hop_cnt = stream_getc(s); - sprintf(tmp_buf, "%d", multi_hop_cnt); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD, - tmp_buf); - - if (zvrf_id (zvrf) != VRF_DEFAULT) - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_VRF_NAME_FIELD, - zvrf_name (zvrf)); - } - else - { - if (dst_p.family == AF_INET6) - { - src_p.family = stream_getw(s); - - if (src_p.family == AF_INET) - src_p.prefixlen = IPV4_MAX_BYTELEN; - else - src_p.prefixlen = IPV6_MAX_BYTELEN; - - stream_get(&src_p.u.prefix, s, src_p.prefixlen); - if (src_p.family == AF_INET) - { - inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - } - else - { - inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - } - } - len = stream_getc(s); - stream_get(if_name, s, len); - if_name[len] = '\0'; - - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_IFNAME_FIELD, - if_name); - } - - sprintf(tmp_buf, "%d", 1); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEND_EVENT, - tmp_buf); - - ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); - - if (IS_ZEBRA_DEBUG_SEND) - zlog_debug ("%s: Sent message (%d) %s", __func__, data_len, - ptm_cb.out_data); - zebra_ptm_send_message(ptm_cb.out_data, data_len); - return 0; + struct stream *s; + struct prefix src_p; + struct prefix dst_p; + u_char multi_hop; + u_char multi_hop_cnt; + u_char detect_mul; + unsigned int min_rx_timer; + unsigned int min_tx_timer; + char if_name[INTERFACE_NAMSIZ]; + u_char len; + void *out_ctxt; + char buf[INET6_ADDRSTRLEN]; + char tmp_buf[64]; + int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; + unsigned int pid; + + if (command == ZEBRA_BFD_DEST_UPDATE) + client->bfd_peer_upd8_cnt++; + else + client->bfd_peer_add_cnt++; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("bfd_dst_register msg from client %s: length=%d", + zebra_route_string(client->proto), length); + + if (ptm_cb.ptm_sock == -1) { + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + return -1; + } + + ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); + sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_START_CMD); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); + sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, + tmp_buf); + + s = client->ibuf; + + pid = stream_getl(s); + sprintf(tmp_buf, "%d", pid); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, + tmp_buf); + + dst_p.family = stream_getw(s); + + if (dst_p.family == AF_INET) + dst_p.prefixlen = IPV4_MAX_BYTELEN; + else + dst_p.prefixlen = IPV6_MAX_BYTELEN; + + stream_get(&dst_p.u.prefix, s, dst_p.prefixlen); + if (dst_p.family == AF_INET) { + inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_DST_IP_FIELD, buf); + } else { + inet_ntop(AF_INET6, &dst_p.u.prefix6, buf, sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_DST_IP_FIELD, buf); + } + + min_rx_timer = stream_getl(s); + sprintf(tmp_buf, "%d", min_rx_timer); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_RX_FIELD, + tmp_buf); + min_tx_timer = stream_getl(s); + sprintf(tmp_buf, "%d", min_tx_timer); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_TX_FIELD, + tmp_buf); + detect_mul = stream_getc(s); + sprintf(tmp_buf, "%d", detect_mul); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DETECT_MULT_FIELD, + tmp_buf); + + multi_hop = stream_getc(s); + if (multi_hop) { + sprintf(tmp_buf, "%d", 1); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_MULTI_HOP_FIELD, tmp_buf); + src_p.family = stream_getw(s); + + if (src_p.family == AF_INET) + src_p.prefixlen = IPV4_MAX_BYTELEN; + else + src_p.prefixlen = IPV6_MAX_BYTELEN; + + stream_get(&src_p.u.prefix, s, src_p.prefixlen); + if (src_p.family == AF_INET) { + inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); + } else { + inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); + } + + multi_hop_cnt = stream_getc(s); + sprintf(tmp_buf, "%d", multi_hop_cnt); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD, tmp_buf); + + if (zvrf_id(zvrf) != VRF_DEFAULT) + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_VRF_NAME_FIELD, + zvrf_name(zvrf)); + } else { + if (dst_p.family == AF_INET6) { + src_p.family = stream_getw(s); + + if (src_p.family == AF_INET) + src_p.prefixlen = IPV4_MAX_BYTELEN; + else + src_p.prefixlen = IPV6_MAX_BYTELEN; + + stream_get(&src_p.u.prefix, s, src_p.prefixlen); + if (src_p.family == AF_INET) { + inet_ntop(AF_INET, &src_p.u.prefix4, buf, + sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, + buf); + } else { + inet_ntop(AF_INET6, &src_p.u.prefix6, buf, + sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, + buf); + } + } + len = stream_getc(s); + stream_get(if_name, s, len); + if_name[len] = '\0'; + + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_IFNAME_FIELD, if_name); + } + + sprintf(tmp_buf, "%d", 1); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEND_EVENT, + tmp_buf); + + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); + + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug("%s: Sent message (%d) %s", __func__, data_len, + ptm_cb.out_data); + zebra_ptm_send_message(ptm_cb.out_data, data_len); + return 0; } /* BFD peer/dst deregister */ -int -zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length, - struct zebra_vrf *zvrf) +int zebra_ptm_bfd_dst_deregister(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { - struct stream *s; - struct prefix src_p; - struct prefix dst_p; - u_char multi_hop; - char if_name[INTERFACE_NAMSIZ]; - u_char len; - char buf[INET6_ADDRSTRLEN]; - char tmp_buf[64]; - int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; - void *out_ctxt; - unsigned int pid; - - client->bfd_peer_del_cnt++; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("bfd_dst_deregister msg from client %s: length=%d", - zebra_route_string(client->proto), length); - - if (ptm_cb.ptm_sock == -1) - { - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return -1; - } - - ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); - - sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_STOP_CMD); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); - - sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, - tmp_buf); - - s = client->ibuf; - - pid = stream_getl(s); - sprintf(tmp_buf, "%d", pid); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, tmp_buf); - - dst_p.family = stream_getw(s); - - if (dst_p.family == AF_INET) - dst_p.prefixlen = IPV4_MAX_BYTELEN; - else - dst_p.prefixlen = IPV6_MAX_BYTELEN; - - stream_get(&dst_p.u.prefix, s, dst_p.prefixlen); - if (dst_p.family == AF_INET) - inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf)); - else - inet_ntop(AF_INET6, &dst_p.u.prefix6, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DST_IP_FIELD, buf); - - - multi_hop = stream_getc(s); - if (multi_hop) - { - sprintf(tmp_buf, "%d", 1); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MULTI_HOP_FIELD, - tmp_buf); - - src_p.family = stream_getw(s); - - if (src_p.family == AF_INET) - src_p.prefixlen = IPV4_MAX_BYTELEN; - else - src_p.prefixlen = IPV6_MAX_BYTELEN; - - stream_get(&src_p.u.prefix, s, src_p.prefixlen); - if (src_p.family == AF_INET) - inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); - else - inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - - if (zvrf_id (zvrf) != VRF_DEFAULT) - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_VRF_NAME_FIELD, - zvrf_name (zvrf)); - } - else - { - if (dst_p.family == AF_INET6) - { - src_p.family = stream_getw(s); - - if (src_p.family == AF_INET) - src_p.prefixlen = IPV4_MAX_BYTELEN; - else - src_p.prefixlen = IPV6_MAX_BYTELEN; - - stream_get(&src_p.u.prefix, s, src_p.prefixlen); - if (src_p.family == AF_INET) - { - inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - } - else - { - inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - } - } - - len = stream_getc(s); - stream_get(if_name, s, len); - if_name[len] = '\0'; - - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_IFNAME_FIELD, - if_name); - } - - ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); - if (IS_ZEBRA_DEBUG_SEND) - zlog_debug ("%s: Sent message (%d) %s", __func__, data_len, - ptm_cb.out_data); - - zebra_ptm_send_message(ptm_cb.out_data, data_len); - return 0; + struct stream *s; + struct prefix src_p; + struct prefix dst_p; + u_char multi_hop; + char if_name[INTERFACE_NAMSIZ]; + u_char len; + char buf[INET6_ADDRSTRLEN]; + char tmp_buf[64]; + int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; + void *out_ctxt; + unsigned int pid; + + client->bfd_peer_del_cnt++; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("bfd_dst_deregister msg from client %s: length=%d", + zebra_route_string(client->proto), length); + + if (ptm_cb.ptm_sock == -1) { + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + return -1; + } + + ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); + + sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_STOP_CMD); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); + + sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, + tmp_buf); + + s = client->ibuf; + + pid = stream_getl(s); + sprintf(tmp_buf, "%d", pid); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, + tmp_buf); + + dst_p.family = stream_getw(s); + + if (dst_p.family == AF_INET) + dst_p.prefixlen = IPV4_MAX_BYTELEN; + else + dst_p.prefixlen = IPV6_MAX_BYTELEN; + + stream_get(&dst_p.u.prefix, s, dst_p.prefixlen); + if (dst_p.family == AF_INET) + inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf)); + else + inet_ntop(AF_INET6, &dst_p.u.prefix6, buf, sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DST_IP_FIELD, buf); + + + multi_hop = stream_getc(s); + if (multi_hop) { + sprintf(tmp_buf, "%d", 1); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_MULTI_HOP_FIELD, tmp_buf); + + src_p.family = stream_getw(s); + + if (src_p.family == AF_INET) + src_p.prefixlen = IPV4_MAX_BYTELEN; + else + src_p.prefixlen = IPV6_MAX_BYTELEN; + + stream_get(&src_p.u.prefix, s, src_p.prefixlen); + if (src_p.family == AF_INET) + inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); + else + inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); + + if (zvrf_id(zvrf) != VRF_DEFAULT) + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_VRF_NAME_FIELD, + zvrf_name(zvrf)); + } else { + if (dst_p.family == AF_INET6) { + src_p.family = stream_getw(s); + + if (src_p.family == AF_INET) + src_p.prefixlen = IPV4_MAX_BYTELEN; + else + src_p.prefixlen = IPV6_MAX_BYTELEN; + + stream_get(&src_p.u.prefix, s, src_p.prefixlen); + if (src_p.family == AF_INET) { + inet_ntop(AF_INET, &src_p.u.prefix4, buf, + sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, + buf); + } else { + inet_ntop(AF_INET6, &src_p.u.prefix6, buf, + sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, + buf); + } + } + + len = stream_getc(s); + stream_get(if_name, s, len); + if_name[len] = '\0'; + + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_IFNAME_FIELD, if_name); + } + + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug("%s: Sent message (%d) %s", __func__, data_len, + ptm_cb.out_data); + + zebra_ptm_send_message(ptm_cb.out_data, data_len); + return 0; } /* BFD client register */ -int -zebra_ptm_bfd_client_register (struct zserv *client, int sock, u_short length) +int zebra_ptm_bfd_client_register(struct zserv *client, int sock, + u_short length) { - struct stream *s; - unsigned int pid; - void *out_ctxt; - char tmp_buf[64]; - int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; + struct stream *s; + unsigned int pid; + void *out_ctxt; + char tmp_buf[64]; + int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; - client->bfd_client_reg_cnt++; + client->bfd_client_reg_cnt++; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("bfd_client_register msg from client %s: length=%d", - zebra_route_string(client->proto), length); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("bfd_client_register msg from client %s: length=%d", + zebra_route_string(client->proto), length); - if (ptm_cb.ptm_sock == -1) - { - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return -1; - } + if (ptm_cb.ptm_sock == -1) { + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + return -1; + } - ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); + ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); - sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_REG_CMD); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); + sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_REG_CMD); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); - sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, - tmp_buf); + sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, + tmp_buf); - s = client->ibuf; + s = client->ibuf; - pid = stream_getl(s); - sprintf(tmp_buf, "%d", pid); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, - tmp_buf); + pid = stream_getl(s); + sprintf(tmp_buf, "%d", pid); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, + tmp_buf); - ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); - if (IS_ZEBRA_DEBUG_SEND) - zlog_debug ("%s: Sent message (%d) %s", __func__, data_len, - ptm_cb.out_data); - zebra_ptm_send_message(ptm_cb.out_data, data_len); + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug("%s: Sent message (%d) %s", __func__, data_len, + ptm_cb.out_data); + zebra_ptm_send_message(ptm_cb.out_data, data_len); - SET_FLAG(ptm_cb.client_flags[client->proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG); - return 0; + SET_FLAG(ptm_cb.client_flags[client->proto], + ZEBRA_PTM_BFD_CLIENT_FLAG_REG); + return 0; } /* BFD client deregister */ -void -zebra_ptm_bfd_client_deregister (int proto) +void zebra_ptm_bfd_client_deregister(int proto) { - void *out_ctxt; - char tmp_buf[64]; - int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; + void *out_ctxt; + char tmp_buf[64]; + int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; - if (proto != ZEBRA_ROUTE_OSPF && proto != ZEBRA_ROUTE_BGP - && proto != ZEBRA_ROUTE_OSPF6 && proto != ZEBRA_ROUTE_PIM) - return; + if (proto != ZEBRA_ROUTE_OSPF && proto != ZEBRA_ROUTE_BGP + && proto != ZEBRA_ROUTE_OSPF6 && proto != ZEBRA_ROUTE_PIM) + return; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_err("bfd_client_deregister msg for client %s", - zebra_route_string(proto)); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_err("bfd_client_deregister msg for client %s", + zebra_route_string(proto)); - if (ptm_cb.ptm_sock == -1) - { - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return; - } + if (ptm_cb.ptm_sock == -1) { + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + return; + } - ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); + ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); - sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_DEREG_CMD); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); + sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_DEREG_CMD); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); - sprintf(tmp_buf, "%s", zebra_route_string(proto)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, - tmp_buf); + sprintf(tmp_buf, "%s", zebra_route_string(proto)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, + tmp_buf); - ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); - if (IS_ZEBRA_DEBUG_SEND) - zlog_debug ("%s: Sent message (%d) %s", __func__, data_len, - ptm_cb.out_data); + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug("%s: Sent message (%d) %s", __func__, data_len, + ptm_cb.out_data); - zebra_ptm_send_message(ptm_cb.out_data, data_len); - UNSET_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG); + zebra_ptm_send_message(ptm_cb.out_data, data_len); + UNSET_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG); } -int -zebra_ptm_get_enable_state(void) +int zebra_ptm_get_enable_state(void) { - return ptm_cb.ptm_enable; + return ptm_cb.ptm_enable; } /* * zebra_ptm_get_status_str - Convert status to a display string. */ -static const char * -zebra_ptm_get_status_str(int status) +static const char *zebra_ptm_get_status_str(int status) { - switch (status) - { - case ZEBRA_PTM_STATUS_DOWN: - return "fail"; - case ZEBRA_PTM_STATUS_UP: - return "pass"; - case ZEBRA_PTM_STATUS_UNKNOWN: - default: - return "n/a"; - } + switch (status) { + case ZEBRA_PTM_STATUS_DOWN: + return "fail"; + case ZEBRA_PTM_STATUS_UP: + return "pass"; + case ZEBRA_PTM_STATUS_UNKNOWN: + default: + return "n/a"; + } } -void -zebra_ptm_show_status(struct vty *vty, struct interface *ifp) +void zebra_ptm_show_status(struct vty *vty, struct interface *ifp) { - vty_out (vty, " PTM status: "); - if (ifp->ptm_enable) { - vty_out (vty, "%s\n",zebra_ptm_get_status_str(ifp->ptm_status)); - } else { - vty_out (vty, "disabled\n"); - } + vty_out(vty, " PTM status: "); + if (ifp->ptm_enable) { + vty_out(vty, "%s\n", zebra_ptm_get_status_str(ifp->ptm_status)); + } else { + vty_out(vty, "disabled\n"); + } } -void -zebra_ptm_send_status_req(void) +void zebra_ptm_send_status_req(void) { - void *out_ctxt; - int len = ZEBRA_PTM_SEND_MAX_SOCKBUF; - - if (ptm_cb.ptm_enable) - { - ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, - ZEBRA_PTM_GET_STATUS_CMD); - ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &len); - - zebra_ptm_send_message(ptm_cb.out_data, len); - } + void *out_ctxt; + int len = ZEBRA_PTM_SEND_MAX_SOCKBUF; + + if (ptm_cb.ptm_enable) { + ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, + &out_ctxt); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, + ZEBRA_PTM_GET_STATUS_CMD); + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &len); + + zebra_ptm_send_message(ptm_cb.out_data, len); + } } -void -zebra_ptm_reset_status(int ptm_disable) +void zebra_ptm_reset_status(int ptm_disable) { - struct vrf *vrf; - struct listnode *i; - struct interface *ifp; - int send_linkup; - - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, i, ifp)) - { - send_linkup = 0; - if (ifp->ptm_enable) - { - if (!if_is_operative(ifp)) - send_linkup = 1; - - if (ptm_disable) - ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; - ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; - - if (if_is_operative (ifp) && send_linkup) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("%s: Bringing up interface %s", __func__, - ifp->name); - if_up (ifp); - } - } - } + struct vrf *vrf; + struct listnode *i; + struct interface *ifp; + int send_linkup; + + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, i, ifp)) { + send_linkup = 0; + if (ifp->ptm_enable) { + if (!if_is_operative(ifp)) + send_linkup = 1; + + if (ptm_disable) + ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + + if (if_is_operative(ifp) && send_linkup) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s: Bringing up interface %s", + __func__, ifp->name); + if_up(ifp); + } + } + } } -void -zebra_ptm_if_init(struct zebra_if *zebra_ifp) +void zebra_ptm_if_init(struct zebra_if *zebra_ifp) { - zebra_ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC; + zebra_ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC; } -void -zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp) +void zebra_ptm_if_set_ptm_state(struct interface *ifp, + struct zebra_if *zebra_ifp) { - if (zebra_ifp && zebra_ifp->ptm_enable != ZEBRA_IF_PTM_ENABLE_UNSPEC) - ifp->ptm_enable = zebra_ifp->ptm_enable; + if (zebra_ifp && zebra_ifp->ptm_enable != ZEBRA_IF_PTM_ENABLE_UNSPEC) + ifp->ptm_enable = zebra_ifp->ptm_enable; } -void -zebra_ptm_if_write (struct vty *vty, struct zebra_if *zebra_ifp) +void zebra_ptm_if_write(struct vty *vty, struct zebra_if *zebra_ifp) { - if (zebra_ifp->ptm_enable == ZEBRA_IF_PTM_ENABLE_OFF) - vty_out (vty, " no ptm-enable\n"); + if (zebra_ifp->ptm_enable == ZEBRA_IF_PTM_ENABLE_OFF) + vty_out(vty, " no ptm-enable\n"); } diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index 28fe9c1de..9f9269ab5 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -29,23 +29,22 @@ extern const char ZEBRA_PTM_SOCK_NAME[]; #define ZEBRA_PTM_BFD_CLIENT_FLAG_REG (1 << 1) /* client registered with BFD */ /* Zebra ptm context block */ -struct zebra_ptm_cb -{ - int ptm_sock; /* ptm file descriptor. */ +struct zebra_ptm_cb { + int ptm_sock; /* ptm file descriptor. */ - struct buffer *wb; /* Buffer of data waiting to be written to ptm. */ + struct buffer *wb; /* Buffer of data waiting to be written to ptm. */ - struct thread *t_read; /* Thread for read */ - struct thread *t_write; /* Thread for write */ - struct thread *t_timer; /* Thread for timer */ + struct thread *t_read; /* Thread for read */ + struct thread *t_write; /* Thread for write */ + struct thread *t_timer; /* Thread for timer */ - char *out_data; - char *in_data; - int reconnect_time; + char *out_data; + char *in_data; + int reconnect_time; - int ptm_enable; - int pid; - u_int8_t client_flags[ZEBRA_ROUTE_MAX]; + int ptm_enable; + int pid; + u_int8_t client_flags[ZEBRA_ROUTE_MAX]; }; #define ZEBRA_PTM_STATUS_DOWN 0 @@ -57,22 +56,22 @@ struct zebra_ptm_cb #define ZEBRA_IF_PTM_ENABLE_ON 1 #define ZEBRA_IF_PTM_ENABLE_UNSPEC 2 -void zebra_ptm_init (void); +void zebra_ptm_init(void); void zebra_ptm_finish(void); -int zebra_ptm_connect (struct thread *t); -void zebra_ptm_write (struct vty *vty); +int zebra_ptm_connect(struct thread *t); +void zebra_ptm_write(struct vty *vty); int zebra_ptm_get_enable_state(void); -int zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length, - int command, struct zebra_vrf *zvrf); -int zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf); -void -zebra_ptm_show_status(struct vty *vty, struct interface *ifp); -int zebra_ptm_bfd_client_register (struct zserv *client, int sock, - u_short length); +int zebra_ptm_bfd_dst_register(struct zserv *client, int sock, u_short length, + int command, struct zebra_vrf *zvrf); +int zebra_ptm_bfd_dst_deregister(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf); +void zebra_ptm_show_status(struct vty *vty, struct interface *ifp); +int zebra_ptm_bfd_client_register(struct zserv *client, int sock, + u_short length); void zebra_ptm_if_init(struct zebra_if *zebra_ifp); -void zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp); -void zebra_ptm_if_write (struct vty *vty, struct zebra_if *zebra_ifp); -void zebra_ptm_bfd_client_deregister (int proto); +void zebra_ptm_if_set_ptm_state(struct interface *ifp, + struct zebra_if *zebra_ifp); +void zebra_ptm_if_write(struct vty *vty, struct zebra_if *zebra_ifp); +void zebra_ptm_bfd_client_deregister(int proto); #endif diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c index d6902142a..1378ea186 100644 --- a/zebra/zebra_ptm_redistribute.c +++ b/zebra/zebra_ptm_redistribute.c @@ -26,102 +26,100 @@ #include "zebra/zebra_ptm_redistribute.h" #include "zebra/zebra_memory.h" -static int -zsend_interface_bfd_update (int cmd, struct zserv *client, - struct interface *ifp, struct prefix *dp, - struct prefix *sp, int status, vrf_id_t vrf_id) +static int zsend_interface_bfd_update(int cmd, struct zserv *client, + struct interface *ifp, struct prefix *dp, + struct prefix *sp, int status, + vrf_id_t vrf_id) { - int blen; - struct stream *s; - - /* Check this client need interface information. */ - if (! client->ifinfo) - return 0; - - s = client->obuf; - stream_reset (s); - - zserv_create_header (s, cmd, vrf_id); - if (ifp) - stream_putl (s, ifp->ifindex); - else - stream_putl (s, 0); - - /* BFD destination prefix information. */ - stream_putc (s, dp->family); - blen = prefix_blen (dp); - stream_put (s, &dp->u.prefix, blen); - stream_putc (s, dp->prefixlen); - - /* BFD status */ - stream_putl(s, status); - - /* BFD source prefix information. */ - stream_putc (s, sp->family); - blen = prefix_blen (sp); - stream_put (s, &sp->u.prefix, blen); - stream_putc (s, sp->prefixlen); - - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); - - client->if_bfd_cnt++; - return zebra_server_send_message(client); + int blen; + struct stream *s; + + /* Check this client need interface information. */ + if (!client->ifinfo) + return 0; + + s = client->obuf; + stream_reset(s); + + zserv_create_header(s, cmd, vrf_id); + if (ifp) + stream_putl(s, ifp->ifindex); + else + stream_putl(s, 0); + + /* BFD destination prefix information. */ + stream_putc(s, dp->family); + blen = prefix_blen(dp); + stream_put(s, &dp->u.prefix, blen); + stream_putc(s, dp->prefixlen); + + /* BFD status */ + stream_putl(s, status); + + /* BFD source prefix information. */ + stream_putc(s, sp->family); + blen = prefix_blen(sp); + stream_put(s, &sp->u.prefix, blen); + stream_putc(s, sp->prefixlen); + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + client->if_bfd_cnt++; + return zebra_server_send_message(client); } -void -zebra_interface_bfd_update (struct interface *ifp, struct prefix *dp, - struct prefix *sp, int status, vrf_id_t vrf_id) +void zebra_interface_bfd_update(struct interface *ifp, struct prefix *dp, + struct prefix *sp, int status, vrf_id_t vrf_id) { - struct listnode *node, *nnode; - struct zserv *client; - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - /* Supporting for OSPF, BGP and PIM */ - if (client->proto != ZEBRA_ROUTE_OSPF && client->proto != ZEBRA_ROUTE_BGP - && client->proto != ZEBRA_ROUTE_OSPF6 && client->proto != ZEBRA_ROUTE_PIM) - continue; - - /* Notify to the protocol daemons. */ - zsend_interface_bfd_update (ZEBRA_INTERFACE_BFD_DEST_UPDATE, client, ifp, - dp, sp, status, vrf_id); - } + struct listnode *node, *nnode; + struct zserv *client; + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + /* Supporting for OSPF, BGP and PIM */ + if (client->proto != ZEBRA_ROUTE_OSPF + && client->proto != ZEBRA_ROUTE_BGP + && client->proto != ZEBRA_ROUTE_OSPF6 + && client->proto != ZEBRA_ROUTE_PIM) + continue; + + /* Notify to the protocol daemons. */ + zsend_interface_bfd_update(ZEBRA_INTERFACE_BFD_DEST_UPDATE, + client, ifp, dp, sp, status, vrf_id); + } } -static int -zsend_bfd_peer_replay (int cmd, struct zserv *client) +static int zsend_bfd_peer_replay(int cmd, struct zserv *client) { - struct stream *s; + struct stream *s; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, cmd, VRF_DEFAULT); //Pending: adjust when multi-vrf bfd work + zserv_create_header( + s, cmd, VRF_DEFAULT); // Pending: adjust when multi-vrf bfd work - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - client->bfd_peer_replay_cnt++; - return zebra_server_send_message(client); + client->bfd_peer_replay_cnt++; + return zebra_server_send_message(client); } -void -zebra_bfd_peer_replay_req (void) +void zebra_bfd_peer_replay_req(void) { - struct listnode *node, *nnode; - struct zserv *client; - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - /* Supporting for BGP */ - if ((client->proto != ZEBRA_ROUTE_BGP) && - (client->proto != ZEBRA_ROUTE_OSPF) && - (client->proto != ZEBRA_ROUTE_OSPF6) && - (client->proto != ZEBRA_ROUTE_PIM)) - continue; - - /* Notify to the protocol daemons. */ - zsend_bfd_peer_replay (ZEBRA_BFD_DEST_REPLAY, client); - } + struct listnode *node, *nnode; + struct zserv *client; + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + /* Supporting for BGP */ + if ((client->proto != ZEBRA_ROUTE_BGP) + && (client->proto != ZEBRA_ROUTE_OSPF) + && (client->proto != ZEBRA_ROUTE_OSPF6) + && (client->proto != ZEBRA_ROUTE_PIM)) + continue; + + /* Notify to the protocol daemons. */ + zsend_bfd_peer_replay(ZEBRA_BFD_DEST_REPLAY, client); + } } diff --git a/zebra/zebra_ptm_redistribute.h b/zebra/zebra_ptm_redistribute.h index ac3873f24..c1b12bd0d 100644 --- a/zebra/zebra_ptm_redistribute.h +++ b/zebra/zebra_ptm_redistribute.h @@ -21,7 +21,7 @@ #ifndef _ZEBRA_PTM_REDISTRIBUTE_H #define _ZEBRA_PTM_REDISTRIBUTE_H -extern void zebra_interface_bfd_update (struct interface *, struct prefix *, - struct prefix *, int, vrf_id_t); -extern void zebra_bfd_peer_replay_req (void); +extern void zebra_interface_bfd_update(struct interface *, struct prefix *, + struct prefix *, int, vrf_id_t); +extern void zebra_bfd_peer_replay_req(void); #endif /* _ZEBRA_PTM_REDISTRIBUTE_H */ diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index b07a0cf05..98508aaa8 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -51,7 +51,8 @@ #include "zebra/interface.h" #include "zebra/connected.h" -DEFINE_HOOK(rib_update, (struct route_node *rn, const char *reason), (rn, reason)) +DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason), + (rn, reason)) /* Should we allow non Quagga processes to delete our routes */ extern int allow_delete; @@ -63,691 +64,652 @@ extern int allow_delete; int rib_process_hold_time = 10; /* Each route type's string and default distance value. */ -static const struct -{ - int key; - int distance; -} route_info[ZEBRA_ROUTE_MAX] = -{ - [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0}, - [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0}, - [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0}, - [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1}, - [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120}, - [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120}, - [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110}, - [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110}, - [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115}, - [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}, - [ZEBRA_ROUTE_NHRP] = {ZEBRA_ROUTE_NHRP, 10}, - /* no entry/default: 150 */ +static const struct { + int key; + int distance; +} route_info[ZEBRA_ROUTE_MAX] = { + [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0}, + [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0}, + [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0}, + [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1}, + [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120}, + [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120}, + [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110}, + [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110}, + [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115}, + [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}, + [ZEBRA_ROUTE_NHRP] = {ZEBRA_ROUTE_NHRP, 10}, + /* no entry/default: 150 */ }; /* RPF lookup behaviour */ static enum multicast_mode ipv4_multicast_mode = MCAST_NO_CONFIG; -static void __attribute__((format (printf, 5, 6))) -_rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn, int priority, - const char *msgfmt, ...) +static void __attribute__((format(printf, 5, 6))) +_rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn, + int priority, const char *msgfmt, ...) { - char buf[SRCDEST2STR_BUFFER + sizeof(" (MRIB)")]; - char msgbuf[512]; - va_list ap; + char buf[SRCDEST2STR_BUFFER + sizeof(" (MRIB)")]; + char msgbuf[512]; + va_list ap; - va_start(ap, msgfmt); - vsnprintf(msgbuf, sizeof(msgbuf), msgfmt, ap); - va_end(ap); + va_start(ap, msgfmt); + vsnprintf(msgbuf, sizeof(msgbuf), msgfmt, ap); + va_end(ap); - if (rn) - { - rib_table_info_t *info = srcdest_rnode_table_info (rn); - srcdest_rnode2str(rn, buf, sizeof(buf)); + if (rn) { + rib_table_info_t *info = srcdest_rnode_table_info(rn); + srcdest_rnode2str(rn, buf, sizeof(buf)); - if (info->safi == SAFI_MULTICAST) - strcat(buf, " (MRIB)"); - } - else - { - snprintf(buf, sizeof(buf), "{(route_node *) NULL}"); - } + if (info->safi == SAFI_MULTICAST) + strcat(buf, " (MRIB)"); + } else { + snprintf(buf, sizeof(buf), "{(route_node *) NULL}"); + } - zlog (priority, "%s: %d:%s: %s", _func, vrf_id, buf, msgbuf); + zlog(priority, "%s: %d:%s: %s", _func, vrf_id, buf, msgbuf); } -#define rnode_debug(node, vrf_id, ...) \ +#define rnode_debug(node, vrf_id, ...) \ _rnode_zlog(__func__, vrf_id, node, LOG_DEBUG, __VA_ARGS__) -#define rnode_info(node, ...) \ +#define rnode_info(node, ...) \ _rnode_zlog(__func__, vrf_id, node, LOG_INFO, __VA_ARGS__) -u_char -route_distance (int type) +u_char route_distance(int type) { - u_char distance; + u_char distance; - if ((unsigned)type >= array_size(route_info)) - distance = 150; - else - distance = route_info[type].distance; + if ((unsigned)type >= array_size(route_info)) + distance = 150; + else + distance = route_info[type].distance; - return distance; + return distance; } -int -is_zebra_valid_kernel_table(u_int32_t table_id) +int is_zebra_valid_kernel_table(u_int32_t table_id) { - if ((table_id > ZEBRA_KERNEL_TABLE_MAX)) - return 0; + if ((table_id > ZEBRA_KERNEL_TABLE_MAX)) + return 0; #ifdef linux - if ((table_id == RT_TABLE_UNSPEC) || - (table_id == RT_TABLE_LOCAL) || - (table_id == RT_TABLE_COMPAT)) - return 0; + if ((table_id == RT_TABLE_UNSPEC) || (table_id == RT_TABLE_LOCAL) + || (table_id == RT_TABLE_COMPAT)) + return 0; #endif - return 1; + return 1; } -int -is_zebra_main_routing_table(u_int32_t table_id) +int is_zebra_main_routing_table(u_int32_t table_id) { - if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) - return 1; - return 0; + if ((table_id == RT_TABLE_MAIN) + || (table_id == zebrad.rtm_table_default)) + return 1; + return 0; } -int -zebra_check_addr (struct prefix *p) +int zebra_check_addr(struct prefix *p) { - if (p->family == AF_INET) - { - u_int32_t addr; + if (p->family == AF_INET) { + u_int32_t addr; - addr = p->u.prefix4.s_addr; - addr = ntohl (addr); + addr = p->u.prefix4.s_addr; + addr = ntohl(addr); - if (IPV4_NET127 (addr) - || IN_CLASSD (addr) - || IPV4_LINKLOCAL(addr)) - return 0; - } - if (p->family == AF_INET6) - { - if (IN6_IS_ADDR_LOOPBACK (&p->u.prefix6)) - return 0; - if (IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) - return 0; - } - return 1; + if (IPV4_NET127(addr) || IN_CLASSD(addr) + || IPV4_LINKLOCAL(addr)) + return 0; + } + if (p->family == AF_INET6) { + if (IN6_IS_ADDR_LOOPBACK(&p->u.prefix6)) + return 0; + if (IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) + return 0; + } + return 1; } /* Add nexthop to the end of a rib node's nexthop list */ -void -route_entry_nexthop_add (struct route_entry *re, struct nexthop *nexthop) +void route_entry_nexthop_add(struct route_entry *re, struct nexthop *nexthop) { - nexthop_add(&re->nexthop, nexthop); - re->nexthop_num++; + nexthop_add(&re->nexthop, nexthop); + re->nexthop_num++; } - /** * copy_nexthop - copy a nexthop to the rib structure. */ -void -route_entry_copy_nexthops (struct route_entry *re, struct nexthop *nh) +void route_entry_copy_nexthops(struct route_entry *re, struct nexthop *nh) { - assert(!re->nexthop); - copy_nexthops(&re->nexthop, nh, NULL); - for (struct nexthop *nexthop = nh; nexthop; nexthop = nexthop->next) - re->nexthop_num++; + assert(!re->nexthop); + copy_nexthops(&re->nexthop, nh, NULL); + for (struct nexthop *nexthop = nh; nexthop; nexthop = nexthop->next) + re->nexthop_num++; } /* Delete specified nexthop from the list. */ -void -route_entry_nexthop_delete (struct route_entry *re, struct nexthop *nexthop) +void route_entry_nexthop_delete(struct route_entry *re, struct nexthop *nexthop) { - if (nexthop->next) - nexthop->next->prev = nexthop->prev; - if (nexthop->prev) - nexthop->prev->next = nexthop->next; - else - re->nexthop = nexthop->next; - re->nexthop_num--; + if (nexthop->next) + nexthop->next->prev = nexthop->prev; + if (nexthop->prev) + nexthop->prev->next = nexthop->next; + else + re->nexthop = nexthop->next; + re->nexthop_num--; } - -struct nexthop * -route_entry_nexthop_ifindex_add (struct route_entry *re, ifindex_t ifindex) +struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *re, + ifindex_t ifindex) { - struct nexthop *nexthop; + struct nexthop *nexthop; - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_IFINDEX; - nexthop->ifindex = ifindex; + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_IFINDEX; + nexthop->ifindex = ifindex; - route_entry_nexthop_add (re, nexthop); + route_entry_nexthop_add(re, nexthop); - return nexthop; + return nexthop; } -struct nexthop * -route_entry_nexthop_ipv4_add (struct route_entry *re, struct in_addr *ipv4, struct in_addr *src) +struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *re, + struct in_addr *ipv4, + struct in_addr *src) { - struct nexthop *nexthop; + struct nexthop *nexthop; - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_IPV4; - nexthop->gate.ipv4 = *ipv4; - if (src) - nexthop->src.ipv4 = *src; + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_IPV4; + nexthop->gate.ipv4 = *ipv4; + if (src) + nexthop->src.ipv4 = *src; - route_entry_nexthop_add (re, nexthop); + route_entry_nexthop_add(re, nexthop); - return nexthop; + return nexthop; } -struct nexthop * -route_entry_nexthop_ipv4_ifindex_add (struct route_entry *re, struct in_addr *ipv4, - struct in_addr *src, ifindex_t ifindex) +struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re, + struct in_addr *ipv4, + struct in_addr *src, + ifindex_t ifindex) { - struct nexthop *nexthop; - struct interface *ifp; + struct nexthop *nexthop; + struct interface *ifp; - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX; - nexthop->gate.ipv4 = *ipv4; - if (src) - nexthop->src.ipv4 = *src; - nexthop->ifindex = ifindex; - ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); - /*Pending: need to think if null ifp here is ok during bootup? - There was a crash because ifp here was coming to be NULL */ - if (ifp) - if (connected_is_unnumbered(ifp)) { - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK); - } + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX; + nexthop->gate.ipv4 = *ipv4; + if (src) + nexthop->src.ipv4 = *src; + nexthop->ifindex = ifindex; + ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT); + /*Pending: need to think if null ifp here is ok during bootup? + There was a crash because ifp here was coming to be NULL */ + if (ifp) + if (connected_is_unnumbered(ifp)) { + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK); + } - route_entry_nexthop_add (re, nexthop); + route_entry_nexthop_add(re, nexthop); - return nexthop; + return nexthop; } -struct nexthop * -route_entry_nexthop_ipv6_add (struct route_entry *re, struct in6_addr *ipv6) +struct nexthop *route_entry_nexthop_ipv6_add(struct route_entry *re, + struct in6_addr *ipv6) { - struct nexthop *nexthop; + struct nexthop *nexthop; - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_IPV6; - nexthop->gate.ipv6 = *ipv6; + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_IPV6; + nexthop->gate.ipv6 = *ipv6; - route_entry_nexthop_add (re, nexthop); + route_entry_nexthop_add(re, nexthop); - return nexthop; + return nexthop; } -struct nexthop * -route_entry_nexthop_ipv6_ifindex_add (struct route_entry *re, struct in6_addr *ipv6, - ifindex_t ifindex) +struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re, + struct in6_addr *ipv6, + ifindex_t ifindex) { - struct nexthop *nexthop; + struct nexthop *nexthop; - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX; - nexthop->gate.ipv6 = *ipv6; - nexthop->ifindex = ifindex; + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX; + nexthop->gate.ipv6 = *ipv6; + nexthop->ifindex = ifindex; - route_entry_nexthop_add (re, nexthop); + route_entry_nexthop_add(re, nexthop); - return nexthop; + return nexthop; } -struct nexthop * -route_entry_nexthop_blackhole_add (struct route_entry *re) +struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *re) { - struct nexthop *nexthop; + struct nexthop *nexthop; - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_BLACKHOLE; - SET_FLAG (re->flags, ZEBRA_FLAG_BLACKHOLE); + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_BLACKHOLE; + SET_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE); - route_entry_nexthop_add (re, nexthop); + route_entry_nexthop_add(re, nexthop); - return nexthop; + return nexthop; } -static void -nexthop_set_resolved (afi_t afi, struct nexthop *newhop, struct nexthop *nexthop) +static void nexthop_set_resolved(afi_t afi, struct nexthop *newhop, + struct nexthop *nexthop) { - struct nexthop *resolved_hop; + struct nexthop *resolved_hop; - resolved_hop = nexthop_new(); - SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE); - /* If the resolving route specifies a gateway, use it */ - if (newhop->type == NEXTHOP_TYPE_IPV4 - || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - resolved_hop->type = newhop->type; - resolved_hop->gate.ipv4 = newhop->gate.ipv4; + resolved_hop = nexthop_new(); + SET_FLAG(resolved_hop->flags, NEXTHOP_FLAG_ACTIVE); + /* If the resolving route specifies a gateway, use it */ + if (newhop->type == NEXTHOP_TYPE_IPV4 + || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + resolved_hop->type = newhop->type; + resolved_hop->gate.ipv4 = newhop->gate.ipv4; - if (newhop->ifindex) - { - resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; - resolved_hop->ifindex = newhop->ifindex; - if (newhop->flags & NEXTHOP_FLAG_ONLINK) - resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + if (newhop->ifindex) { + resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; + resolved_hop->ifindex = newhop->ifindex; + if (newhop->flags & NEXTHOP_FLAG_ONLINK) + resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + } } - } - if (newhop->type == NEXTHOP_TYPE_IPV6 - || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - resolved_hop->type = newhop->type; - resolved_hop->gate.ipv6 = newhop->gate.ipv6; - - if (newhop->ifindex) - { - resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; - resolved_hop->ifindex = newhop->ifindex; + if (newhop->type == NEXTHOP_TYPE_IPV6 + || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + resolved_hop->type = newhop->type; + resolved_hop->gate.ipv6 = newhop->gate.ipv6; + + if (newhop->ifindex) { + resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; + resolved_hop->ifindex = newhop->ifindex; + } } - } - /* If the resolving route is an interface route, - * it means the gateway we are looking up is connected - * to that interface. (The actual network is _not_ onlink). - * Therefore, the resolved route should have the original - * gateway as nexthop as it is directly connected. - * - * On Linux, we have to set the onlink netlink flag because - * otherwise, the kernel won't accept the route. - */ - if (newhop->type == NEXTHOP_TYPE_IFINDEX) - { - resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; - if (afi == AFI_IP) - { - resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; - resolved_hop->gate.ipv4 = nexthop->gate.ipv4; - } - else if (afi == AFI_IP6) - { - resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; - resolved_hop->gate.ipv6 = nexthop->gate.ipv6; + /* If the resolving route is an interface route, + * it means the gateway we are looking up is connected + * to that interface. (The actual network is _not_ onlink). + * Therefore, the resolved route should have the original + * gateway as nexthop as it is directly connected. + * + * On Linux, we have to set the onlink netlink flag because + * otherwise, the kernel won't accept the route. + */ + if (newhop->type == NEXTHOP_TYPE_IFINDEX) { + resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + if (afi == AFI_IP) { + resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; + resolved_hop->gate.ipv4 = nexthop->gate.ipv4; + } else if (afi == AFI_IP6) { + resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; + resolved_hop->gate.ipv6 = nexthop->gate.ipv6; + } + resolved_hop->ifindex = newhop->ifindex; } - resolved_hop->ifindex = newhop->ifindex; - } - resolved_hop->rparent = nexthop; - nexthop_add(&nexthop->resolved, resolved_hop); + resolved_hop->rparent = nexthop; + nexthop_add(&nexthop->resolved, resolved_hop); } /* If force flag is not set, do not modify falgs at all for uninstall the route from FIB. */ -static int -nexthop_active (afi_t afi, struct route_entry *re, struct nexthop *nexthop, int set, - struct route_node *top) -{ - struct prefix p; - struct route_table *table; - struct route_node *rn; - struct route_entry *match; - int resolved; - struct nexthop *newhop; - struct interface *ifp; - - if ((nexthop->type == NEXTHOP_TYPE_IPV4) || nexthop->type == NEXTHOP_TYPE_IPV6) - nexthop->ifindex = 0; - - if (set) - { - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); - zebra_deregister_rnh_static_nexthops(re->vrf_id, nexthop->resolved, top); - nexthops_free(nexthop->resolved); - nexthop->resolved = NULL; - re->nexthop_mtu = 0; - } - - /* Skip nexthops that have been filtered out due to route-map */ - /* The nexthops are specific to this route and so the same */ - /* nexthop for a different route may not have this flag set */ - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED)) - return 0; - - /* - * Check to see if we should trust the passed in information - * for UNNUMBERED interfaces as that we won't find the GW - * address in the routing table. - */ - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) - { - ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); - if (ifp && connected_is_unnumbered(ifp)) - { - if (if_is_operative(ifp)) - return 1; - else - return 0; +static int nexthop_active(afi_t afi, struct route_entry *re, + struct nexthop *nexthop, int set, + struct route_node *top) +{ + struct prefix p; + struct route_table *table; + struct route_node *rn; + struct route_entry *match; + int resolved; + struct nexthop *newhop; + struct interface *ifp; + + if ((nexthop->type == NEXTHOP_TYPE_IPV4) + || nexthop->type == NEXTHOP_TYPE_IPV6) + nexthop->ifindex = 0; + + if (set) { + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE); + zebra_deregister_rnh_static_nexthops(re->vrf_id, + nexthop->resolved, top); + nexthops_free(nexthop->resolved); + nexthop->resolved = NULL; + re->nexthop_mtu = 0; } - else - return 0; - } - - /* Make lookup prefix. */ - memset (&p, 0, sizeof (struct prefix)); - switch (afi) - { - case AFI_IP: - p.family = AF_INET; - p.prefixlen = IPV4_MAX_PREFIXLEN; - p.u.prefix4 = nexthop->gate.ipv4; - break; - case AFI_IP6: - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_PREFIXLEN; - p.u.prefix6 = nexthop->gate.ipv6; - break; - default: - assert (afi != AFI_IP && afi != AFI_IP6); - break; - } - /* Lookup table. */ - table = zebra_vrf_table (afi, SAFI_UNICAST, re->vrf_id); - if (! table) - return 0; - - rn = route_node_match (table, (struct prefix *) &p); - while (rn) - { - route_unlock_node (rn); - - /* If lookup self prefix return immediately. */ - if (rn == top) - return 0; - - /* Pick up selected route. */ - /* However, do not resolve over default route unless explicitly allowed. */ - if (is_default_prefix (&rn->p) && - !nh_resolve_via_default (p.family)) - return 0; - RNODE_FOREACH_RE (rn, match) - { - if (CHECK_FLAG (match->status, ROUTE_ENTRY_REMOVED)) - continue; - - /* if the next hop is imported from another table, skip it */ - if (match->type == ZEBRA_ROUTE_TABLE) - continue; - if (CHECK_FLAG (match->status, ROUTE_ENTRY_SELECTED_FIB)) - break; + /* Skip nexthops that have been filtered out due to route-map */ + /* The nexthops are specific to this route and so the same */ + /* nexthop for a different route may not have this flag set */ + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED)) + return 0; + + /* + * Check to see if we should trust the passed in information + * for UNNUMBERED interfaces as that we won't find the GW + * address in the routing table. + */ + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) { + ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT); + if (ifp && connected_is_unnumbered(ifp)) { + if (if_is_operative(ifp)) + return 1; + else + return 0; + } else + return 0; } - /* If there is no selected route or matched route is EGP, go up - tree. */ - if (! match) - { - do { - rn = rn->parent; - } while (rn && rn->info == NULL); - if (rn) - route_lock_node (rn); - - continue; + /* Make lookup prefix. */ + memset(&p, 0, sizeof(struct prefix)); + switch (afi) { + case AFI_IP: + p.family = AF_INET; + p.prefixlen = IPV4_MAX_PREFIXLEN; + p.u.prefix4 = nexthop->gate.ipv4; + break; + case AFI_IP6: + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_PREFIXLEN; + p.u.prefix6 = nexthop->gate.ipv6; + break; + default: + assert(afi != AFI_IP && afi != AFI_IP6); + break; } + /* Lookup table. */ + table = zebra_vrf_table(afi, SAFI_UNICAST, re->vrf_id); + if (!table) + return 0; + + rn = route_node_match(table, (struct prefix *)&p); + while (rn) { + route_unlock_node(rn); + + /* If lookup self prefix return immediately. */ + if (rn == top) + return 0; + + /* Pick up selected route. */ + /* However, do not resolve over default route unless explicitly + * allowed. */ + if (is_default_prefix(&rn->p) + && !nh_resolve_via_default(p.family)) + return 0; + + RNODE_FOREACH_RE(rn, match) + { + if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)) + continue; + + /* if the next hop is imported from another table, skip + * it */ + if (match->type == ZEBRA_ROUTE_TABLE) + continue; + if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB)) + break; + } - /* If the longest prefix match for the nexthop yields - * a blackhole, mark it as inactive. */ - if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE) - || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT)) - return 0; + /* If there is no selected route or matched route is EGP, go up + tree. */ + if (!match) { + do { + rn = rn->parent; + } while (rn && rn->info == NULL); + if (rn) + route_lock_node(rn); - if (match->type == ZEBRA_ROUTE_CONNECT) - { - /* Directly point connected route. */ - newhop = match->nexthop; - if (newhop) - { - if (nexthop->type == NEXTHOP_TYPE_IPV4 || - nexthop->type == NEXTHOP_TYPE_IPV6) - nexthop->ifindex = newhop->ifindex; - } - return 1; - } - else if (CHECK_FLAG (re->flags, ZEBRA_FLAG_INTERNAL)) - { - resolved = 0; - for (ALL_NEXTHOPS(match->nexthop, newhop)) - if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB) - && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE)) - { - if (set) - { - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); - SET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - - nexthop_set_resolved(afi, newhop, nexthop); - } - resolved = 1; - } - return resolved; - } - else if (re->type == ZEBRA_ROUTE_STATIC) - { - resolved = 0; - for (ALL_NEXTHOPS(match->nexthop, newhop)) - if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)) - { - if (set) - { - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); - - nexthop_set_resolved(afi, newhop, nexthop); - } - resolved = 1; - } - if (resolved && set) - re->nexthop_mtu = match->mtu; - return resolved; - } - else - { - return 0; + continue; + } + + /* If the longest prefix match for the nexthop yields + * a blackhole, mark it as inactive. */ + if (CHECK_FLAG(match->flags, ZEBRA_FLAG_BLACKHOLE) + || CHECK_FLAG(match->flags, ZEBRA_FLAG_REJECT)) + return 0; + + if (match->type == ZEBRA_ROUTE_CONNECT) { + /* Directly point connected route. */ + newhop = match->nexthop; + if (newhop) { + if (nexthop->type == NEXTHOP_TYPE_IPV4 + || nexthop->type == NEXTHOP_TYPE_IPV6) + nexthop->ifindex = newhop->ifindex; + } + return 1; + } else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_INTERNAL)) { + resolved = 0; + for (ALL_NEXTHOPS(match->nexthop, newhop)) + if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_FIB) + && !CHECK_FLAG(newhop->flags, + NEXTHOP_FLAG_RECURSIVE)) { + if (set) { + SET_FLAG( + nexthop->flags, + NEXTHOP_FLAG_RECURSIVE); + SET_FLAG( + re->status, + ROUTE_ENTRY_NEXTHOPS_CHANGED); + + nexthop_set_resolved( + afi, newhop, nexthop); + } + resolved = 1; + } + return resolved; + } else if (re->type == ZEBRA_ROUTE_STATIC) { + resolved = 0; + for (ALL_NEXTHOPS(match->nexthop, newhop)) + if (CHECK_FLAG(newhop->flags, + NEXTHOP_FLAG_FIB)) { + if (set) { + SET_FLAG( + nexthop->flags, + NEXTHOP_FLAG_RECURSIVE); + + nexthop_set_resolved( + afi, newhop, nexthop); + } + resolved = 1; + } + if (resolved && set) + re->nexthop_mtu = match->mtu; + return resolved; + } else { + return 0; + } } - } - return 0; + return 0; } -struct route_entry * -rib_match (afi_t afi, safi_t safi, vrf_id_t vrf_id, - union g_addr *addr, struct route_node **rn_out) -{ - struct prefix p; - struct route_table *table; - struct route_node *rn; - struct route_entry *match; - struct nexthop *newhop; +struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id, + union g_addr *addr, struct route_node **rn_out) +{ + struct prefix p; + struct route_table *table; + struct route_node *rn; + struct route_entry *match; + struct nexthop *newhop; + + /* Lookup table. */ + table = zebra_vrf_table(afi, safi, vrf_id); + if (!table) + return 0; + + memset(&p, 0, sizeof(struct prefix)); + p.family = afi; + if (afi == AFI_IP) { + p.u.prefix4 = addr->ipv4; + p.prefixlen = IPV4_MAX_PREFIXLEN; + } else { + p.u.prefix6 = addr->ipv6; + p.prefixlen = IPV6_MAX_PREFIXLEN; + } - /* Lookup table. */ - table = zebra_vrf_table (afi, safi, vrf_id); - if (! table) - return 0; + rn = route_node_match(table, (struct prefix *)&p); - memset (&p, 0, sizeof (struct prefix)); - p.family = afi; - if (afi == AFI_IP) - { - p.u.prefix4 = addr->ipv4; - p.prefixlen = IPV4_MAX_PREFIXLEN; - } - else - { - p.u.prefix6 = addr->ipv6; - p.prefixlen = IPV6_MAX_PREFIXLEN; - } + while (rn) { + route_unlock_node(rn); - rn = route_node_match (table, (struct prefix *) &p); + /* Pick up selected route. */ + RNODE_FOREACH_RE(rn, match) + { + if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)) + continue; + if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB)) + break; + } - while (rn) - { - route_unlock_node (rn); - - /* Pick up selected route. */ - RNODE_FOREACH_RE (rn, match) - { - if (CHECK_FLAG (match->status, ROUTE_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG (match->status, ROUTE_ENTRY_SELECTED_FIB)) - break; + /* If there is no selected route or matched route is EGP, go up + tree. */ + if (!match) { + do { + rn = rn->parent; + } while (rn && rn->info == NULL); + if (rn) + route_lock_node(rn); + } else { + if (match->type != ZEBRA_ROUTE_CONNECT) { + int found = 0; + for (ALL_NEXTHOPS(match->nexthop, newhop)) + if (CHECK_FLAG(newhop->flags, + NEXTHOP_FLAG_FIB)) { + found = 1; + break; + } + if (!found) + return NULL; + } + + if (rn_out) + *rn_out = rn; + return match; + } } - - /* If there is no selected route or matched route is EGP, go up - tree. */ - if (! match) - { - do { - rn = rn->parent; - } while (rn && rn->info == NULL); - if (rn) - route_lock_node (rn); + return NULL; +} + +struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id, + struct in_addr addr, + struct route_node **rn_out) +{ + struct route_entry *re = NULL, *mre = NULL, *ure = NULL; + struct route_node *m_rn = NULL, *u_rn = NULL; + union g_addr gaddr = {.ipv4 = addr}; + + switch (ipv4_multicast_mode) { + case MCAST_MRIB_ONLY: + return rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, + rn_out); + case MCAST_URIB_ONLY: + return rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, rn_out); + case MCAST_NO_CONFIG: + case MCAST_MIX_MRIB_FIRST: + re = mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, + &m_rn); + if (!mre) + re = ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id, + &gaddr, &u_rn); + break; + case MCAST_MIX_DISTANCE: + mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); + ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); + if (mre && ure) + re = ure->distance < mre->distance ? ure : mre; + else if (mre) + re = mre; + else if (ure) + re = ure; + break; + case MCAST_MIX_PFXLEN: + mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); + ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); + if (mre && ure) + re = u_rn->p.prefixlen > m_rn->p.prefixlen ? ure : mre; + else if (mre) + re = mre; + else if (ure) + re = ure; + break; } - else - { - if (match->type != ZEBRA_ROUTE_CONNECT) - { - int found = 0; - for (ALL_NEXTHOPS(match->nexthop, newhop)) - if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)) - { - found = 1; - break; - } - if (!found) - return NULL; - } - if (rn_out) - *rn_out = rn; - return match; - } - } - return NULL; -} + if (rn_out) + *rn_out = (re == mre) ? m_rn : u_rn; -struct route_entry * -rib_match_ipv4_multicast (vrf_id_t vrf_id, struct in_addr addr, struct route_node **rn_out) -{ - struct route_entry *re = NULL, *mre = NULL, *ure = NULL; - struct route_node *m_rn = NULL, *u_rn = NULL; - union g_addr gaddr = { .ipv4 = addr }; + if (IS_ZEBRA_DEBUG_RIB) { + char buf[BUFSIZ]; + inet_ntop(AF_INET, &addr, buf, BUFSIZ); - switch (ipv4_multicast_mode) - { - case MCAST_MRIB_ONLY: - return rib_match (AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, rn_out); - case MCAST_URIB_ONLY: - return rib_match (AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, rn_out); - case MCAST_NO_CONFIG: - case MCAST_MIX_MRIB_FIRST: - re = mre = rib_match (AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); - if (!mre) - re = ure = rib_match (AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); - break; - case MCAST_MIX_DISTANCE: - mre = rib_match (AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); - ure = rib_match (AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); - if (mre && ure) - re = ure->distance < mre->distance ? ure : mre; - else if (mre) - re = mre; - else if (ure) - re = ure; - break; - case MCAST_MIX_PFXLEN: - mre = rib_match (AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); - ure = rib_match (AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); - if (mre && ure) - re = u_rn->p.prefixlen > m_rn->p.prefixlen ? ure : mre; - else if (mre) - re = mre; - else if (ure) - re = ure; - break; - } - - if (rn_out) - *rn_out = (re == mre) ? m_rn : u_rn; - - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[BUFSIZ]; - inet_ntop (AF_INET, &addr, buf, BUFSIZ); - - zlog_debug("%s: %s: found %s, using %s", - __func__, buf, - mre ? (ure ? "MRIB+URIB" : "MRIB") : - ure ? "URIB" : "nothing", - re == ure ? "URIB" : re == mre ? "MRIB" : "none"); - } - return re; + zlog_debug("%s: %s: found %s, using %s", __func__, buf, + mre ? (ure ? "MRIB+URIB" : "MRIB") + : ure ? "URIB" : "nothing", + re == ure ? "URIB" : re == mre ? "MRIB" : "none"); + } + return re; } -void -multicast_mode_ipv4_set (enum multicast_mode mode) +void multicast_mode_ipv4_set(enum multicast_mode mode) { - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug("%s: multicast lookup mode set (%d)", __func__, mode); - ipv4_multicast_mode = mode; + if (IS_ZEBRA_DEBUG_RIB) + zlog_debug("%s: multicast lookup mode set (%d)", __func__, + mode); + ipv4_multicast_mode = mode; } -enum multicast_mode -multicast_mode_ipv4_get (void) +enum multicast_mode multicast_mode_ipv4_get(void) { - return ipv4_multicast_mode; + return ipv4_multicast_mode; } -struct route_entry * -rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id) +struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id) { - struct route_table *table; - struct route_node *rn; - struct route_entry *match; - struct nexthop *nexthop; + struct route_table *table; + struct route_node *rn; + struct route_entry *match; + struct nexthop *nexthop; - /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return 0; + /* Lookup table. */ + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) + return 0; - rn = route_node_lookup (table, (struct prefix *) p); + rn = route_node_lookup(table, (struct prefix *)p); - /* No route for this prefix. */ - if (! rn) - return NULL; + /* No route for this prefix. */ + if (!rn) + return NULL; - /* Unlock node. */ - route_unlock_node (rn); + /* Unlock node. */ + route_unlock_node(rn); - RNODE_FOREACH_RE (rn, match) - { - if (CHECK_FLAG (match->status, ROUTE_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG (match->status, ROUTE_ENTRY_SELECTED_FIB)) - break; - } + RNODE_FOREACH_RE(rn, match) + { + if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)) + continue; + if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB)) + break; + } - if (! match) - return NULL; + if (!match) + return NULL; - if (match->type == ZEBRA_ROUTE_CONNECT) - return match; + if (match->type == ZEBRA_ROUTE_CONNECT) + return match; - for (ALL_NEXTHOPS(match->nexthop, nexthop)) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - return match; + for (ALL_NEXTHOPS(match->nexthop, nexthop)) + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) + return match; - return NULL; + return NULL; } /* @@ -762,73 +724,76 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id) * 2: connected route found * 3: no matches found */ -int -rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate, - vrf_id_t vrf_id) +int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate, + vrf_id_t vrf_id) { - struct route_table *table; - struct route_node *rn; - struct route_entry *match; - struct nexthop *nexthop; - int nexthops_active; + struct route_table *table; + struct route_node *rn; + struct route_entry *match; + struct nexthop *nexthop; + int nexthops_active; - /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return ZEBRA_RIB_LOOKUP_ERROR; + /* Lookup table. */ + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) + return ZEBRA_RIB_LOOKUP_ERROR; - /* Scan the RIB table for exactly matching RIB entry. */ - rn = route_node_lookup (table, (struct prefix *) p); + /* Scan the RIB table for exactly matching RIB entry. */ + rn = route_node_lookup(table, (struct prefix *)p); - /* No route for this prefix. */ - if (! rn) - return ZEBRA_RIB_NOTFOUND; + /* No route for this prefix. */ + if (!rn) + return ZEBRA_RIB_NOTFOUND; - /* Unlock node. */ - route_unlock_node (rn); + /* Unlock node. */ + route_unlock_node(rn); - /* Find out if a "selected" RR for the discovered RIB entry exists ever. */ - RNODE_FOREACH_RE (rn, match) - { - if (CHECK_FLAG (match->status, ROUTE_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG (match->status, ROUTE_ENTRY_SELECTED_FIB)) - break; - } + /* Find out if a "selected" RR for the discovered RIB entry exists ever. + */ + RNODE_FOREACH_RE(rn, match) + { + if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)) + continue; + if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB)) + break; + } - /* None such found :( */ - if (!match) - return ZEBRA_RIB_NOTFOUND; - - if (match->type == ZEBRA_ROUTE_CONNECT) - return ZEBRA_RIB_FOUND_CONNECTED; - - /* Ok, we have a cood candidate, let's check it's nexthop list... */ - nexthops_active = 0; - for (ALL_NEXTHOPS(match->nexthop, nexthop)) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - nexthops_active = 1; - if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate)) - return ZEBRA_RIB_FOUND_EXACT; - if (IS_ZEBRA_DEBUG_RIB) - { - char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN]; - inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN); - inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN); - zlog_debug ("%s: qgate == %s, %s == %s", __func__, - qgate_buf, nexthop->rparent ? "rgate" : "gate", gate_buf); - } - } - - if (nexthops_active) - return ZEBRA_RIB_FOUND_NOGATE; - - return ZEBRA_RIB_NOTFOUND; -} - -#define RIB_SYSTEM_ROUTE(R) \ - ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT) + /* None such found :( */ + if (!match) + return ZEBRA_RIB_NOTFOUND; + + if (match->type == ZEBRA_ROUTE_CONNECT) + return ZEBRA_RIB_FOUND_CONNECTED; + + /* Ok, we have a cood candidate, let's check it's nexthop list... */ + nexthops_active = 0; + for (ALL_NEXTHOPS(match->nexthop, nexthop)) + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) { + nexthops_active = 1; + if (nexthop->gate.ipv4.s_addr == sockunion2ip(qgate)) + return ZEBRA_RIB_FOUND_EXACT; + if (IS_ZEBRA_DEBUG_RIB) { + char gate_buf[INET_ADDRSTRLEN], + qgate_buf[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &nexthop->gate.ipv4.s_addr, + gate_buf, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &sockunion2ip(qgate), + qgate_buf, INET_ADDRSTRLEN); + zlog_debug("%s: qgate == %s, %s == %s", + __func__, qgate_buf, + nexthop->rparent ? "rgate" : "gate", + gate_buf); + } + } + + if (nexthops_active) + return ZEBRA_RIB_FOUND_NOGATE; + + return ZEBRA_RIB_NOTFOUND; +} + +#define RIB_SYSTEM_ROUTE(R) \ + ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT) /* This function verifies reachability of one given nexthop, which can be * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored @@ -840,114 +805,107 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate, * The return value is the final value of 'ACTIVE' flag. */ -static unsigned -nexthop_active_check (struct route_node *rn, struct route_entry *re, - struct nexthop *nexthop, int set) -{ - struct interface *ifp; - route_map_result_t ret = RMAP_MATCH; - int family; - char buf[SRCDEST2STR_BUFFER]; - struct prefix *p, *src_p; - srcdest_rnode_prefixes (rn, &p, &src_p); - - if (rn->p.family == AF_INET) - family = AFI_IP; - else if (rn->p.family == AF_INET6) - family = AFI_IP6; - else - family = 0; - switch (nexthop->type) - { - case NEXTHOP_TYPE_IFINDEX: - ifp = if_lookup_by_index (nexthop->ifindex, re->vrf_id); - if (ifp && if_is_operative(ifp)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - family = AFI_IP; - if (nexthop_active (AFI_IP, re, nexthop, set, rn)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - case NEXTHOP_TYPE_IPV6: - family = AFI_IP6; - if (nexthop_active (AFI_IP6, re, nexthop, set, rn)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - /* RFC 5549, v4 prefix with v6 NH */ - if (rn->p.family != AF_INET) - family = AFI_IP6; - if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6)) - { - ifp = if_lookup_by_index (nexthop->ifindex, re->vrf_id); - if (ifp && if_is_operative(ifp)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); +static unsigned nexthop_active_check(struct route_node *rn, + struct route_entry *re, + struct nexthop *nexthop, int set) +{ + struct interface *ifp; + route_map_result_t ret = RMAP_MATCH; + int family; + char buf[SRCDEST2STR_BUFFER]; + struct prefix *p, *src_p; + srcdest_rnode_prefixes(rn, &p, &src_p); + + if (rn->p.family == AF_INET) + family = AFI_IP; + else if (rn->p.family == AF_INET6) + family = AFI_IP6; + else + family = 0; + switch (nexthop->type) { + case NEXTHOP_TYPE_IFINDEX: + ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id); + if (ifp && if_is_operative(ifp)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + family = AFI_IP; + if (nexthop_active(AFI_IP, re, nexthop, set, rn)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + case NEXTHOP_TYPE_IPV6: + family = AFI_IP6; + if (nexthop_active(AFI_IP6, re, nexthop, set, rn)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + /* RFC 5549, v4 prefix with v6 NH */ + if (rn->p.family != AF_INET) + family = AFI_IP6; + if (IN6_IS_ADDR_LINKLOCAL(&nexthop->gate.ipv6)) { + ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id); + if (ifp && if_is_operative(ifp)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } else { + if (nexthop_active(AFI_IP6, re, nexthop, set, rn)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } + break; + case NEXTHOP_TYPE_BLACKHOLE: + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + default: + break; + } + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + return 0; + + /* XXX: What exactly do those checks do? Do we support + * e.g. IPv4 routes with IPv6 nexthops or vice versa? */ + if (RIB_SYSTEM_ROUTE(re) || (family == AFI_IP && p->family != AF_INET) + || (family == AFI_IP6 && p->family != AF_INET6)) + return CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + + /* The original code didn't determine the family correctly + * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi + * from the rib_table_info in those cases. + * Possibly it may be better to use only the rib_table_info + * in every case. + */ + if (!family) { + rib_table_info_t *info; + + info = srcdest_rnode_table_info(rn); + family = info->afi; } - else - { - if (nexthop_active (AFI_IP6, re, nexthop, set, rn)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - } - break; - case NEXTHOP_TYPE_BLACKHOLE: - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - default: - break; - } - if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - return 0; - - /* XXX: What exactly do those checks do? Do we support - * e.g. IPv4 routes with IPv6 nexthops or vice versa? */ - if (RIB_SYSTEM_ROUTE(re) || - (family == AFI_IP && p->family != AF_INET) || - (family == AFI_IP6 && p->family != AF_INET6)) - return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - - /* The original code didn't determine the family correctly - * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi - * from the rib_table_info in those cases. - * Possibly it may be better to use only the rib_table_info - * in every case. - */ - if (!family) - { - rib_table_info_t *info; - - info = srcdest_rnode_table_info(rn); - family = info->afi; - } - - memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr)); - /* It'll get set if required inside */ - ret = zebra_route_map_check(family, re->type, p, nexthop, re->vrf_id, - re->tag); - if (ret == RMAP_DENYMATCH) - { - if (IS_ZEBRA_DEBUG_RIB) - { - srcdest_rnode2str(rn, buf, sizeof(buf)); - zlog_debug("%u:%s: Filtering out with NH out %s due to route map", - re->vrf_id, buf, - ifindex2ifname (nexthop->ifindex, re->vrf_id)); + memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr)); + + /* It'll get set if required inside */ + ret = zebra_route_map_check(family, re->type, p, nexthop, re->vrf_id, + re->tag); + if (ret == RMAP_DENYMATCH) { + if (IS_ZEBRA_DEBUG_RIB) { + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_debug( + "%u:%s: Filtering out with NH out %s due to route map", + re->vrf_id, buf, + ifindex2ifname(nexthop->ifindex, re->vrf_id)); + } + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); } - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - } - return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); + return CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); } /* Iterate over all nexthops of the given RIB entry and refresh their @@ -959,180 +917,170 @@ nexthop_active_check (struct route_node *rn, struct route_entry *re, * Return value is the new number of active nexthops. */ -static int -nexthop_active_update (struct route_node *rn, struct route_entry *re, int set) -{ - struct nexthop *nexthop; - union g_addr prev_src; - unsigned int prev_active, new_active, old_num_nh; - ifindex_t prev_index; - old_num_nh = re->nexthop_active_num; - - re->nexthop_active_num = 0; - UNSET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - { - /* No protocol daemon provides src and so we're skipping tracking it */ - prev_src = nexthop->rmap_src; - prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - prev_index = nexthop->ifindex; - if ((new_active = nexthop_active_check (rn, re, nexthop, set))) - re->nexthop_active_num++; - /* Don't allow src setting on IPv6 addr for now */ - if (prev_active != new_active || - prev_index != nexthop->ifindex || - ((nexthop->type >= NEXTHOP_TYPE_IFINDEX && - nexthop->type < NEXTHOP_TYPE_IPV6) && - prev_src.ipv4.s_addr != nexthop->rmap_src.ipv4.s_addr) || - ((nexthop->type >= NEXTHOP_TYPE_IPV6 && - nexthop->type < NEXTHOP_TYPE_BLACKHOLE) && - !(IPV6_ADDR_SAME (&prev_src.ipv6, &nexthop->rmap_src.ipv6)))) - { - SET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - SET_FLAG (re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - } - } - - if (old_num_nh != re->nexthop_active_num) - SET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - - if (CHECK_FLAG (re->status, ROUTE_ENTRY_CHANGED)) - { - SET_FLAG (re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - } +static int nexthop_active_update(struct route_node *rn, struct route_entry *re, + int set) +{ + struct nexthop *nexthop; + union g_addr prev_src; + unsigned int prev_active, new_active, old_num_nh; + ifindex_t prev_index; + old_num_nh = re->nexthop_active_num; + + re->nexthop_active_num = 0; + UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED); + + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { + /* No protocol daemon provides src and so we're skipping + * tracking it */ + prev_src = nexthop->rmap_src; + prev_active = CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + prev_index = nexthop->ifindex; + if ((new_active = nexthop_active_check(rn, re, nexthop, set))) + re->nexthop_active_num++; + /* Don't allow src setting on IPv6 addr for now */ + if (prev_active != new_active || prev_index != nexthop->ifindex + || ((nexthop->type >= NEXTHOP_TYPE_IFINDEX + && nexthop->type < NEXTHOP_TYPE_IPV6) + && prev_src.ipv4.s_addr + != nexthop->rmap_src.ipv4.s_addr) + || ((nexthop->type >= NEXTHOP_TYPE_IPV6 + && nexthop->type < NEXTHOP_TYPE_BLACKHOLE) + && !(IPV6_ADDR_SAME(&prev_src.ipv6, + &nexthop->rmap_src.ipv6)))) { + SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); + SET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); + } + } + + if (old_num_nh != re->nexthop_active_num) + SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); - return re->nexthop_active_num; + if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)) { + SET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); + } + + return re->nexthop_active_num; } /* * Is this RIB labeled-unicast? It must be of type BGP and all paths * (nexthops) must have a label. */ -int -zebra_rib_labeled_unicast (struct route_entry *re) +int zebra_rib_labeled_unicast(struct route_entry *re) { - struct nexthop *nexthop = NULL; + struct nexthop *nexthop = NULL; - if (re->type != ZEBRA_ROUTE_BGP) - return 0; + if (re->type != ZEBRA_ROUTE_BGP) + return 0; - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - if (!nexthop->nh_label || !nexthop->nh_label->num_labels) - return 0; + for (ALL_NEXTHOPS(re->nexthop, nexthop)) + if (!nexthop->nh_label || !nexthop->nh_label->num_labels) + return 0; - return 1; + return 1; } /* Update flag indicates whether this is a "replace" or not. Currently, this * is only used for IPv4. */ -int -rib_install_kernel (struct route_node *rn, struct route_entry *re, struct route_entry *old) +int rib_install_kernel(struct route_node *rn, struct route_entry *re, + struct route_entry *old) { - int ret = 0; - struct nexthop *nexthop; - rib_table_info_t *info = srcdest_rnode_table_info(rn); - struct prefix *p, *src_p; - struct zebra_vrf *zvrf = vrf_info_lookup (re->vrf_id); - - srcdest_rnode_prefixes (rn, &p, &src_p); + int ret = 0; + struct nexthop *nexthop; + rib_table_info_t *info = srcdest_rnode_table_info(rn); + struct prefix *p, *src_p; + struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); - if (info->safi != SAFI_UNICAST) - { - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - return ret; - } + srcdest_rnode_prefixes(rn, &p, &src_p); - /* - * Make sure we update the FPM any time we send new information to - * the kernel. - */ - hook_call(rib_update, rn, "installing in kernel"); - ret = kernel_route_rib (p, src_p, old, re); - zvrf->installs++; + if (info->safi != SAFI_UNICAST) { + for (ALL_NEXTHOPS(re->nexthop, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + return ret; + } - /* If install succeeds, update FIB flag for nexthops. */ - if (!ret) - { - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - } + /* + * Make sure we update the FPM any time we send new information to + * the kernel. + */ + hook_call(rib_update, rn, "installing in kernel"); + ret = kernel_route_rib(p, src_p, old, re); + zvrf->installs++; + + /* If install succeeds, update FIB flag for nexthops. */ + if (!ret) { + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } + } - return ret; + return ret; } /* Uninstall the route from kernel. */ -int -rib_uninstall_kernel (struct route_node *rn, struct route_entry *re) +int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re) { - int ret = 0; - struct nexthop *nexthop; - rib_table_info_t *info = srcdest_rnode_table_info(rn); - struct prefix *p, *src_p; - struct zebra_vrf *zvrf = vrf_info_lookup (re->vrf_id); + int ret = 0; + struct nexthop *nexthop; + rib_table_info_t *info = srcdest_rnode_table_info(rn); + struct prefix *p, *src_p; + struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); - srcdest_rnode_prefixes (rn, &p, &src_p); + srcdest_rnode_prefixes(rn, &p, &src_p); - if (info->safi != SAFI_UNICAST) - { - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - return ret; - } + if (info->safi != SAFI_UNICAST) { + for (ALL_NEXTHOPS(re->nexthop, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + return ret; + } - /* - * Make sure we update the FPM any time we send new information to - * the kernel. - */ - hook_call(rib_update, rn, "uninstalling from kernel"); - ret = kernel_route_rib (p, src_p, re, NULL); - zvrf->removals++; + /* + * Make sure we update the FPM any time we send new information to + * the kernel. + */ + hook_call(rib_update, rn, "uninstalling from kernel"); + ret = kernel_route_rib(p, src_p, re, NULL); + zvrf->removals++; - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); + for (ALL_NEXTHOPS(re->nexthop, nexthop)) + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); - return ret; + return ret; } /* Uninstall the route from kernel. */ -static void -rib_uninstall (struct route_node *rn, struct route_entry *re) +static void rib_uninstall(struct route_node *rn, struct route_entry *re) { - rib_table_info_t *info = srcdest_rnode_table_info(rn); + rib_table_info_t *info = srcdest_rnode_table_info(rn); - if (CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB)) - { - if (info->safi == SAFI_UNICAST) - hook_call(rib_update, rn, "rib_uninstall"); + if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) { + if (info->safi == SAFI_UNICAST) + hook_call(rib_update, rn, "rib_uninstall"); - if (! RIB_SYSTEM_ROUTE (re)) - rib_uninstall_kernel (rn, re); + if (!RIB_SYSTEM_ROUTE(re)) + rib_uninstall_kernel(rn, re); - /* If labeled-unicast route, uninstall transit LSP. */ - if (zebra_rib_labeled_unicast (re)) - zebra_mpls_lsp_uninstall (info->zvrf, rn, re); + /* If labeled-unicast route, uninstall transit LSP. */ + if (zebra_rib_labeled_unicast(re)) + zebra_mpls_lsp_uninstall(info->zvrf, rn, re); - UNSET_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB); - } + UNSET_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB); + } - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED)) - { - struct prefix *p, *src_p; - srcdest_rnode_prefixes (rn, &p, &src_p); + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) { + struct prefix *p, *src_p; + srcdest_rnode_prefixes(rn, &p, &src_p); - redistribute_delete (p, src_p, re); - UNSET_FLAG (re->flags, ZEBRA_FLAG_SELECTED); - } + redistribute_delete(p, src_p, re); + UNSET_FLAG(re->flags, ZEBRA_FLAG_SELECTED); + } } /* @@ -1140,23 +1088,21 @@ rib_uninstall (struct route_node *rn, struct route_entry *re) * * Returns TRUE if the given dest can be deleted from the table. */ -static int -rib_can_delete_dest (rib_dest_t *dest) +static int rib_can_delete_dest(rib_dest_t *dest) { - if (dest->routes) - { - return 0; - } + if (dest->routes) { + return 0; + } - /* - * Don't delete the dest if we have to update the FPM about this - * prefix. - */ - if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) || - CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM)) - return 0; + /* + * Don't delete the dest if we have to update the FPM about this + * prefix. + */ + if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM) + || CHECK_FLAG(dest->flags, RIB_DEST_SENT_TO_FPM)) + return 0; - return 1; + return 1; } /* @@ -1167,544 +1113,540 @@ rib_can_delete_dest (rib_dest_t *dest) * * Returns TRUE if the dest was deleted, FALSE otherwise. */ -int -rib_gc_dest (struct route_node *rn) +int rib_gc_dest(struct route_node *rn) { - rib_dest_t *dest; - struct zebra_vrf *zvrf; + rib_dest_t *dest; + struct zebra_vrf *zvrf; - dest = rib_dest_from_rnode (rn); - if (!dest) - return 0; + dest = rib_dest_from_rnode(rn); + if (!dest) + return 0; - if (!rib_can_delete_dest (dest)) - return 0; + if (!rib_can_delete_dest(dest)) + return 0; - zvrf = rib_dest_vrf (dest); - if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, zvrf_id (zvrf), "removing dest from table"); + zvrf = rib_dest_vrf(dest); + if (IS_ZEBRA_DEBUG_RIB) + rnode_debug(rn, zvrf_id(zvrf), "removing dest from table"); - dest->rnode = NULL; - XFREE (MTYPE_RIB_DEST, dest); - rn->info = NULL; + dest->rnode = NULL; + XFREE(MTYPE_RIB_DEST, dest); + rn->info = NULL; - /* - * Release the one reference that we keep on the route node. - */ - route_unlock_node (rn); - return 1; + /* + * Release the one reference that we keep on the route node. + */ + route_unlock_node(rn); + return 1; } -static void -rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, - struct route_entry *new) +static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, + struct route_entry *new) { - hook_call(rib_update, rn, "new route selected"); + hook_call(rib_update, rn, "new route selected"); - /* Update real nexthop. This may actually determine if nexthop is active or not. */ - if (!nexthop_active_update (rn, new, 1)) - { - UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); - return; - } + /* Update real nexthop. This may actually determine if nexthop is active + * or not. */ + if (!nexthop_active_update(rn, new, 1)) { + UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); + return; + } - SET_FLAG (new->status, ROUTE_ENTRY_SELECTED_FIB); - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - zlog_debug ("%u:%s: Adding route rn %p, re %p (type %d)", - zvrf_id (zvrf), buf, rn, new, new->type); - } + SET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB); + if (IS_ZEBRA_DEBUG_RIB) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_debug("%u:%s: Adding route rn %p, re %p (type %d)", + zvrf_id(zvrf), buf, rn, new, new->type); + } - /* If labeled-unicast route, install transit LSP. */ - if (zebra_rib_labeled_unicast (new)) - zebra_mpls_lsp_install (zvrf, rn, new); + /* If labeled-unicast route, install transit LSP. */ + if (zebra_rib_labeled_unicast(new)) + zebra_mpls_lsp_install(zvrf, rn, new); - if (!RIB_SYSTEM_ROUTE (new)) - { - if (rib_install_kernel (rn, new, NULL)) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - zlog_warn ("%u:%s: Route install failed", - zvrf_id (zvrf), buf); - } - } + if (!RIB_SYSTEM_ROUTE(new)) { + if (rib_install_kernel(rn, new, NULL)) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_warn("%u:%s: Route install failed", zvrf_id(zvrf), + buf); + } + } - UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); + UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); } -static void -rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, - struct route_entry *old) +static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, + struct route_entry *old) { - hook_call(rib_update, rn, "removing existing route"); + hook_call(rib_update, rn, "removing existing route"); - /* Uninstall from kernel. */ - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - zlog_debug ("%u:%s: Deleting route rn %p, re %p (type %d)", - zvrf_id (zvrf), buf, rn, old, old->type); - } + /* Uninstall from kernel. */ + if (IS_ZEBRA_DEBUG_RIB) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_debug("%u:%s: Deleting route rn %p, re %p (type %d)", + zvrf_id(zvrf), buf, rn, old, old->type); + } - /* If labeled-unicast route, uninstall transit LSP. */ - if (zebra_rib_labeled_unicast (old)) - zebra_mpls_lsp_uninstall (zvrf, rn, old); + /* If labeled-unicast route, uninstall transit LSP. */ + if (zebra_rib_labeled_unicast(old)) + zebra_mpls_lsp_uninstall(zvrf, rn, old); + + if (!RIB_SYSTEM_ROUTE(old)) + rib_uninstall_kernel(rn, old); + + UNSET_FLAG(old->status, ROUTE_ENTRY_SELECTED_FIB); + + /* Update nexthop for route, reset changed flag. */ + nexthop_active_update(rn, old, 1); + UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); +} + +static void rib_process_update_fib(struct zebra_vrf *zvrf, + struct route_node *rn, + struct route_entry *old, + struct route_entry *new) +{ + struct nexthop *nexthop = NULL; + int nh_active = 0; + int installed = 1; + + /* + * We have to install or update if a new route has been selected or + * something has changed. + */ + if (new != old || CHECK_FLAG(new->status, ROUTE_ENTRY_CHANGED)) { + hook_call(rib_update, rn, "updating existing route"); + + /* Update the nexthop; we could determine here that nexthop is + * inactive. */ + if (nexthop_active_update(rn, new, 1)) + nh_active = 1; + + /* If nexthop is active, install the selected route, if + * appropriate. If + * the install succeeds, cleanup flags for prior route, if + * different from + * newly selected. + */ + if (nh_active) { + if (IS_ZEBRA_DEBUG_RIB) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + if (new != old) + zlog_debug( + "%u:%s: Updating route rn %p, re %p (type %d) " + "old %p (type %d)", + zvrf_id(zvrf), buf, rn, new, + new->type, old, old->type); + else + zlog_debug( + "%u:%s: Updating route rn %p, re %p (type %d)", + zvrf_id(zvrf), buf, rn, new, + new->type); + } + + /* If labeled-unicast route, uninstall transit LSP. */ + if (zebra_rib_labeled_unicast(old)) + zebra_mpls_lsp_uninstall(zvrf, rn, old); + + /* Non-system route should be installed. */ + if (!RIB_SYSTEM_ROUTE(new)) { + /* If labeled-unicast route, install transit + * LSP. */ + if (zebra_rib_labeled_unicast(new)) + zebra_mpls_lsp_install(zvrf, rn, new); + + if (rib_install_kernel(rn, new, old)) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + installed = 0; + zlog_warn("%u:%s: Route install failed", + zvrf_id(zvrf), buf); + } + } + + /* If install succeeded or system route, cleanup flags + * for prior route. */ + if (installed && new != old) { + if (RIB_SYSTEM_ROUTE(new)) { + if (!RIB_SYSTEM_ROUTE(old)) + rib_uninstall_kernel(rn, old); + } else { + for (nexthop = old->nexthop; nexthop; + nexthop = nexthop->next) + UNSET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + } + } + + /* Update for redistribution. */ + if (installed) + SET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB); + } - if (!RIB_SYSTEM_ROUTE (old)) - rib_uninstall_kernel (rn, old); + /* + * If nexthop for selected route is not active or install + * failed, we + * may need to uninstall and delete for redistribution. + */ + if (!nh_active || !installed) { + if (IS_ZEBRA_DEBUG_RIB) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + if (new != old) + zlog_debug( + "%u:%s: Deleting route rn %p, re %p (type %d) " + "old %p (type %d) - %s", + zvrf_id(zvrf), buf, rn, new, + new->type, old, old->type, + nh_active ? "install failed" + : "nexthop inactive"); + else + zlog_debug( + "%u:%s: Deleting route rn %p, re %p (type %d) - %s", + zvrf_id(zvrf), buf, rn, new, + new->type, + nh_active ? "install failed" + : "nexthop inactive"); + } + + /* If labeled-unicast route, uninstall transit LSP. */ + if (zebra_rib_labeled_unicast(old)) + zebra_mpls_lsp_uninstall(zvrf, rn, old); + + if (!RIB_SYSTEM_ROUTE(old)) + rib_uninstall_kernel(rn, old); + UNSET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB); + } + } else { + /* + * Same route selected; check if in the FIB and if not, + * re-install. This + * is housekeeping code to deal with race conditions in kernel + * with linux + * netlink reporting interface up before IPv4 or IPv6 protocol + * is ready + * to add routes. + */ + if (!RIB_SYSTEM_ROUTE(new)) { + int in_fib = 0; + + for (ALL_NEXTHOPS(new->nexthop, nexthop)) + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB)) { + in_fib = 1; + break; + } + if (!in_fib) + rib_install_kernel(rn, new, NULL); + } + } + + /* Update prior route. */ + if (new != old) { + UNSET_FLAG(old->status, ROUTE_ENTRY_SELECTED_FIB); - UNSET_FLAG (old->status, ROUTE_ENTRY_SELECTED_FIB); + /* Set real nexthop. */ + nexthop_active_update(rn, old, 1); + UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); + } - /* Update nexthop for route, reset changed flag. */ - nexthop_active_update (rn, old, 1); - UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); + /* Clear changed flag. */ + UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); } -static void -rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn, - struct route_entry *old, struct route_entry *new) -{ - struct nexthop *nexthop = NULL; - int nh_active = 0; - int installed = 1; +/* Check if 'alternate' RIB entry is better than 'current'. */ +static struct route_entry *rib_choose_best(struct route_entry *current, + struct route_entry *alternate) +{ + if (current == NULL) + return alternate; + + /* filter route selection in following order: + * - connected beats other types + * - lower distance beats higher + * - lower metric beats higher for equal distance + * - last, hence oldest, route wins tie break. + */ + + /* Connected routes. Pick the last connected + * route of the set of lowest metric connected routes. + */ + if (alternate->type == ZEBRA_ROUTE_CONNECT) { + if (current->type != ZEBRA_ROUTE_CONNECT + || alternate->metric <= current->metric) + return alternate; + + return current; + } - /* - * We have to install or update if a new route has been selected or - * something has changed. - */ - if (new != old || - CHECK_FLAG (new->status, ROUTE_ENTRY_CHANGED)) - { - hook_call(rib_update, rn, "updating existing route"); - - /* Update the nexthop; we could determine here that nexthop is inactive. */ - if (nexthop_active_update (rn, new, 1)) - nh_active = 1; - - /* If nexthop is active, install the selected route, if appropriate. If - * the install succeeds, cleanup flags for prior route, if different from - * newly selected. - */ - if (nh_active) - { - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - if (new != old) - zlog_debug ("%u:%s: Updating route rn %p, re %p (type %d) " - "old %p (type %d)", zvrf_id (zvrf), buf, - rn, new, new->type, old, old->type); - else - zlog_debug ("%u:%s: Updating route rn %p, re %p (type %d)", - zvrf_id (zvrf), buf, rn, new, new->type); - } - - /* If labeled-unicast route, uninstall transit LSP. */ - if (zebra_rib_labeled_unicast (old)) - zebra_mpls_lsp_uninstall (zvrf, rn, old); - - /* Non-system route should be installed. */ - if (!RIB_SYSTEM_ROUTE (new)) - { - /* If labeled-unicast route, install transit LSP. */ - if (zebra_rib_labeled_unicast (new)) - zebra_mpls_lsp_install (zvrf, rn, new); - - if (rib_install_kernel (rn, new, old)) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - installed = 0; - zlog_warn ("%u:%s: Route install failed", zvrf_id (zvrf), buf); - } - } - - /* If install succeeded or system route, cleanup flags for prior route. */ - if (installed && new != old) - { - if (RIB_SYSTEM_ROUTE(new)) - { - if (!RIB_SYSTEM_ROUTE (old)) - rib_uninstall_kernel (rn, old); - } - else - { - for (nexthop = old->nexthop; nexthop; nexthop = nexthop->next) - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - } - - /* Update for redistribution. */ - if (installed) - SET_FLAG (new->status, ROUTE_ENTRY_SELECTED_FIB); - } - - /* - * If nexthop for selected route is not active or install failed, we - * may need to uninstall and delete for redistribution. - */ - if (!nh_active || !installed) - { - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - if (new != old) - zlog_debug ("%u:%s: Deleting route rn %p, re %p (type %d) " - "old %p (type %d) - %s", zvrf_id (zvrf), buf, - rn, new, new->type, old, old->type, - nh_active ? "install failed" : "nexthop inactive"); - else - zlog_debug ("%u:%s: Deleting route rn %p, re %p (type %d) - %s", - zvrf_id (zvrf), buf, rn, new, new->type, - nh_active ? "install failed" : "nexthop inactive"); - } - - /* If labeled-unicast route, uninstall transit LSP. */ - if (zebra_rib_labeled_unicast (old)) - zebra_mpls_lsp_uninstall (zvrf, rn, old); - - if (!RIB_SYSTEM_ROUTE (old)) - rib_uninstall_kernel (rn, old); - UNSET_FLAG (new->status, ROUTE_ENTRY_SELECTED_FIB); - } - } - else - { - /* - * Same route selected; check if in the FIB and if not, re-install. This - * is housekeeping code to deal with race conditions in kernel with linux - * netlink reporting interface up before IPv4 or IPv6 protocol is ready - * to add routes. - */ - if (!RIB_SYSTEM_ROUTE (new)) - { - int in_fib = 0; - - for (ALL_NEXTHOPS(new->nexthop, nexthop)) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - in_fib = 1; - break; - } - if (!in_fib) - rib_install_kernel (rn, new, NULL); - } - } + if (current->type == ZEBRA_ROUTE_CONNECT) + return current; - /* Update prior route. */ - if (new != old) - { - UNSET_FLAG (old->status, ROUTE_ENTRY_SELECTED_FIB); + /* higher distance loses */ + if (alternate->distance < current->distance) + return alternate; + if (current->distance < alternate->distance) + return current; - /* Set real nexthop. */ - nexthop_active_update (rn, old, 1); - UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); - } + /* metric tie-breaks equal distance */ + if (alternate->metric <= current->metric) + return alternate; - /* Clear changed flag. */ - UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); + return current; } -/* Check if 'alternate' RIB entry is better than 'current'. */ -static struct route_entry * -rib_choose_best (struct route_entry *current, struct route_entry *alternate) -{ - if (current == NULL) - return alternate; - - /* filter route selection in following order: - * - connected beats other types - * - lower distance beats higher - * - lower metric beats higher for equal distance - * - last, hence oldest, route wins tie break. - */ - - /* Connected routes. Pick the last connected - * route of the set of lowest metric connected routes. - */ - if (alternate->type == ZEBRA_ROUTE_CONNECT) - { - if (current->type != ZEBRA_ROUTE_CONNECT - || alternate->metric <= current->metric) - return alternate; +/* Core function for processing routing information base. */ +static void rib_process(struct route_node *rn) +{ + struct route_entry *re; + struct route_entry *next; + struct route_entry *old_selected = NULL; + struct route_entry *new_selected = NULL; + struct route_entry *old_fib = NULL; + struct route_entry *new_fib = NULL; + struct route_entry *best = NULL; + char buf[SRCDEST2STR_BUFFER]; + rib_dest_t *dest; + struct zebra_vrf *zvrf = NULL; + struct prefix *p, *src_p; + srcdest_rnode_prefixes(rn, &p, &src_p); + vrf_id_t vrf_id = VRF_UNKNOWN; + + assert(rn); + + dest = rib_dest_from_rnode(rn); + if (dest) { + zvrf = rib_dest_vrf(dest); + vrf_id = zvrf_id(zvrf); + } - return current; - } + if (IS_ZEBRA_DEBUG_RIB) + srcdest_rnode2str(rn, buf, sizeof(buf)); - if (current->type == ZEBRA_ROUTE_CONNECT) - return current; + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("%u:%s: Processing rn %p", vrf_id, buf, rn); - /* higher distance loses */ - if (alternate->distance < current->distance) - return alternate; - if (current->distance < alternate->distance) - return current; + RNODE_FOREACH_RE_SAFE(rn, re, next) + { + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u:%s: Examine re %p (type %d) status %x flags %x " + "dist %d metric %d", + vrf_id, buf, re, re->type, re->status, + re->flags, re->distance, re->metric); + + UNSET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); + + /* Currently selected re. */ + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) { + assert(old_selected == NULL); + old_selected = re; + } + /* Currently in fib */ + if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) { + assert(old_fib == NULL); + old_fib = re; + } - /* metric tie-breaks equal distance */ - if (alternate->metric <= current->metric) - return alternate; + /* Skip deleted entries from selection */ + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + /* Skip unreachable nexthop. */ + /* This first call to nexthop_active_update is merely to + * determine if + * there's any change to nexthops associated with this RIB + * entry. Now, + * rib_process() can be invoked due to an external event such as + * link + * down or due to next-hop-tracking evaluation. In the latter + * case, + * a decision has already been made that the NHs have changed. + * So, no + * need to invoke a potentially expensive call again. Further, + * since + * the change might be in a recursive NH which is not caught in + * the nexthop_active_update() code. Thus, we might miss changes + * to + * recursive NHs. + */ + if (!CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED) + && !nexthop_active_update(rn, re, 0)) { + if (re->type == ZEBRA_ROUTE_TABLE) { + /* XXX: HERE BE DRAGONS!!!!! + * In all honesty, I have not yet figured out + * what this part + * does or why the ROUTE_ENTRY_CHANGED test + * above is correct + * or why we need to delete a route here, and + * also not whether + * this concerns both selected and fib route, or + * only selected + * or only fib */ + /* This entry was denied by the 'ip protocol + * table' route-map, we + * need to delete it */ + if (re != old_selected) { + if (IS_ZEBRA_DEBUG_RIB) + zlog_debug( + "%s: %s: imported via import-table but denied " + "by the ip protocol table route-map", + __func__, buf); + rib_unlink(rn, re); + } else + SET_FLAG(re->status, + ROUTE_ENTRY_REMOVED); + } + + continue; + } - return current; -} + /* Infinite distance. */ + if (re->distance == DISTANCE_INFINITY) { + UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED); + continue; + } -/* Core function for processing routing information base. */ -static void -rib_process (struct route_node *rn) -{ - struct route_entry *re; - struct route_entry *next; - struct route_entry *old_selected = NULL; - struct route_entry *new_selected = NULL; - struct route_entry *old_fib = NULL; - struct route_entry *new_fib = NULL; - struct route_entry *best = NULL; - char buf[SRCDEST2STR_BUFFER]; - rib_dest_t *dest; - struct zebra_vrf *zvrf = NULL; - struct prefix *p, *src_p; - srcdest_rnode_prefixes(rn, &p, &src_p); - vrf_id_t vrf_id = VRF_UNKNOWN; - - assert (rn); - - dest = rib_dest_from_rnode (rn); - if (dest) - { - zvrf = rib_dest_vrf (dest); - vrf_id = zvrf_id (zvrf); - } + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_FIB_OVERRIDE)) { + best = rib_choose_best(new_fib, re); + if (new_fib && best != new_fib) + UNSET_FLAG(new_fib->status, + ROUTE_ENTRY_CHANGED); + new_fib = best; + } else { + best = rib_choose_best(new_selected, re); + if (new_selected && best != new_selected) + UNSET_FLAG(new_selected->status, + ROUTE_ENTRY_CHANGED); + new_selected = best; + } + if (best != re) + UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED); + } /* RNODE_FOREACH_RE */ + + /* If no FIB override route, use the selected route also for FIB */ + if (new_fib == NULL) + new_fib = new_selected; + + /* After the cycle is finished, the following pointers will be set: + * old_selected --- RE entry currently having SELECTED + * new_selected --- RE entry that is newly SELECTED + * old_fib --- RE entry currently in kernel FIB + * new_fib --- RE entry that is newly to be in kernel FIB + * + * new_selected will get SELECTED flag, and is going to be redistributed + * the zclients. new_fib (which can be new_selected) will be installed + * in kernel. + */ + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) { + zlog_debug( + "%u:%s: After processing: old_selected %p new_selected %p old_fib %p new_fib %p", + vrf_id, buf, (void *)old_selected, (void *)new_selected, + (void *)old_fib, (void *)new_fib); + } - if (IS_ZEBRA_DEBUG_RIB) - srcdest_rnode2str(rn, buf, sizeof(buf)); + /* Buffer ROUTE_ENTRY_CHANGED here, because it will get cleared if + * fib == selected */ + bool selected_changed = new_selected && CHECK_FLAG(new_selected->status, + ROUTE_ENTRY_CHANGED); + + /* Update fib according to selection results */ + if (new_fib && old_fib) + rib_process_update_fib(zvrf, rn, old_fib, new_fib); + else if (new_fib) + rib_process_add_fib(zvrf, rn, new_fib); + else if (old_fib) + rib_process_del_fib(zvrf, rn, old_fib); + + /* Redistribute SELECTED entry */ + if (old_selected != new_selected || selected_changed) { + struct nexthop *nexthop; + + /* Check if we have a FIB route for the destination, otherwise, + * don't redistribute it */ + for (ALL_NEXTHOPS(new_fib ? new_fib->nexthop : NULL, nexthop)) { + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) { + break; + } + } + if (!nexthop) + new_selected = NULL; - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u:%s: Processing rn %p", vrf_id, buf, rn); + if (new_selected && new_selected != new_fib) { + nexthop_active_update(rn, new_selected, 1); + UNSET_FLAG(new_selected->status, ROUTE_ENTRY_CHANGED); + } - RNODE_FOREACH_RE_SAFE (rn, re, next) - { - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u:%s: Examine re %p (type %d) status %x flags %x " - "dist %d metric %d", - vrf_id, buf, re, re->type, re->status, - re->flags, re->distance, re->metric); - - UNSET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - - /* Currently selected re. */ - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED)) - { - assert (old_selected == NULL); - old_selected = re; - } - /* Currently in fib */ - if (CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB)) - { - assert (old_fib == NULL); - old_fib = re; - } - - /* Skip deleted entries from selection */ - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - - /* Skip unreachable nexthop. */ - /* This first call to nexthop_active_update is merely to determine if - * there's any change to nexthops associated with this RIB entry. Now, - * rib_process() can be invoked due to an external event such as link - * down or due to next-hop-tracking evaluation. In the latter case, - * a decision has already been made that the NHs have changed. So, no - * need to invoke a potentially expensive call again. Further, since - * the change might be in a recursive NH which is not caught in - * the nexthop_active_update() code. Thus, we might miss changes to - * recursive NHs. - */ - if (!CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED) && - ! nexthop_active_update (rn, re, 0)) - { - if (re->type == ZEBRA_ROUTE_TABLE) - { - /* XXX: HERE BE DRAGONS!!!!! - * In all honesty, I have not yet figured out what this part - * does or why the ROUTE_ENTRY_CHANGED test above is correct - * or why we need to delete a route here, and also not whether - * this concerns both selected and fib route, or only selected - * or only fib */ - /* This entry was denied by the 'ip protocol table' route-map, we - * need to delete it */ - if (re != old_selected) - { - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%s: %s: imported via import-table but denied " - "by the ip protocol table route-map", - __func__, buf); - rib_unlink (rn, re); + if (old_selected) { + if (!new_selected) + redistribute_delete(p, src_p, old_selected); + if (old_selected != new_selected) + UNSET_FLAG(old_selected->flags, + ZEBRA_FLAG_SELECTED); } - else - SET_FLAG (re->status, ROUTE_ENTRY_REMOVED); - } - - continue; - } - - /* Infinite distance. */ - if (re->distance == DISTANCE_INFINITY) - { - UNSET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - continue; - } - - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_FIB_OVERRIDE)) - { - best = rib_choose_best(new_fib, re); - if (new_fib && best != new_fib) - UNSET_FLAG (new_fib->status, ROUTE_ENTRY_CHANGED); - new_fib = best; - } - else - { - best = rib_choose_best(new_selected, re); - if (new_selected && best != new_selected) - UNSET_FLAG (new_selected->status, ROUTE_ENTRY_CHANGED); - new_selected = best; - } - if (best != re) - UNSET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - } /* RNODE_FOREACH_RE */ - - /* If no FIB override route, use the selected route also for FIB */ - if (new_fib == NULL) - new_fib = new_selected; - - /* After the cycle is finished, the following pointers will be set: - * old_selected --- RE entry currently having SELECTED - * new_selected --- RE entry that is newly SELECTED - * old_fib --- RE entry currently in kernel FIB - * new_fib --- RE entry that is newly to be in kernel FIB - * - * new_selected will get SELECTED flag, and is going to be redistributed - * the zclients. new_fib (which can be new_selected) will be installed in kernel. - */ - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - { - zlog_debug ("%u:%s: After processing: old_selected %p new_selected %p old_fib %p new_fib %p", - vrf_id, buf, - (void *)old_selected, - (void *)new_selected, - (void *)old_fib, - (void *)new_fib); - } - /* Buffer ROUTE_ENTRY_CHANGED here, because it will get cleared if - * fib == selected */ - bool selected_changed = new_selected && CHECK_FLAG(new_selected->status, - ROUTE_ENTRY_CHANGED); - - /* Update fib according to selection results */ - if (new_fib && old_fib) - rib_process_update_fib (zvrf, rn, old_fib, new_fib); - else if (new_fib) - rib_process_add_fib (zvrf, rn, new_fib); - else if (old_fib) - rib_process_del_fib (zvrf, rn, old_fib); - - /* Redistribute SELECTED entry */ - if (old_selected != new_selected || selected_changed) - { - struct nexthop *nexthop; - - /* Check if we have a FIB route for the destination, otherwise, - * don't redistribute it */ - for (ALL_NEXTHOPS(new_fib ? new_fib->nexthop : NULL, nexthop)) - { - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) - { - break; - } - } - if (!nexthop) - new_selected = NULL; - - if (new_selected && new_selected != new_fib) - { - nexthop_active_update(rn, new_selected, 1); - UNSET_FLAG(new_selected->status, ROUTE_ENTRY_CHANGED); - } - - if (old_selected) - { - if (!new_selected) - redistribute_delete(p, src_p, old_selected); - if (old_selected != new_selected) - UNSET_FLAG (old_selected->flags, ZEBRA_FLAG_SELECTED); - } - - if (new_selected) - { - /* Install new or replace existing redistributed entry */ - SET_FLAG (new_selected->flags, ZEBRA_FLAG_SELECTED); - redistribute_update (p, src_p, new_selected, old_selected); - } - } + if (new_selected) { + /* Install new or replace existing redistributed entry + */ + SET_FLAG(new_selected->flags, ZEBRA_FLAG_SELECTED); + redistribute_update(p, src_p, new_selected, + old_selected); + } + } - /* Remove all RE entries queued for removal */ - RNODE_FOREACH_RE_SAFE (rn, re, next) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - { - if (IS_ZEBRA_DEBUG_RIB) - { - rnode_debug (rn, vrf_id, "rn %p, removing re %p", - (void *)rn, (void *)re); - } - rib_unlink(rn, re); - } - } + /* Remove all RE entries queued for removal */ + RNODE_FOREACH_RE_SAFE(rn, re, next) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) { + if (IS_ZEBRA_DEBUG_RIB) { + rnode_debug(rn, vrf_id, "rn %p, removing re %p", + (void *)rn, (void *)re); + } + rib_unlink(rn, re); + } + } - /* - * Check if the dest can be deleted now. - */ - rib_gc_dest (rn); + /* + * Check if the dest can be deleted now. + */ + rib_gc_dest(rn); } /* Take a list of route_node structs and return 1, if there was a record - * picked from it and processed by rib_process(). Don't process more, + * picked from it and processed by rib_process(). Don't process more, * than one RN record; operate only in the specified sub-queue. */ -static unsigned int -process_subq (struct list * subq, u_char qindex) +static unsigned int process_subq(struct list *subq, u_char qindex) { - struct listnode *lnode = listhead (subq); - struct route_node *rnode; - rib_dest_t *dest; - struct zebra_vrf *zvrf = NULL; + struct listnode *lnode = listhead(subq); + struct route_node *rnode; + rib_dest_t *dest; + struct zebra_vrf *zvrf = NULL; - if (!lnode) - return 0; + if (!lnode) + return 0; - rnode = listgetdata (lnode); - dest = rib_dest_from_rnode (rnode); - if (dest) - zvrf = rib_dest_vrf (dest); + rnode = listgetdata(lnode); + dest = rib_dest_from_rnode(rnode); + if (dest) + zvrf = rib_dest_vrf(dest); - rib_process (rnode); + rib_process(rnode); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rnode, buf, sizeof(buf)); - zlog_debug ("%u:%s: rn %p dequeued from sub-queue %u", - zvrf ? zvrf_id (zvrf) : 0, buf, rnode, qindex); - } + if (IS_ZEBRA_DEBUG_RIB_DETAILED) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rnode, buf, sizeof(buf)); + zlog_debug("%u:%s: rn %p dequeued from sub-queue %u", + zvrf ? zvrf_id(zvrf) : 0, buf, rnode, qindex); + } - if (rnode->info) - UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex)); + if (rnode->info) + UNSET_FLAG(rib_dest_from_rnode(rnode)->flags, + RIB_ROUTE_QUEUED(qindex)); #if 0 else @@ -1714,231 +1656,229 @@ process_subq (struct list * subq, u_char qindex) zlog_backtrace(LOG_DEBUG); } #endif - route_unlock_node (rnode); - list_delete_node (subq, lnode); - return 1; + route_unlock_node(rnode); + list_delete_node(subq, lnode); + return 1; } /* * All meta queues have been processed. Trigger next-hop evaluation. */ -static void -meta_queue_process_complete (struct work_queue *dummy) +static void meta_queue_process_complete(struct work_queue *dummy) { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - /* Evaluate nexthops for those VRFs which underwent route processing. This - * should limit the evaluation to the necessary VRFs in most common - * situations. - */ - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - { - zvrf = vrf->info; - if (zvrf == NULL || !(zvrf->flags & ZEBRA_VRF_RIB_SCHEDULED)) - continue; - - zvrf->flags &= ~ZEBRA_VRF_RIB_SCHEDULED; - zebra_evaluate_rnh(zvrf_id (zvrf), AF_INET, 0, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(zvrf_id (zvrf), AF_INET, 0, RNH_IMPORT_CHECK_TYPE, NULL); - zebra_evaluate_rnh(zvrf_id (zvrf), AF_INET6, 0, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(zvrf_id (zvrf), AF_INET6, 0, RNH_IMPORT_CHECK_TYPE, NULL); - } + /* Evaluate nexthops for those VRFs which underwent route processing. + * This + * should limit the evaluation to the necessary VRFs in most common + * situations. + */ + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + { + zvrf = vrf->info; + if (zvrf == NULL || !(zvrf->flags & ZEBRA_VRF_RIB_SCHEDULED)) + continue; + + zvrf->flags &= ~ZEBRA_VRF_RIB_SCHEDULED; + zebra_evaluate_rnh(zvrf_id(zvrf), AF_INET, 0, RNH_NEXTHOP_TYPE, + NULL); + zebra_evaluate_rnh(zvrf_id(zvrf), AF_INET, 0, + RNH_IMPORT_CHECK_TYPE, NULL); + zebra_evaluate_rnh(zvrf_id(zvrf), AF_INET6, 0, RNH_NEXTHOP_TYPE, + NULL); + zebra_evaluate_rnh(zvrf_id(zvrf), AF_INET6, 0, + RNH_IMPORT_CHECK_TYPE, NULL); + } - /* Schedule LSPs for processing, if needed. */ - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (mpls_should_lsps_be_processed(zvrf)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: Scheduling all LSPs upon RIB completion", zvrf_id (zvrf)); - zebra_mpls_lsp_schedule (zvrf); - mpls_unmark_lsps_for_processing(zvrf); - } + /* Schedule LSPs for processing, if needed. */ + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (mpls_should_lsps_be_processed(zvrf)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: Scheduling all LSPs upon RIB completion", + zvrf_id(zvrf)); + zebra_mpls_lsp_schedule(zvrf); + mpls_unmark_lsps_for_processing(zvrf); + } } /* Dispatch the meta queue by picking, processing and unlocking the next RN from - * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data + * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and + * data * is pointed to the meta queue structure. */ -static wq_item_status -meta_queue_process (struct work_queue *dummy, void *data) +static wq_item_status meta_queue_process(struct work_queue *dummy, void *data) { - struct meta_queue * mq = data; - unsigned i; + struct meta_queue *mq = data; + unsigned i; - for (i = 0; i < MQ_SIZE; i++) - if (process_subq (mq->subq[i], i)) - { - mq->size--; - break; - } - return mq->size ? WQ_REQUEUE : WQ_SUCCESS; + for (i = 0; i < MQ_SIZE; i++) + if (process_subq(mq->subq[i], i)) { + mq->size--; + break; + } + return mq->size ? WQ_REQUEUE : WQ_SUCCESS; } /* * Map from rib types to queue type (priority) in meta queue */ static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = { - [ZEBRA_ROUTE_SYSTEM] = 4, - [ZEBRA_ROUTE_KERNEL] = 0, - [ZEBRA_ROUTE_CONNECT] = 0, - [ZEBRA_ROUTE_STATIC] = 1, - [ZEBRA_ROUTE_RIP] = 2, - [ZEBRA_ROUTE_RIPNG] = 2, - [ZEBRA_ROUTE_OSPF] = 2, - [ZEBRA_ROUTE_OSPF6] = 2, - [ZEBRA_ROUTE_ISIS] = 2, - [ZEBRA_ROUTE_BGP] = 3, - [ZEBRA_ROUTE_PIM] = 4, // Shouldn't happen but for safety - [ZEBRA_ROUTE_EIGRP] = 2, - [ZEBRA_ROUTE_NHRP] = 2, - [ZEBRA_ROUTE_HSLS] = 4, - [ZEBRA_ROUTE_OLSR] = 4, - [ZEBRA_ROUTE_TABLE] = 1, - [ZEBRA_ROUTE_LDP] = 4, - [ZEBRA_ROUTE_VNC] = 3, - [ZEBRA_ROUTE_VNC_DIRECT] = 3, - [ZEBRA_ROUTE_VNC_DIRECT_RH] = 3, - [ZEBRA_ROUTE_BGP_DIRECT] = 3, - [ZEBRA_ROUTE_BGP_DIRECT_EXT] = 3, - [ZEBRA_ROUTE_BABEL] = 2, - [ZEBRA_ROUTE_ALL] = 4, // Shouldn't happen but for safety + [ZEBRA_ROUTE_SYSTEM] = 4, + [ZEBRA_ROUTE_KERNEL] = 0, + [ZEBRA_ROUTE_CONNECT] = 0, + [ZEBRA_ROUTE_STATIC] = 1, + [ZEBRA_ROUTE_RIP] = 2, + [ZEBRA_ROUTE_RIPNG] = 2, + [ZEBRA_ROUTE_OSPF] = 2, + [ZEBRA_ROUTE_OSPF6] = 2, + [ZEBRA_ROUTE_ISIS] = 2, + [ZEBRA_ROUTE_BGP] = 3, + [ZEBRA_ROUTE_PIM] = 4, // Shouldn't happen but for safety + [ZEBRA_ROUTE_EIGRP] = 2, + [ZEBRA_ROUTE_NHRP] = 2, + [ZEBRA_ROUTE_HSLS] = 4, + [ZEBRA_ROUTE_OLSR] = 4, + [ZEBRA_ROUTE_TABLE] = 1, + [ZEBRA_ROUTE_LDP] = 4, + [ZEBRA_ROUTE_VNC] = 3, + [ZEBRA_ROUTE_VNC_DIRECT] = 3, + [ZEBRA_ROUTE_VNC_DIRECT_RH] = 3, + [ZEBRA_ROUTE_BGP_DIRECT] = 3, + [ZEBRA_ROUTE_BGP_DIRECT_EXT] = 3, + [ZEBRA_ROUTE_BABEL] = 2, + [ZEBRA_ROUTE_ALL] = 4, // Shouldn't happen but for safety }; /* Look into the RN and queue it into one or more priority queues, * increasing the size for each data push done. */ -static void -rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn) +static void rib_meta_queue_add(struct meta_queue *mq, struct route_node *rn) { - struct route_entry *re; + struct route_entry *re; - RNODE_FOREACH_RE (rn, re) - { - u_char qindex = meta_queue_map[re->type]; - struct zebra_vrf *zvrf; - - /* Invariant: at this point we always have rn->info set. */ - if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags, - RIB_ROUTE_QUEUED (qindex))) + RNODE_FOREACH_RE(rn, re) { - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rnode_debug (rn, re->vrf_id, "rn %p is already queued in sub-queue %u", - (void *)rn, qindex); - continue; - } + u_char qindex = meta_queue_map[re->type]; + struct zebra_vrf *zvrf; + + /* Invariant: at this point we always have rn->info set. */ + if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags, + RIB_ROUTE_QUEUED(qindex))) { + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + rnode_debug( + rn, re->vrf_id, + "rn %p is already queued in sub-queue %u", + (void *)rn, qindex); + continue; + } - SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex)); - listnode_add (mq->subq[qindex], rn); - route_lock_node (rn); - mq->size++; + SET_FLAG(rib_dest_from_rnode(rn)->flags, + RIB_ROUTE_QUEUED(qindex)); + listnode_add(mq->subq[qindex], rn); + route_lock_node(rn); + mq->size++; - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rnode_debug (rn, re->vrf_id, "queued rn %p into sub-queue %u", - (void *)rn, qindex); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + rnode_debug(rn, re->vrf_id, + "queued rn %p into sub-queue %u", + (void *)rn, qindex); - zvrf = zebra_vrf_lookup_by_id (re->vrf_id); - if (zvrf) - zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED; - } + zvrf = zebra_vrf_lookup_by_id(re->vrf_id); + if (zvrf) + zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED; + } } /* Add route_node to work queue and schedule processing */ -void -rib_queue_add (struct route_node *rn) +void rib_queue_add(struct route_node *rn) { - assert (rn); - - /* Pointless to queue a route_node with no RIB entries to add or remove */ - if (!rnode_to_ribs (rn)) - { - zlog_debug ("%s: called for route_node (%p, %d) with no ribs", - __func__, (void *)rn, rn->lock); - zlog_backtrace(LOG_DEBUG); - return; - } + assert(rn); - if (zebrad.ribq == NULL) - { - zlog_err ("%s: work_queue does not exist!", __func__); - return; - } + /* Pointless to queue a route_node with no RIB entries to add or remove + */ + if (!rnode_to_ribs(rn)) { + zlog_debug("%s: called for route_node (%p, %d) with no ribs", + __func__, (void *)rn, rn->lock); + zlog_backtrace(LOG_DEBUG); + return; + } - /* - * The RIB queue should normally be either empty or holding the only - * work_queue_item element. In the latter case this element would - * hold a pointer to the meta queue structure, which must be used to - * actually queue the route nodes to process. So create the MQ - * holder, if necessary, then push the work into it in any case. - * This semantics was introduced after 0.99.9 release. - */ - if (!zebrad.ribq->items->count) - work_queue_add (zebrad.ribq, zebrad.mq); + if (zebrad.ribq == NULL) { + zlog_err("%s: work_queue does not exist!", __func__); + return; + } + + /* + * The RIB queue should normally be either empty or holding the only + * work_queue_item element. In the latter case this element would + * hold a pointer to the meta queue structure, which must be used to + * actually queue the route nodes to process. So create the MQ + * holder, if necessary, then push the work into it in any case. + * This semantics was introduced after 0.99.9 release. + */ + if (!zebrad.ribq->items->count) + work_queue_add(zebrad.ribq, zebrad.mq); - rib_meta_queue_add (zebrad.mq, rn); + rib_meta_queue_add(zebrad.mq, rn); - return; + return; } /* Create new meta queue. A destructor function doesn't seem to be necessary here. */ -static struct meta_queue * -meta_queue_new (void) +static struct meta_queue *meta_queue_new(void) { - struct meta_queue *new; - unsigned i; + struct meta_queue *new; + unsigned i; - new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue)); - assert(new); + new = XCALLOC(MTYPE_WORK_QUEUE, sizeof(struct meta_queue)); + assert(new); - for (i = 0; i < MQ_SIZE; i++) - { - new->subq[i] = list_new (); - assert(new->subq[i]); - } + for (i = 0; i < MQ_SIZE; i++) { + new->subq[i] = list_new(); + assert(new->subq[i]); + } - return new; + return new; } -void -meta_queue_free (struct meta_queue *mq) +void meta_queue_free(struct meta_queue *mq) { - unsigned i; + unsigned i; - for (i = 0; i < MQ_SIZE; i++) - list_delete (mq->subq[i]); + for (i = 0; i < MQ_SIZE; i++) + list_delete(mq->subq[i]); - XFREE (MTYPE_WORK_QUEUE, mq); + XFREE(MTYPE_WORK_QUEUE, mq); } /* initialise zebra rib work queue */ -static void -rib_queue_init (struct zebra_t *zebra) +static void rib_queue_init(struct zebra_t *zebra) { - assert (zebra); - - if (! (zebra->ribq = work_queue_new (zebra->master, - "route_node processing"))) - { - zlog_err ("%s: could not initialise work queue!", __func__); - return; - } + assert(zebra); + + if (!(zebra->ribq = + work_queue_new(zebra->master, "route_node processing"))) { + zlog_err("%s: could not initialise work queue!", __func__); + return; + } - /* fill in the work queue spec */ - zebra->ribq->spec.workfunc = &meta_queue_process; - zebra->ribq->spec.errorfunc = NULL; - zebra->ribq->spec.completion_func = &meta_queue_process_complete; - /* XXX: TODO: These should be runtime configurable via vty */ - zebra->ribq->spec.max_retries = 3; - zebra->ribq->spec.hold = rib_process_hold_time; - - if (!(zebra->mq = meta_queue_new ())) - { - zlog_err ("%s: could not initialise meta queue!", __func__); - return; - } - return; + /* fill in the work queue spec */ + zebra->ribq->spec.workfunc = &meta_queue_process; + zebra->ribq->spec.errorfunc = NULL; + zebra->ribq->spec.completion_func = &meta_queue_process_complete; + /* XXX: TODO: These should be runtime configurable via vty */ + zebra->ribq->spec.max_retries = 3; + zebra->ribq->spec.hold = rib_process_hold_time; + + if (!(zebra->mq = meta_queue_new())) { + zlog_err("%s: could not initialise meta queue!", __func__); + return; + } + return; } /* RIB updates are processed via a queue of pointers to route_nodes. @@ -1967,7 +1907,7 @@ rib_queue_init (struct zebra_t *zebra) * ('dest'). Queueing state for a route_node is kept on the dest. The * dest is created on-demand by rib_link() and is kept around at least * as long as there are ribs hanging off it (@see rib_gc_dest()). - * + * * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code): * * - route_nodes: refcounted by: @@ -1977,65 +1917,59 @@ rib_queue_init (struct zebra_t *zebra) * - managed by: rib_addqueue, rib_process. * */ - + /* Add RE to head of the route node. */ -static void -rib_link (struct route_node *rn, struct route_entry *re, int process) -{ - struct route_entry *head; - rib_dest_t *dest; - afi_t afi; - const char *rmap_name; - - assert (re && rn); - - dest = rib_dest_from_rnode (rn); - if (!dest) - { - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rnode_debug (rn, re->vrf_id, "rn %p adding dest", rn); +static void rib_link(struct route_node *rn, struct route_entry *re, int process) +{ + struct route_entry *head; + rib_dest_t *dest; + afi_t afi; + const char *rmap_name; - dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t)); - route_lock_node (rn); /* rn route table reference */ - rn->info = dest; - dest->rnode = rn; - } + assert(re && rn); - head = dest->routes; - if (head) - { - head->prev = re; - } - re->next = head; - dest->routes = re; + dest = rib_dest_from_rnode(rn); + if (!dest) { + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + rnode_debug(rn, re->vrf_id, "rn %p adding dest", rn); - afi = (rn->p.family == AF_INET) ? AFI_IP : - (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX; - if (is_zebra_import_table_enabled (afi, re->table)) - { - rmap_name = zebra_get_import_table_route_map (afi, re->table); - zebra_add_import_table_entry(rn, re, rmap_name); - } - else - if (process) - rib_queue_add (rn); -} - -void -rib_addnode (struct route_node *rn, struct route_entry *re, int process) -{ - /* RE node has been un-removed before route-node is processed. - * route_node must hence already be on the queue for processing.. - */ - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - { - if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, re->vrf_id, "rn %p, un-removed re %p", (void *)rn, (void *)re); + dest = XCALLOC(MTYPE_RIB_DEST, sizeof(rib_dest_t)); + route_lock_node(rn); /* rn route table reference */ + rn->info = dest; + dest->rnode = rn; + } - UNSET_FLAG (re->status, ROUTE_ENTRY_REMOVED); - return; - } - rib_link (rn, re, process); + head = dest->routes; + if (head) { + head->prev = re; + } + re->next = head; + dest->routes = re; + + afi = (rn->p.family == AF_INET) + ? AFI_IP + : (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX; + if (is_zebra_import_table_enabled(afi, re->table)) { + rmap_name = zebra_get_import_table_route_map(afi, re->table); + zebra_add_import_table_entry(rn, re, rmap_name); + } else if (process) + rib_queue_add(rn); +} + +void rib_addnode(struct route_node *rn, struct route_entry *re, int process) +{ + /* RE node has been un-removed before route-node is processed. + * route_node must hence already be on the queue for processing.. + */ + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) { + if (IS_ZEBRA_DEBUG_RIB) + rnode_debug(rn, re->vrf_id, "rn %p, un-removed re %p", + (void *)rn, (void *)re); + + UNSET_FLAG(re->status, ROUTE_ENTRY_REMOVED); + return; + } + rib_link(rn, re, process); } /* @@ -2047,64 +1981,60 @@ rib_addnode (struct route_node *rn, struct route_entry *re, int process) * rib_gc_dest() at some point. This allows a rib_dest_t that is no * longer required to be deleted. */ -void -rib_unlink (struct route_node *rn, struct route_entry *re) +void rib_unlink(struct route_node *rn, struct route_entry *re) { - rib_dest_t *dest; - - assert (rn && re); - - if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, re->vrf_id, "rn %p, re %p", (void *)rn, (void *)re); - - dest = rib_dest_from_rnode (rn); + rib_dest_t *dest; - if (re->next) - re->next->prev = re->prev; + assert(rn && re); - if (re->prev) - re->prev->next = re->next; - else - { - dest->routes = re->next; - } + if (IS_ZEBRA_DEBUG_RIB) + rnode_debug(rn, re->vrf_id, "rn %p, re %p", (void *)rn, + (void *)re); - /* free RE and nexthops */ - zebra_deregister_rnh_static_nexthops (re->vrf_id, re->nexthop, rn); - nexthops_free(re->nexthop); - XFREE (MTYPE_RE, re); + dest = rib_dest_from_rnode(rn); -} + if (re->next) + re->next->prev = re->prev; -void -rib_delnode (struct route_node *rn, struct route_entry *re) -{ - afi_t afi; + if (re->prev) + re->prev->next = re->next; + else { + dest->routes = re->next; + } - if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, re->vrf_id, "rn %p, re %p, removing", (void *)rn, (void *)re); - SET_FLAG (re->status, ROUTE_ENTRY_REMOVED); + /* free RE and nexthops */ + zebra_deregister_rnh_static_nexthops(re->vrf_id, re->nexthop, rn); + nexthops_free(re->nexthop); + XFREE(MTYPE_RE, re); +} + +void rib_delnode(struct route_node *rn, struct route_entry *re) +{ + afi_t afi; + + if (IS_ZEBRA_DEBUG_RIB) + rnode_debug(rn, re->vrf_id, "rn %p, re %p, removing", + (void *)rn, (void *)re); + SET_FLAG(re->status, ROUTE_ENTRY_REMOVED); + + afi = (rn->p.family == AF_INET) + ? AFI_IP + : (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX; + if (is_zebra_import_table_enabled(afi, re->table)) { + zebra_del_import_table_entry(rn, re); + /* Just clean up if non main table */ + if (IS_ZEBRA_DEBUG_RIB) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_debug( + "%u:%s: Freeing route rn %p, re %p (type %d)", + re->vrf_id, buf, rn, re, re->type); + } - afi = (rn->p.family == AF_INET) ? AFI_IP : - (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX; - if (is_zebra_import_table_enabled (afi, re->table)) - { - zebra_del_import_table_entry(rn, re); - /* Just clean up if non main table */ - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - zlog_debug ("%u:%s: Freeing route rn %p, re %p (type %d)", - re->vrf_id, buf, rn, re, re->type); - } - - rib_unlink(rn, re); - } - else - { - rib_queue_add (rn); - } + rib_unlink(rn, re); + } else { + rib_queue_add(rn); + } } /* This function dumps the contents of a given RE entry into @@ -2112,115 +2042,95 @@ rib_delnode (struct route_node *rn, struct route_entry *re) * question are passed as 1st and 2nd arguments. */ -void _route_entry_dump (const char * func, - union prefixconstptr pp, - union prefixconstptr src_pp, - const struct route_entry * re) -{ - const struct prefix *p = pp.p; - const struct prefix *src_p = src_pp.p; - bool is_srcdst = src_p && src_p->prefixlen; - char straddr[PREFIX_STRLEN]; - char srcaddr[PREFIX_STRLEN]; - struct nexthop *nexthop; - - zlog_debug ("%s: dumping RE entry %p for %s%s%s vrf %u", func, (const void *)re, - prefix2str(pp, straddr, sizeof(straddr)), - is_srcdst ? " from " : "", - is_srcdst ? prefix2str(src_pp, srcaddr, sizeof(srcaddr)) : "", - re->vrf_id); - zlog_debug - ( - "%s: refcnt == %lu, uptime == %lu, type == %u, instance == %d, table == %d", - func, - re->refcnt, - (unsigned long) re->uptime, - re->type, - re->instance, - re->table - ); - zlog_debug - ( - "%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u", - func, - re->metric, - re->mtu, - re->distance, - re->flags, - re->status - ); - zlog_debug - ( - "%s: nexthop_num == %u, nexthop_active_num == %u", - func, - re->nexthop_num, - re->nexthop_active_num - ); - - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN); - zlog_debug - ( - "%s: %s %s with flags %s%s%s", - func, - (nexthop->rparent ? " NH" : "NH"), - straddr, - (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""), - (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""), - (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "") - ); - } - zlog_debug ("%s: dump complete", func); +void _route_entry_dump(const char *func, union prefixconstptr pp, + union prefixconstptr src_pp, + const struct route_entry *re) +{ + const struct prefix *p = pp.p; + const struct prefix *src_p = src_pp.p; + bool is_srcdst = src_p && src_p->prefixlen; + char straddr[PREFIX_STRLEN]; + char srcaddr[PREFIX_STRLEN]; + struct nexthop *nexthop; + + zlog_debug("%s: dumping RE entry %p for %s%s%s vrf %u", func, + (const void *)re, prefix2str(pp, straddr, sizeof(straddr)), + is_srcdst ? " from " : "", + is_srcdst ? prefix2str(src_pp, srcaddr, sizeof(srcaddr)) + : "", + re->vrf_id); + zlog_debug( + "%s: refcnt == %lu, uptime == %lu, type == %u, instance == %d, table == %d", + func, re->refcnt, (unsigned long)re->uptime, re->type, + re->instance, re->table); + zlog_debug( + "%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u", + func, re->metric, re->mtu, re->distance, re->flags, re->status); + zlog_debug("%s: nexthop_num == %u, nexthop_active_num == %u", func, + re->nexthop_num, re->nexthop_active_num); + + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + inet_ntop(p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN); + zlog_debug("%s: %s %s with flags %s%s%s", func, + (nexthop->rparent ? " NH" : "NH"), straddr, + (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE) + ? "ACTIVE " + : ""), + (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) + ? "FIB " + : ""), + (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE) + ? "RECURSIVE" + : "")); + } + zlog_debug("%s: dump complete", func); } /* This is an exported helper to rtm_read() to dump the strange * RE entry found by rib_lookup_ipv4_route() */ -void rib_lookup_and_dump (struct prefix_ipv4 * p, vrf_id_t vrf_id) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - char prefix_buf[INET_ADDRSTRLEN]; - - /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - { - zlog_err ("%s: zebra_vrf_table() returned NULL", __func__); - return; - } - - /* Scan the RIB table for exactly matching RE entry. */ - rn = route_node_lookup (table, (struct prefix *) p); - - /* No route for this prefix. */ - if (! rn) - { - zlog_debug ("%s: lookup failed for %s", __func__, - prefix2str((struct prefix*) p, prefix_buf, sizeof(prefix_buf))); - return; - } - - /* Unlock node. */ - route_unlock_node (rn); - - /* let's go */ - RNODE_FOREACH_RE (rn, re) - { - zlog_debug - ( - "%s: rn %p, re %p: %s, %s", - __func__, - (void *)rn, - (void *)re, - (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED) ? "removed" : "NOT removed"), - (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected") - ); - route_entry_dump (p, NULL, re); - } +void rib_lookup_and_dump(struct prefix_ipv4 *p, vrf_id_t vrf_id) +{ + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + char prefix_buf[INET_ADDRSTRLEN]; + + /* Lookup table. */ + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) { + zlog_err("%s: zebra_vrf_table() returned NULL", __func__); + return; + } + + /* Scan the RIB table for exactly matching RE entry. */ + rn = route_node_lookup(table, (struct prefix *)p); + + /* No route for this prefix. */ + if (!rn) { + zlog_debug("%s: lookup failed for %s", __func__, + prefix2str((struct prefix *)p, prefix_buf, + sizeof(prefix_buf))); + return; + } + + /* Unlock node. */ + route_unlock_node(rn); + + /* let's go */ + RNODE_FOREACH_RE(rn, re) + { + zlog_debug("%s: rn %p, re %p: %s, %s", __func__, (void *)rn, + (void *)re, + (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED) + ? "removed" + : "NOT removed"), + (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) + ? "selected" + : "NOT selected")); + route_entry_dump(p, NULL, re); + } } /* Check if requested address assignment will fail due to another @@ -2228,637 +2138,628 @@ void rib_lookup_and_dump (struct prefix_ipv4 * p, vrf_id_t vrf_id) * actions, if needed: remove such a route from FIB and deSELECT * corresponding RE entry. Then put affected RN into RIBQ head. */ -void rib_lookup_and_pushup (struct prefix_ipv4 * p, vrf_id_t vrf_id) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - unsigned changed = 0; - - if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id))) - { - zlog_err ("%s: zebra_vrf_table() returned NULL", __func__); - return; - } - - /* No matches would be the simplest case. */ - if (NULL == (rn = route_node_lookup (table, (struct prefix *) p))) - return; - - /* Unlock node. */ - route_unlock_node (rn); - - /* Check all RE entries. In case any changes have to be done, requeue - * the RN into RIBQ head. If the routing message about the new connected - * route (generated by the IP address we are going to assign very soon) - * comes before the RIBQ is processed, the new RE entry will join - * RIBQ record already on head. This is necessary for proper revalidation - * of the rest of the RE. - */ - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB) && - ! RIB_SYSTEM_ROUTE (re)) - { - changed = 1; - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[PREFIX_STRLEN]; - zlog_debug ("%u:%s: freeing way for connected prefix", - re->vrf_id, prefix2str(&rn->p, buf, sizeof(buf))); - route_entry_dump (&rn->p, NULL, re); - } - rib_uninstall (rn, re); - } - } - if (changed) - rib_queue_add (rn); +void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id) +{ + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + unsigned changed = 0; + + if (NULL == (table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id))) { + zlog_err("%s: zebra_vrf_table() returned NULL", __func__); + return; + } + + /* No matches would be the simplest case. */ + if (NULL == (rn = route_node_lookup(table, (struct prefix *)p))) + return; + + /* Unlock node. */ + route_unlock_node(rn); + + /* Check all RE entries. In case any changes have to be done, requeue + * the RN into RIBQ head. If the routing message about the new connected + * route (generated by the IP address we are going to assign very soon) + * comes before the RIBQ is processed, the new RE entry will join + * RIBQ record already on head. This is necessary for proper + * revalidation + * of the rest of the RE. + */ + RNODE_FOREACH_RE(rn, re) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB) + && !RIB_SYSTEM_ROUTE(re)) { + changed = 1; + if (IS_ZEBRA_DEBUG_RIB) { + char buf[PREFIX_STRLEN]; + zlog_debug( + "%u:%s: freeing way for connected prefix", + re->vrf_id, + prefix2str(&rn->p, buf, sizeof(buf))); + route_entry_dump(&rn->p, NULL, re); + } + rib_uninstall(rn, re); + } + } + if (changed) + rib_queue_add(rn); } -int -rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct route_entry *re) +int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, struct route_entry *re) { - struct route_table *table; - struct route_node *rn; - struct route_entry *same; - struct nexthop *nexthop; - int ret = 0; - int family; + struct route_table *table; + struct route_node *rn; + struct route_entry *same; + struct nexthop *nexthop; + int ret = 0; + int family; - if (!re) - return 0; + if (!re) + return 0; - if (p->family == AF_INET) - family = AFI_IP; - else - family = AFI_IP6; + if (p->family == AF_INET) + family = AFI_IP; + else + family = AFI_IP6; - assert(!src_p || family == AFI_IP6); + assert(!src_p || family == AFI_IP6); - /* Lookup table. */ - table = zebra_vrf_table_with_table_id (family, safi, re->vrf_id, re->table); - if (! table) - return 0; + /* Lookup table. */ + table = zebra_vrf_table_with_table_id(family, safi, re->vrf_id, + re->table); + if (!table) + return 0; - /* Make it sure prefixlen is applied to the prefix. */ - apply_mask (p); - if (src_p) - apply_mask_ipv6 (src_p); + /* Make it sure prefixlen is applied to the prefix. */ + apply_mask(p); + if (src_p) + apply_mask_ipv6(src_p); - /* Set default distance by route type. */ - if (re->distance == 0) - { - re->distance = route_info[re->type].distance; + /* Set default distance by route type. */ + if (re->distance == 0) { + re->distance = route_info[re->type].distance; - /* iBGP distance is 200. */ - if (re->type == ZEBRA_ROUTE_BGP - && CHECK_FLAG (re->flags, ZEBRA_FLAG_IBGP)) - re->distance = 200; - } + /* iBGP distance is 200. */ + if (re->type == ZEBRA_ROUTE_BGP + && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) + re->distance = 200; + } - /* Lookup route node.*/ - rn = srcdest_rnode_get (table, p, src_p); + /* Lookup route node.*/ + rn = srcdest_rnode_get(table, p, src_p); - /* If same type of route are installed, treat it as a implicit - withdraw. */ - RNODE_FOREACH_RE (rn, same) - { - if (CHECK_FLAG (same->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (same->type == re->type && same->instance == re->instance - && same->table == re->table - && same->type != ZEBRA_ROUTE_CONNECT) - break; - } - - /* If this route is kernel route, set FIB flag to the route. */ - if (re->type == ZEBRA_ROUTE_KERNEL || re->type == ZEBRA_ROUTE_CONNECT) - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - - /* Link new re to node.*/ - if (IS_ZEBRA_DEBUG_RIB) - { - rnode_debug(rn, re->vrf_id, "Inserting route rn %p, re %p (type %d) existing %p", - (void *)rn, (void *)re, re->type, (void *)same); + /* If same type of route are installed, treat it as a implicit + withdraw. */ + RNODE_FOREACH_RE(rn, same) + { + if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED)) + continue; - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - route_entry_dump (p, src_p, re); - } - rib_addnode (rn, re, 1); - ret = 1; + if (same->type == re->type && same->instance == re->instance + && same->table == re->table + && same->type != ZEBRA_ROUTE_CONNECT) + break; + } - /* Free implicit route.*/ - if (same) - { - rib_delnode (rn, same); - ret = -1; - } - - route_unlock_node (rn); - return ret; -} + /* If this route is kernel route, set FIB flag to the route. */ + if (re->type == ZEBRA_ROUTE_KERNEL || re->type == ZEBRA_ROUTE_CONNECT) + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); -void -rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, - int flags, struct prefix *p, struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, u_int32_t table_id) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - struct route_entry *fib = NULL; - struct route_entry *same = NULL; - struct nexthop *nexthop; - char buf2[INET6_ADDRSTRLEN]; - - assert(!src_p || afi == AFI_IP6); - - /* Lookup table. */ - table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id); - if (! table) - return; - - /* Apply mask. */ - apply_mask (p); - if (src_p) - apply_mask_ipv6 (src_p); - - /* Lookup route node. */ - rn = srcdest_rnode_lookup (table, p, src_p); - if (! rn) - { - char dst_buf[PREFIX_STRLEN], src_buf[PREFIX_STRLEN]; - - prefix2str(p, dst_buf, sizeof(dst_buf)); - if (src_p && src_p->prefixlen) - prefix2str(src_p, src_buf, sizeof(src_buf)); - else - src_buf[0] = '\0'; - - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%u:%s%s%s doesn't exist in rib", - vrf_id, dst_buf, - (src_buf[0] != '\0') ? " from " : "", - src_buf); - return; - } + /* Link new re to node.*/ + if (IS_ZEBRA_DEBUG_RIB) { + rnode_debug( + rn, re->vrf_id, + "Inserting route rn %p, re %p (type %d) existing %p", + (void *)rn, (void *)re, re->type, (void *)same); - /* Lookup same type route. */ - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB)) - fib = re; - - if (re->type != type) - continue; - if (re->instance != instance) - continue; - if (re->type == ZEBRA_ROUTE_CONNECT && (nexthop = re->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX) - { - if (nexthop->ifindex != ifindex) - continue; - if (re->refcnt) - { - re->refcnt--; - route_unlock_node (rn); - route_unlock_node (rn); - return; - } - same = re; - break; - } - /* Make sure that the route found has the same gateway. */ - else - { - if (gate == NULL) - { - same = re; - break; - } - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) || - IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate)) - { - same = re; - break; - } - if (same) - break; - } - } - /* If same type of route can't be found and this message is from - kernel. */ - if (! same) - { - if (fib && type == ZEBRA_ROUTE_KERNEL && - CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)) - { - if (IS_ZEBRA_DEBUG_RIB) - { - rnode_debug (rn, vrf_id, "rn %p, re %p (type %d) was deleted from kernel, adding", - rn, fib, fib->type); - } - if (allow_delete) - { - /* Unset flags. */ - for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next) - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - - UNSET_FLAG (fib->status, ROUTE_ENTRY_SELECTED_FIB); - } - else - { - /* This means someone else, other than Zebra, has deleted - * a Zebra router from the kernel. We will add it back */ - rib_install_kernel(rn, fib, NULL); - } - } - else - { - if (IS_ZEBRA_DEBUG_RIB) - { - if (gate) - rnode_debug(rn, vrf_id, "via %s ifindex %d type %d " - "doesn't exist in rib", - inet_ntop (family2afi(afi), gate, buf2, INET_ADDRSTRLEN), /* FIXME */ - ifindex, - type); - else - rnode_debug (rn, vrf_id, "ifindex %d type %d doesn't exist in rib", - ifindex, - type); - } - route_unlock_node (rn); - return; + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + route_entry_dump(p, src_p, re); } - } - - if (same) - rib_delnode (rn, same); - - route_unlock_node (rn); - return; -} + rib_addnode(rn, re, 1); + ret = 1; + /* Free implicit route.*/ + if (same) { + rib_delnode(rn, same); + ret = -1; + } + route_unlock_node(rn); + return ret; +} + +void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, + u_short instance, int flags, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, + ifindex_t ifindex, u_int32_t table_id) +{ + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + struct route_entry *fib = NULL; + struct route_entry *same = NULL; + struct nexthop *nexthop; + char buf2[INET6_ADDRSTRLEN]; + + assert(!src_p || afi == AFI_IP6); + + /* Lookup table. */ + table = zebra_vrf_table_with_table_id(afi, safi, vrf_id, table_id); + if (!table) + return; + + /* Apply mask. */ + apply_mask(p); + if (src_p) + apply_mask_ipv6(src_p); + + /* Lookup route node. */ + rn = srcdest_rnode_lookup(table, p, src_p); + if (!rn) { + char dst_buf[PREFIX_STRLEN], src_buf[PREFIX_STRLEN]; + + prefix2str(p, dst_buf, sizeof(dst_buf)); + if (src_p && src_p->prefixlen) + prefix2str(src_p, src_buf, sizeof(src_buf)); + else + src_buf[0] = '\0'; + + if (IS_ZEBRA_DEBUG_RIB) + zlog_debug("%u:%s%s%s doesn't exist in rib", vrf_id, + dst_buf, + (src_buf[0] != '\0') ? " from " : "", + src_buf); + return; + } -int -rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, - u_short instance, int flags, struct prefix *p, - struct prefix_ipv6 *src_p, union g_addr *gate, - union g_addr *src, ifindex_t ifindex, - u_int32_t table_id, u_int32_t metric, u_int32_t mtu, - u_char distance) -{ - struct route_entry *re; - struct route_entry *same = NULL; - struct route_table *table; - struct route_node *rn; - struct nexthop *nexthop; + /* Lookup same type route. */ + RNODE_FOREACH_RE(rn, re) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) + fib = re; + + if (re->type != type) + continue; + if (re->instance != instance) + continue; + if (re->type == ZEBRA_ROUTE_CONNECT && (nexthop = re->nexthop) + && nexthop->type == NEXTHOP_TYPE_IFINDEX) { + if (nexthop->ifindex != ifindex) + continue; + if (re->refcnt) { + re->refcnt--; + route_unlock_node(rn); + route_unlock_node(rn); + return; + } + same = re; + break; + } + /* Make sure that the route found has the same gateway. */ + else { + if (gate == NULL) { + same = re; + break; + } + for (ALL_NEXTHOPS(re->nexthop, nexthop)) + if (IPV4_ADDR_SAME(&nexthop->gate.ipv4, gate) + || IPV6_ADDR_SAME(&nexthop->gate.ipv6, + gate)) { + same = re; + break; + } + if (same) + break; + } + } + /* If same type of route can't be found and this message is from + kernel. */ + if (!same) { + if (fib && type == ZEBRA_ROUTE_KERNEL + && CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)) { + if (IS_ZEBRA_DEBUG_RIB) { + rnode_debug( + rn, vrf_id, + "rn %p, re %p (type %d) was deleted from kernel, adding", + rn, fib, fib->type); + } + if (allow_delete) { + /* Unset flags. */ + for (nexthop = fib->nexthop; nexthop; + nexthop = nexthop->next) + UNSET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + + UNSET_FLAG(fib->status, + ROUTE_ENTRY_SELECTED_FIB); + } else { + /* This means someone else, other than Zebra, + * has deleted + * a Zebra router from the kernel. We will add + * it back */ + rib_install_kernel(rn, fib, NULL); + } + } else { + if (IS_ZEBRA_DEBUG_RIB) { + if (gate) + rnode_debug( + rn, vrf_id, + "via %s ifindex %d type %d " + "doesn't exist in rib", + inet_ntop( + family2afi(afi), gate, + buf2, + INET_ADDRSTRLEN), /* FIXME + */ + ifindex, type); + else + rnode_debug( + rn, vrf_id, + "ifindex %d type %d doesn't exist in rib", + ifindex, type); + } + route_unlock_node(rn); + return; + } + } - assert(!src_p || afi == AFI_IP6); + if (same) + rib_delnode(rn, same); - /* Lookup table. */ - table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id); - if (! table) - return 0; + route_unlock_node(rn); + return; +} - /* Make sure mask is applied. */ - apply_mask (p); - if (src_p) - apply_mask_ipv6 (src_p); - /* Set default distance by route type. */ - if (distance == 0) - { - if ((unsigned)type >= array_size(route_info)) - distance = 150; - else - distance = route_info[type].distance; - - /* iBGP distance is 200. */ - if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP)) - distance = 200; - } +int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, + int flags, struct prefix *p, struct prefix_ipv6 *src_p, + union g_addr *gate, union g_addr *src, ifindex_t ifindex, + u_int32_t table_id, u_int32_t metric, u_int32_t mtu, + u_char distance) +{ + struct route_entry *re; + struct route_entry *same = NULL; + struct route_table *table; + struct route_node *rn; + struct nexthop *nexthop; + + assert(!src_p || afi == AFI_IP6); + + /* Lookup table. */ + table = zebra_vrf_table_with_table_id(afi, safi, vrf_id, table_id); + if (!table) + return 0; + + /* Make sure mask is applied. */ + apply_mask(p); + if (src_p) + apply_mask_ipv6(src_p); + + /* Set default distance by route type. */ + if (distance == 0) { + if ((unsigned)type >= array_size(route_info)) + distance = 150; + else + distance = route_info[type].distance; + + /* iBGP distance is 200. */ + if (type == ZEBRA_ROUTE_BGP + && CHECK_FLAG(flags, ZEBRA_FLAG_IBGP)) + distance = 200; + } - /* Lookup route node.*/ - rn = srcdest_rnode_get (table, p, src_p); + /* Lookup route node.*/ + rn = srcdest_rnode_get(table, p, src_p); - /* If same type of route are installed, treat it as a implicit - withdraw. */ - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (re->type != type) - continue; - if (re->instance != instance) - continue; - if (re->type != ZEBRA_ROUTE_CONNECT) - { - same = re; - break; - } - /* Duplicate connected route comes in. */ - else if ((nexthop = re->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX && - nexthop->ifindex == ifindex && - !CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) + /* If same type of route are installed, treat it as a implicit + withdraw. */ + RNODE_FOREACH_RE(rn, re) { - re->refcnt++; - return 0 ; + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + if (re->type != type) + continue; + if (re->instance != instance) + continue; + if (re->type != ZEBRA_ROUTE_CONNECT) { + same = re; + break; + } + /* Duplicate connected route comes in. */ + else if ((nexthop = re->nexthop) + && nexthop->type == NEXTHOP_TYPE_IFINDEX + && nexthop->ifindex == ifindex + && !CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) { + re->refcnt++; + return 0; + } } - } - /* Allocate new re structure. */ - re = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - - re->type = type; - re->instance = instance; - re->distance = distance; - re->flags = flags; - re->metric = metric; - re->mtu = mtu; - re->table = table_id; - re->vrf_id = vrf_id; - re->nexthop_num = 0; - re->uptime = time (NULL); - - /* Nexthop settings. */ - if (gate) - { - if (afi == AFI_IP6) - { - if (ifindex) - route_entry_nexthop_ipv6_ifindex_add (re, &gate->ipv6, ifindex); - else - route_entry_nexthop_ipv6_add (re, &gate->ipv6); - } - else - { - if (ifindex) - route_entry_nexthop_ipv4_ifindex_add (re, &gate->ipv4, &src->ipv4, ifindex); - else - route_entry_nexthop_ipv4_add (re, &gate->ipv4, &src->ipv4); + /* Allocate new re structure. */ + re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + + re->type = type; + re->instance = instance; + re->distance = distance; + re->flags = flags; + re->metric = metric; + re->mtu = mtu; + re->table = table_id; + re->vrf_id = vrf_id; + re->nexthop_num = 0; + re->uptime = time(NULL); + + /* Nexthop settings. */ + if (gate) { + if (afi == AFI_IP6) { + if (ifindex) + route_entry_nexthop_ipv6_ifindex_add( + re, &gate->ipv6, ifindex); + else + route_entry_nexthop_ipv6_add(re, &gate->ipv6); + } else { + if (ifindex) + route_entry_nexthop_ipv4_ifindex_add( + re, &gate->ipv4, &src->ipv4, ifindex); + else + route_entry_nexthop_ipv4_add(re, &gate->ipv4, + &src->ipv4); + } + } else + route_entry_nexthop_ifindex_add(re, ifindex); + + /* If this route is kernel route, set FIB flag to the route. */ + if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT) + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + + /* Link new rib to node.*/ + if (IS_ZEBRA_DEBUG_RIB) { + rnode_debug( + rn, vrf_id, + "Inserting route rn %p, re %p (type %d) existing %p", + (void *)rn, (void *)re, re->type, (void *)same); + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + route_entry_dump(p, src_p, re); } - } - else - route_entry_nexthop_ifindex_add (re, ifindex); - - /* If this route is kernel route, set FIB flag to the route. */ - if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT) - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); + rib_addnode(rn, re, 1); - /* Link new rib to node.*/ - if (IS_ZEBRA_DEBUG_RIB) - { - rnode_debug (rn, vrf_id, "Inserting route rn %p, re %p (type %d) existing %p", - (void *)rn, (void *)re, re->type, (void *)same); - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - route_entry_dump (p, src_p, re); - } - rib_addnode (rn, re, 1); + /* Free implicit route.*/ + if (same) + rib_delnode(rn, same); - /* Free implicit route.*/ - if (same) - rib_delnode (rn, same); - - route_unlock_node (rn); - return 0; + route_unlock_node(rn); + return 0; } /* Schedule routes of a particular table (address-family) based on event. */ -static void -rib_update_table (struct route_table *table, rib_update_event_t event) -{ - struct route_node *rn; - struct route_entry *re, *next; - - /* Walk all routes and queue for processing, if appropriate for - * the trigger event. - */ - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - { - switch (event) - { - case RIB_UPDATE_IF_CHANGE: - /* Examine all routes that won't get processed by the protocol or - * triggered by nexthop evaluation (NHT). This would be system, - * kernel and certain static routes. Note that NHT will get - * triggered upon an interface event as connected routes always - * get queued for processing. - */ - RNODE_FOREACH_RE_SAFE (rn, re, next) - { - if (re->type == ZEBRA_ROUTE_OSPF || - re->type == ZEBRA_ROUTE_OSPF6 || - re->type == ZEBRA_ROUTE_BGP) - continue; /* protocol will handle. */ - else if (re->type == ZEBRA_ROUTE_STATIC) - { - struct nexthop *nh; - for (nh = re->nexthop; nh; nh = nh->next) - if (!(nh->type == NEXTHOP_TYPE_IPV4 || - nh->type == NEXTHOP_TYPE_IPV6)) - break; - - /* If we only have nexthops to a gateway, NHT will - * take care. - */ - if (nh) - rib_queue_add (rn); - } - else - rib_queue_add (rn); - } - break; - - case RIB_UPDATE_RMAP_CHANGE: - case RIB_UPDATE_OTHER: - /* Right now, examine all routes. Can restrict to a protocol in - * some cases (TODO). - */ - if (rnode_to_ribs (rn)) - rib_queue_add (rn); - break; - - default: - break; - } - } +static void rib_update_table(struct route_table *table, + rib_update_event_t event) +{ + struct route_node *rn; + struct route_entry *re, *next; + + /* Walk all routes and queue for processing, if appropriate for + * the trigger event. + */ + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) { + switch (event) { + case RIB_UPDATE_IF_CHANGE: + /* Examine all routes that won't get processed by the + * protocol or + * triggered by nexthop evaluation (NHT). This would be + * system, + * kernel and certain static routes. Note that NHT will + * get + * triggered upon an interface event as connected routes + * always + * get queued for processing. + */ + RNODE_FOREACH_RE_SAFE(rn, re, next) + { + if (re->type == ZEBRA_ROUTE_OSPF + || re->type == ZEBRA_ROUTE_OSPF6 + || re->type == ZEBRA_ROUTE_BGP) + continue; /* protocol will handle. */ + else if (re->type == ZEBRA_ROUTE_STATIC) { + struct nexthop *nh; + for (nh = re->nexthop; nh; + nh = nh->next) + if (!(nh->type + == NEXTHOP_TYPE_IPV4 + || nh->type + == NEXTHOP_TYPE_IPV6)) + break; + + /* If we only have nexthops to a + * gateway, NHT will + * take care. + */ + if (nh) + rib_queue_add(rn); + } else + rib_queue_add(rn); + } + break; + + case RIB_UPDATE_RMAP_CHANGE: + case RIB_UPDATE_OTHER: + /* Right now, examine all routes. Can restrict to a + * protocol in + * some cases (TODO). + */ + if (rnode_to_ribs(rn)) + rib_queue_add(rn); + break; + + default: + break; + } + } } /* RIB update function. */ -void -rib_update (vrf_id_t vrf_id, rib_update_event_t event) +void rib_update(vrf_id_t vrf_id, rib_update_event_t event) { - struct route_table *table; + struct route_table *table; - /* Process routes of interested address-families. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (table) - rib_update_table (table, event); + /* Process routes of interested address-families. */ + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (table) + rib_update_table(table, event); - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); - if (table) - rib_update_table (table, event); + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); + if (table) + rib_update_table(table, event); } /* Remove all routes which comes from non main table. */ -static void -rib_weed_table (struct route_table *table) +static void rib_weed_table(struct route_table *table) { - struct route_node *rn; - struct route_entry *re; - struct route_entry *next; + struct route_node *rn; + struct route_entry *re; + struct route_entry *next; - if (table) - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE_SAFE (rn, re, next) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; + if (table) + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE_SAFE(rn, re, next) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; - if (re->table != zebrad.rtm_table_default && - re->table != RT_TABLE_MAIN) - rib_delnode (rn, re); - } + if (re->table != zebrad.rtm_table_default + && re->table != RT_TABLE_MAIN) + rib_delnode(rn, re); + } } /* Delete all routes from non main table. */ -void -rib_weed_tables (void) +void rib_weed_tables(void) { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - if ((zvrf = vrf->info) != NULL) - { - rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]); - rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); - } + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + if ((zvrf = vrf->info) != NULL) { + rib_weed_table(zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_weed_table(zvrf->table[AFI_IP6][SAFI_UNICAST]); + } } /* Delete self installed routes after zebra is relaunched. */ -static void -rib_sweep_table (struct route_table *table) -{ - struct route_node *rn; - struct route_entry *re; - struct route_entry *next; - int ret = 0; - - if (table) - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE_SAFE (rn, re, next) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (re->type == ZEBRA_ROUTE_KERNEL && - CHECK_FLAG (re->flags, ZEBRA_FLAG_SELFROUTE)) - { - ret = rib_uninstall_kernel (rn, re); - if (! ret) - rib_delnode (rn, re); - } - } +static void rib_sweep_table(struct route_table *table) +{ + struct route_node *rn; + struct route_entry *re; + struct route_entry *next; + int ret = 0; + + if (table) + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE_SAFE(rn, re, next) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + if (re->type == ZEBRA_ROUTE_KERNEL + && CHECK_FLAG(re->flags, + ZEBRA_FLAG_SELFROUTE)) { + ret = rib_uninstall_kernel(rn, re); + if (!ret) + rib_delnode(rn, re); + } + } } /* Sweep all RIB tables. */ -void -rib_sweep_route (void) +void rib_sweep_route(void) { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - if ((zvrf = vrf->info) != NULL) - { - rib_sweep_table (zvrf->table[AFI_IP][SAFI_UNICAST]); - rib_sweep_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); - } + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + if ((zvrf = vrf->info) != NULL) { + rib_sweep_table(zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_sweep_table(zvrf->table[AFI_IP6][SAFI_UNICAST]); + } } /* Remove specific by protocol routes from 'table'. */ -static unsigned long -rib_score_proto_table (u_char proto, u_short instance, struct route_table *table) -{ - struct route_node *rn; - struct route_entry *re; - struct route_entry *next; - unsigned long n = 0; - - if (table) - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE_SAFE (rn, re, next) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - if (re->type == proto && re->instance == instance) - { - rib_delnode (rn, re); - n++; - } - } - return n; +static unsigned long rib_score_proto_table(u_char proto, u_short instance, + struct route_table *table) +{ + struct route_node *rn; + struct route_entry *re; + struct route_entry *next; + unsigned long n = 0; + + if (table) + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE_SAFE(rn, re, next) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + if (re->type == proto + && re->instance == instance) { + rib_delnode(rn, re); + n++; + } + } + return n; } /* Remove specific by protocol routes. */ -unsigned long -rib_score_proto (u_char proto, u_short instance) +unsigned long rib_score_proto(u_char proto, u_short instance) { - struct vrf *vrf; - struct zebra_vrf *zvrf; - unsigned long cnt = 0; + struct vrf *vrf; + struct zebra_vrf *zvrf; + unsigned long cnt = 0; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - if ((zvrf = vrf->info) != NULL) - cnt += rib_score_proto_table (proto, instance, zvrf->table[AFI_IP][SAFI_UNICAST]) - +rib_score_proto_table (proto, instance, zvrf->table[AFI_IP6][SAFI_UNICAST]); + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + if ((zvrf = vrf->info) != NULL) + cnt += rib_score_proto_table(proto, instance, + zvrf->table[AFI_IP][SAFI_UNICAST]) + + rib_score_proto_table( + proto, instance, + zvrf->table[AFI_IP6][SAFI_UNICAST]); - return cnt; + return cnt; } /* Close RIB and clean up kernel routes. */ -void -rib_close_table (struct route_table *table) +void rib_close_table(struct route_table *table) { - struct route_node *rn; - rib_table_info_t *info = table->info; - struct route_entry *re; + struct route_node *rn; + rib_table_info_t *info = table->info; + struct route_entry *re; - if (table) - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE (rn, re) - { - if (!CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB)) - continue; + if (table) + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE(rn, re) + { + if (!CHECK_FLAG(re->status, + ROUTE_ENTRY_SELECTED_FIB)) + continue; - if (info->safi == SAFI_UNICAST) - hook_call(rib_update, rn, NULL); + if (info->safi == SAFI_UNICAST) + hook_call(rib_update, rn, NULL); - if (! RIB_SYSTEM_ROUTE (re)) - rib_uninstall_kernel (rn, re); - } + if (!RIB_SYSTEM_ROUTE(re)) + rib_uninstall_kernel(rn, re); + } } /* Routing information base initialize. */ -void -rib_init (void) +void rib_init(void) { - rib_queue_init (&zebrad); + rib_queue_init(&zebrad); } /* @@ -2868,22 +2769,20 @@ rib_init (void) * * Returns TRUE if a vrf id was found, FALSE otherwise. */ -static inline int -vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p) +static inline int vrf_id_get_next(vrf_id_t vrf_id, vrf_id_t *next_id_p) { - struct vrf *vrf; + struct vrf *vrf; - vrf = vrf_lookup_by_id (vrf_id); - if (vrf) - { - vrf = RB_NEXT (vrf_id_head, vrf); - if (vrf) { - *next_id_p = vrf->vrf_id; - return 1; - } - } + vrf = vrf_lookup_by_id(vrf_id); + if (vrf) { + vrf = RB_NEXT(vrf_id_head, vrf); + if (vrf) { + *next_id_p = vrf->vrf_id; + return 1; + } + } - return 0; + return 0; } /* @@ -2891,81 +2790,76 @@ vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p) * * Returns the next table in the iteration. */ -struct route_table * -rib_tables_iter_next (rib_tables_iter_t *iter) -{ - struct route_table *table; - - /* - * Array that helps us go over all AFI/SAFI combinations via one - * index. - */ - static struct { - afi_t afi; - safi_t safi; - } afi_safis[] = { - { AFI_IP, SAFI_UNICAST }, - { AFI_IP, SAFI_MULTICAST }, - { AFI_IP, SAFI_LABELED_UNICAST }, - { AFI_IP6, SAFI_UNICAST }, - { AFI_IP6, SAFI_MULTICAST }, - { AFI_IP6, SAFI_LABELED_UNICAST }, - }; - - table = NULL; - - switch (iter->state) - { - - case RIB_TABLES_ITER_S_INIT: - iter->vrf_id = VRF_DEFAULT; - iter->afi_safi_ix = -1; - - /* Fall through */ - - case RIB_TABLES_ITER_S_ITERATING: - iter->afi_safi_ix++; - while (1) - { +struct route_table *rib_tables_iter_next(rib_tables_iter_t *iter) +{ + struct route_table *table; + + /* + * Array that helps us go over all AFI/SAFI combinations via one + * index. + */ + static struct { + afi_t afi; + safi_t safi; + } afi_safis[] = { + {AFI_IP, SAFI_UNICAST}, {AFI_IP, SAFI_MULTICAST}, + {AFI_IP, SAFI_LABELED_UNICAST}, {AFI_IP6, SAFI_UNICAST}, + {AFI_IP6, SAFI_MULTICAST}, {AFI_IP6, SAFI_LABELED_UNICAST}, + }; + + table = NULL; + + switch (iter->state) { + + case RIB_TABLES_ITER_S_INIT: + iter->vrf_id = VRF_DEFAULT; + iter->afi_safi_ix = -1; + + /* Fall through */ + + case RIB_TABLES_ITER_S_ITERATING: + iter->afi_safi_ix++; + while (1) { + + while (iter->afi_safi_ix + < (int)ZEBRA_NUM_OF(afi_safis)) { + table = zebra_vrf_table( + afi_safis[iter->afi_safi_ix].afi, + afi_safis[iter->afi_safi_ix].safi, + iter->vrf_id); + if (table) + break; + + iter->afi_safi_ix++; + } + + /* + * Found another table in this vrf. + */ + if (table) + break; + + /* + * Done with all tables in the current vrf, go to the + * next + * one. + */ + if (!vrf_id_get_next(iter->vrf_id, &iter->vrf_id)) + break; + + iter->afi_safi_ix = 0; + } - while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis)) - { - table = zebra_vrf_table (afi_safis[iter->afi_safi_ix].afi, - afi_safis[iter->afi_safi_ix].safi, - iter->vrf_id); - if (table) break; - iter->afi_safi_ix++; - } - - /* - * Found another table in this vrf. - */ - if (table) - break; - - /* - * Done with all tables in the current vrf, go to the next - * one. - */ - if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id)) - break; - - iter->afi_safi_ix = 0; + case RIB_TABLES_ITER_S_DONE: + return NULL; } - break; - - case RIB_TABLES_ITER_S_DONE: - return NULL; - } - - if (table) - iter->state = RIB_TABLES_ITER_S_ITERATING; - else - iter->state = RIB_TABLES_ITER_S_DONE; + if (table) + iter->state = RIB_TABLES_ITER_S_ITERATING; + else + iter->state = RIB_TABLES_ITER_S_DONE; - return table; + return table; } - diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index c82712b9c..8a326c27f 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -48,22 +48,23 @@ #include "zebra/interface.h" #include "zebra/zebra_memory.h" -static void free_state(vrf_id_t vrf_id, struct route_entry *re, struct route_node *rn); +static void free_state(vrf_id_t vrf_id, struct route_entry *re, + struct route_node *rn); static void copy_state(struct rnh *rnh, struct route_entry *re, struct route_node *rn); -#define lookup_rnh_table(v, f) \ -({ \ - struct zebra_vrf *zvrf; \ - struct route_table *t = NULL; \ - zvrf = zebra_vrf_lookup_by_id(v); \ - if (zvrf) \ - t = zvrf->rnh_table[family2afi(f)]; \ - t; \ -}) +#define lookup_rnh_table(v, f) \ + ({ \ + struct zebra_vrf *zvrf; \ + struct route_table *t = NULL; \ + zvrf = zebra_vrf_lookup_by_id(v); \ + if (zvrf) \ + t = zvrf->rnh_table[family2afi(f)]; \ + t; \ + }) static int compare_state(struct route_entry *r1, struct route_entry *r2); static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, - vrf_id_t vrf_id); + vrf_id_t vrf_id); static void print_rnh(struct route_node *rn, struct vty *vty); int zebra_rnh_ip_default_route = 0; @@ -72,541 +73,526 @@ int zebra_rnh_ipv6_default_route = 0; static inline struct route_table *get_rnh_table(vrf_id_t vrfid, int family, rnh_type_t type) { - struct zebra_vrf *zvrf; - struct route_table *t = NULL; - - zvrf = zebra_vrf_lookup_by_id(vrfid); - if (zvrf) - switch (type) - { - case RNH_NEXTHOP_TYPE: - t = zvrf->rnh_table[family2afi(family)]; - break; - case RNH_IMPORT_CHECK_TYPE: - t = zvrf->import_check_table[family2afi(family)]; - break; - } - - return t; + struct zebra_vrf *zvrf; + struct route_table *t = NULL; + + zvrf = zebra_vrf_lookup_by_id(vrfid); + if (zvrf) + switch (type) { + case RNH_NEXTHOP_TYPE: + t = zvrf->rnh_table[family2afi(family)]; + break; + case RNH_IMPORT_CHECK_TYPE: + t = zvrf->import_check_table[family2afi(family)]; + break; + } + + return t; } -char *rnh_str (struct rnh *rnh, char *buf, int size) +char *rnh_str(struct rnh *rnh, char *buf, int size) { - prefix2str(&(rnh->node->p), buf, size); - return buf; + prefix2str(&(rnh->node->p), buf, size); + return buf; } -struct rnh * -zebra_add_rnh (struct prefix *p, vrf_id_t vrfid, rnh_type_t type) +struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type) { - struct route_table *table; - struct route_node *rn; - struct rnh *rnh = NULL; - char buf[PREFIX2STR_BUFFER]; - - if (IS_ZEBRA_DEBUG_NHT) - { - prefix2str(p, buf, sizeof (buf)); - zlog_debug("%u: Add RNH %s type %d", vrfid, buf, type); - } - table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); - if (!table) - { - prefix2str(p, buf, sizeof (buf)); - zlog_warn("%u: Add RNH %s type %d - table not found", - vrfid, buf, type); - return NULL; - } - - /* Make it sure prefixlen is applied to the prefix. */ - apply_mask (p); - - /* Lookup (or add) route node.*/ - rn = route_node_get (table, p); - - if (!rn->info) - { - rnh = XCALLOC(MTYPE_RNH, sizeof(struct rnh)); - rnh->client_list = list_new(); - rnh->vrf_id = vrfid; - rnh->zebra_static_route_list = list_new(); - route_lock_node (rn); - rn->info = rnh; - rnh->node = rn; - } - - route_unlock_node (rn); - return (rn->info); + struct route_table *table; + struct route_node *rn; + struct rnh *rnh = NULL; + char buf[PREFIX2STR_BUFFER]; + + if (IS_ZEBRA_DEBUG_NHT) { + prefix2str(p, buf, sizeof(buf)); + zlog_debug("%u: Add RNH %s type %d", vrfid, buf, type); + } + table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); + if (!table) { + prefix2str(p, buf, sizeof(buf)); + zlog_warn("%u: Add RNH %s type %d - table not found", vrfid, + buf, type); + return NULL; + } + + /* Make it sure prefixlen is applied to the prefix. */ + apply_mask(p); + + /* Lookup (or add) route node.*/ + rn = route_node_get(table, p); + + if (!rn->info) { + rnh = XCALLOC(MTYPE_RNH, sizeof(struct rnh)); + rnh->client_list = list_new(); + rnh->vrf_id = vrfid; + rnh->zebra_static_route_list = list_new(); + route_lock_node(rn); + rn->info = rnh; + rnh->node = rn; + } + + route_unlock_node(rn); + return (rn->info); } -struct rnh * -zebra_lookup_rnh (struct prefix *p, vrf_id_t vrfid, rnh_type_t type) +struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type) { - struct route_table *table; - struct route_node *rn; + struct route_table *table; + struct route_node *rn; - table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); - if (!table) - return NULL; + table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); + if (!table) + return NULL; - /* Make it sure prefixlen is applied to the prefix. */ - apply_mask (p); + /* Make it sure prefixlen is applied to the prefix. */ + apply_mask(p); - /* Lookup route node.*/ - rn = route_node_lookup (table, p); - if (!rn) - return NULL; + /* Lookup route node.*/ + rn = route_node_lookup(table, p); + if (!rn) + return NULL; - route_unlock_node (rn); - return (rn->info); + route_unlock_node(rn); + return (rn->info); } -void -zebra_free_rnh (struct rnh *rnh) +void zebra_free_rnh(struct rnh *rnh) { - rnh->flags |= ZEBRA_NHT_DELETED; - list_free (rnh->client_list); - list_free (rnh->zebra_static_route_list); - free_state (rnh->vrf_id, rnh->state, rnh->node); - XFREE (MTYPE_RNH, rnh); + rnh->flags |= ZEBRA_NHT_DELETED; + list_free(rnh->client_list); + list_free(rnh->zebra_static_route_list); + free_state(rnh->vrf_id, rnh->state, rnh->node); + XFREE(MTYPE_RNH, rnh); } -void -zebra_delete_rnh (struct rnh *rnh, rnh_type_t type) +void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type) { - struct route_node *rn; + struct route_node *rn; - if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED) || !(rn = rnh->node)) - return; + if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED) || !(rn = rnh->node)) + return; - if (IS_ZEBRA_DEBUG_NHT) - { - char buf[PREFIX2STR_BUFFER]; - zlog_debug("%u: Del RNH %s type %d", - rnh->vrf_id, rnh_str(rnh, buf, sizeof (buf)), type); - } + if (IS_ZEBRA_DEBUG_NHT) { + char buf[PREFIX2STR_BUFFER]; + zlog_debug("%u: Del RNH %s type %d", rnh->vrf_id, + rnh_str(rnh, buf, sizeof(buf)), type); + } - zebra_free_rnh (rnh); - rn->info = NULL; - route_unlock_node (rn); + zebra_free_rnh(rnh); + rn->info = NULL; + route_unlock_node(rn); } -void -zebra_add_rnh_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, - vrf_id_t vrf_id) +void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, + rnh_type_t type, vrf_id_t vrf_id) { - if (IS_ZEBRA_DEBUG_NHT) - { - char buf[PREFIX2STR_BUFFER]; - zlog_debug("%u: Client %s registers for RNH %s type %d", - vrf_id, zebra_route_string(client->proto), - rnh_str(rnh, buf, sizeof (buf)), type); - } - if (!listnode_lookup(rnh->client_list, client)) - { - listnode_add(rnh->client_list, client); - send_client(rnh, client, type, vrf_id); // Pending: check if its needed - } + if (IS_ZEBRA_DEBUG_NHT) { + char buf[PREFIX2STR_BUFFER]; + zlog_debug("%u: Client %s registers for RNH %s type %d", vrf_id, + zebra_route_string(client->proto), + rnh_str(rnh, buf, sizeof(buf)), type); + } + if (!listnode_lookup(rnh->client_list, client)) { + listnode_add(rnh->client_list, client); + send_client(rnh, client, type, + vrf_id); // Pending: check if its needed + } } -void -zebra_remove_rnh_client (struct rnh *rnh, struct zserv *client, rnh_type_t type) +void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, + rnh_type_t type) { - if (IS_ZEBRA_DEBUG_NHT) - { - char buf[PREFIX2STR_BUFFER]; - zlog_debug("Client %s unregisters for RNH %s type %d", - zebra_route_string(client->proto), - rnh_str(rnh, buf, sizeof (buf)), type); - } - listnode_delete(rnh->client_list, client); - if (list_isempty(rnh->client_list) && - list_isempty(rnh->zebra_static_route_list)) - zebra_delete_rnh(rnh, type); + if (IS_ZEBRA_DEBUG_NHT) { + char buf[PREFIX2STR_BUFFER]; + zlog_debug("Client %s unregisters for RNH %s type %d", + zebra_route_string(client->proto), + rnh_str(rnh, buf, sizeof(buf)), type); + } + listnode_delete(rnh->client_list, client); + if (list_isempty(rnh->client_list) + && list_isempty(rnh->zebra_static_route_list)) + zebra_delete_rnh(rnh, type); } -void -zebra_register_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh, - struct route_node *static_rn) +void zebra_register_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh, + struct route_node *static_rn) { - struct rnh *rnh; + struct rnh *rnh; - rnh = zebra_add_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE); - if (rnh && !listnode_lookup(rnh->zebra_static_route_list, static_rn)) - { - listnode_add(rnh->zebra_static_route_list, static_rn); - } + rnh = zebra_add_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE); + if (rnh && !listnode_lookup(rnh->zebra_static_route_list, static_rn)) { + listnode_add(rnh->zebra_static_route_list, static_rn); + } } -void -zebra_deregister_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh, - struct route_node *static_rn) +void zebra_deregister_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh, + struct route_node *static_rn) { - struct rnh *rnh; + struct rnh *rnh; - rnh = zebra_lookup_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE); - if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED)) - return; + rnh = zebra_lookup_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE); + if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED)) + return; - listnode_delete(rnh->zebra_static_route_list, static_rn); + listnode_delete(rnh->zebra_static_route_list, static_rn); - if (list_isempty(rnh->client_list) && - list_isempty(rnh->zebra_static_route_list)) - zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE); + if (list_isempty(rnh->client_list) + && list_isempty(rnh->zebra_static_route_list)) + zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE); } -void -zebra_deregister_rnh_static_nexthops (vrf_id_t vrf_id, struct nexthop *nexthop, - struct route_node *rn) +void zebra_deregister_rnh_static_nexthops(vrf_id_t vrf_id, + struct nexthop *nexthop, + struct route_node *rn) { - struct nexthop *nh; - struct prefix nh_p; - - for (nh = nexthop; nh ; nh = nh->next) - { - switch (nh->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = nh->gate.ipv4; - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = nh->gate.ipv6; - break; - /* - * Not sure what really to do here, we are not - * supposed to have either of these for NHT - * and the code has no way to know what prefix - * to use. So I'm going to just continue - * for the moment, which is preferable to - * what is currently happening which is a - * CRASH and BURN. - * Some simple testing shows that we - * are not leaving slag around for these - * skipped static routes. Since - * they don't appear to be installed - */ - case NEXTHOP_TYPE_IFINDEX: - case NEXTHOP_TYPE_BLACKHOLE: - continue; - break; - } - zebra_deregister_rnh_static_nh(vrf_id, &nh_p, rn); - } + struct nexthop *nh; + struct prefix nh_p; + + for (nh = nexthop; nh; nh = nh->next) { + switch (nh->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = nh->gate.ipv4; + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = nh->gate.ipv6; + break; + /* + * Not sure what really to do here, we are not + * supposed to have either of these for NHT + * and the code has no way to know what prefix + * to use. So I'm going to just continue + * for the moment, which is preferable to + * what is currently happening which is a + * CRASH and BURN. + * Some simple testing shows that we + * are not leaving slag around for these + * skipped static routes. Since + * they don't appear to be installed + */ + case NEXTHOP_TYPE_IFINDEX: + case NEXTHOP_TYPE_BLACKHOLE: + continue; + break; + } + zebra_deregister_rnh_static_nh(vrf_id, &nh_p, rn); + } } /* Apply the NHT route-map for a client to the route (and nexthops) * resolving a NH. */ -static int -zebra_rnh_apply_nht_rmap(int family, struct route_node *prn, - struct route_entry *re, int proto) +static int zebra_rnh_apply_nht_rmap(int family, struct route_node *prn, + struct route_entry *re, int proto) { - int at_least_one = 0; - int rmap_family; /* Route map has diff AF family enum */ - struct nexthop *nexthop; - int ret; - - rmap_family = (family == AF_INET) ? AFI_IP : AFI_IP6; - - if (prn && re) - { - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - { - ret = zebra_nht_route_map_check(rmap_family, proto, &prn->p, re, - nexthop); - if (ret != RMAP_DENYMATCH) - { - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - at_least_one++; /* at least one valid NH */ - } - else - { - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - } + int at_least_one = 0; + int rmap_family; /* Route map has diff AF family enum */ + struct nexthop *nexthop; + int ret; + + rmap_family = (family == AF_INET) ? AFI_IP : AFI_IP6; + + if (prn && re) { + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { + ret = zebra_nht_route_map_check(rmap_family, proto, + &prn->p, re, nexthop); + if (ret != RMAP_DENYMATCH) { + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + at_least_one++; /* at least one valid NH */ + } else { + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } + } } - } - return (at_least_one); + return (at_least_one); } /* * Determine appropriate route (RE entry) resolving a tracked entry * (nexthop or BGP route for import). */ -static struct route_entry * -zebra_rnh_resolve_entry (vrf_id_t vrfid, int family, rnh_type_t type, - struct route_node *nrn, struct rnh *rnh, - struct route_node **prn) +static struct route_entry *zebra_rnh_resolve_entry(vrf_id_t vrfid, int family, + rnh_type_t type, + struct route_node *nrn, + struct rnh *rnh, + struct route_node **prn) { - struct route_table *route_table; - struct route_node *rn; - struct route_entry *re; - - *prn = NULL; - - route_table = zebra_vrf_table(family2afi(family), SAFI_UNICAST, vrfid); - if (!route_table) // unexpected - return NULL; - - rn = route_node_match(route_table, &nrn->p); - if (!rn) - return NULL; - - /* When resolving nexthops, do not resolve via the default route unless - * 'ip nht resolve-via-default' is configured. - */ - if ((type == RNH_NEXTHOP_TYPE) && - (is_default_prefix (&rn->p) && - !nh_resolve_via_default(rn->p.family))) - re = NULL; - else if ((type == RNH_IMPORT_CHECK_TYPE) && - CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH) && - !prefix_same(&nrn->p, &rn->p)) - re = NULL; - else - { - /* Identify appropriate route entry. */ - RNODE_FOREACH_RE(rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - if (! CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB)) - continue; - - if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) - { - if (re->type == ZEBRA_ROUTE_CONNECT) - break; - if (re->type == ZEBRA_ROUTE_NHRP) - { - struct nexthop *nexthop; - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - if (nexthop->type == NEXTHOP_TYPE_IFINDEX) - break; - if (nexthop) - break; - } - } - else if ((type == RNH_IMPORT_CHECK_TYPE) && - (re->type == ZEBRA_ROUTE_BGP)) - continue; - else - break; - } - } - - /* Need to unlock route node */ - route_unlock_node(rn); - if (re) - *prn = rn; - return re; + struct route_table *route_table; + struct route_node *rn; + struct route_entry *re; + + *prn = NULL; + + route_table = zebra_vrf_table(family2afi(family), SAFI_UNICAST, vrfid); + if (!route_table) // unexpected + return NULL; + + rn = route_node_match(route_table, &nrn->p); + if (!rn) + return NULL; + + /* When resolving nexthops, do not resolve via the default route unless + * 'ip nht resolve-via-default' is configured. + */ + if ((type == RNH_NEXTHOP_TYPE) + && (is_default_prefix(&rn->p) + && !nh_resolve_via_default(rn->p.family))) + re = NULL; + else if ((type == RNH_IMPORT_CHECK_TYPE) + && CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH) + && !prefix_same(&nrn->p, &rn->p)) + re = NULL; + else { + /* Identify appropriate route entry. */ + RNODE_FOREACH_RE(rn, re) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + if (!CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) + continue; + + if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) { + if (re->type == ZEBRA_ROUTE_CONNECT) + break; + if (re->type == ZEBRA_ROUTE_NHRP) { + struct nexthop *nexthop; + for (nexthop = re->nexthop; nexthop; + nexthop = nexthop->next) + if (nexthop->type + == NEXTHOP_TYPE_IFINDEX) + break; + if (nexthop) + break; + } + } else if ((type == RNH_IMPORT_CHECK_TYPE) + && (re->type == ZEBRA_ROUTE_BGP)) + continue; + else + break; + } + } + + /* Need to unlock route node */ + route_unlock_node(rn); + if (re) + *prn = rn; + return re; } /* * See if a tracked route entry for import (by BGP) has undergone any * change, and if so, notify the client. */ -static void -zebra_rnh_eval_import_check_entry (vrf_id_t vrfid, int family, int force, - struct route_node *nrn, struct rnh *rnh, - struct route_entry *re) +static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, int family, + int force, struct route_node *nrn, + struct rnh *rnh, + struct route_entry *re) { - int state_changed = 0; - struct zserv *client; - char bufn[INET6_ADDRSTRLEN]; - struct listnode *node; - struct nexthop *nexthop; - - if (re && (rnh->state == NULL)) - { - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - state_changed = 1; - break; - } - } - else if (!re && (rnh->state != NULL)) - state_changed = 1; - - if (compare_state(re, rnh->state)) - copy_state(rnh, re, nrn); - - if (state_changed || force) - { - if (IS_ZEBRA_DEBUG_NHT) - { - prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); - zlog_debug("%u:%s: Route import check %s %s\n", - vrfid, bufn, rnh->state ? "passed" : "failed", - state_changed ? "(state changed)" : ""); - } - /* state changed, notify clients */ - for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) - { - send_client(rnh, client, RNH_IMPORT_CHECK_TYPE, vrfid); - } - } + int state_changed = 0; + struct zserv *client; + char bufn[INET6_ADDRSTRLEN]; + struct listnode *node; + struct nexthop *nexthop; + + if (re && (rnh->state == NULL)) { + for (ALL_NEXTHOPS(re->nexthop, nexthop)) + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) { + state_changed = 1; + break; + } + } else if (!re && (rnh->state != NULL)) + state_changed = 1; + + if (compare_state(re, rnh->state)) + copy_state(rnh, re, nrn); + + if (state_changed || force) { + if (IS_ZEBRA_DEBUG_NHT) { + prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); + zlog_debug("%u:%s: Route import check %s %s\n", vrfid, + bufn, rnh->state ? "passed" : "failed", + state_changed ? "(state changed)" : ""); + } + /* state changed, notify clients */ + for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) { + send_client(rnh, client, RNH_IMPORT_CHECK_TYPE, vrfid); + } + } } /* * Notify clients registered for this nexthop about a change. */ -static void -zebra_rnh_notify_protocol_clients (vrf_id_t vrfid, int family, - struct route_node *nrn, struct rnh *rnh, - struct route_node *prn, struct route_entry *re) +static void zebra_rnh_notify_protocol_clients(vrf_id_t vrfid, int family, + struct route_node *nrn, + struct rnh *rnh, + struct route_node *prn, + struct route_entry *re) { - struct listnode *node; - struct zserv *client; - char bufn[INET6_ADDRSTRLEN]; - char bufp[INET6_ADDRSTRLEN]; - int num_resolving_nh; - - if (IS_ZEBRA_DEBUG_NHT) - { - prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); - if (prn && re) - { - prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); - zlog_debug("%u:%s: NH resolved over route %s", vrfid, bufn, bufp); - } - else - zlog_debug("%u:%s: NH has become unresolved", vrfid, bufn); - } - - for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) - { - if (prn && re) - { - /* Apply route-map for this client to route resolving this - * nexthop to see if it is filtered or not. - */ - num_resolving_nh = zebra_rnh_apply_nht_rmap(family, prn, re, - client->proto); - if (num_resolving_nh) - rnh->filtered[client->proto] = 0; - else - rnh->filtered[client->proto] = 1; - - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("%u:%s: Notifying client %s about NH %s", - vrfid, bufn, zebra_route_string(client->proto), - num_resolving_nh ? "" : "(filtered by route-map)"); - } - else - { - rnh->filtered[client->proto] = 0; - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("%u:%s: Notifying client %s about NH (unreachable)", - vrfid, bufn, zebra_route_string(client->proto)); - } - - send_client(rnh, client, RNH_NEXTHOP_TYPE, vrfid); - } + struct listnode *node; + struct zserv *client; + char bufn[INET6_ADDRSTRLEN]; + char bufp[INET6_ADDRSTRLEN]; + int num_resolving_nh; + + if (IS_ZEBRA_DEBUG_NHT) { + prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); + if (prn && re) { + prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); + zlog_debug("%u:%s: NH resolved over route %s", vrfid, + bufn, bufp); + } else + zlog_debug("%u:%s: NH has become unresolved", vrfid, + bufn); + } + + for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) { + if (prn && re) { + /* Apply route-map for this client to route resolving + * this + * nexthop to see if it is filtered or not. + */ + num_resolving_nh = zebra_rnh_apply_nht_rmap( + family, prn, re, client->proto); + if (num_resolving_nh) + rnh->filtered[client->proto] = 0; + else + rnh->filtered[client->proto] = 1; + + if (IS_ZEBRA_DEBUG_NHT) + zlog_debug( + "%u:%s: Notifying client %s about NH %s", + vrfid, bufn, + zebra_route_string(client->proto), + num_resolving_nh + ? "" + : "(filtered by route-map)"); + } else { + rnh->filtered[client->proto] = 0; + if (IS_ZEBRA_DEBUG_NHT) + zlog_debug( + "%u:%s: Notifying client %s about NH (unreachable)", + vrfid, bufn, + zebra_route_string(client->proto)); + } + + send_client(rnh, client, RNH_NEXTHOP_TYPE, vrfid); + } } -static void -zebra_rnh_process_static_routes (vrf_id_t vrfid, int family, - struct route_node *nrn, struct rnh *rnh, - struct route_node *prn, struct route_entry *re) +static void zebra_rnh_process_static_routes(vrf_id_t vrfid, int family, + struct route_node *nrn, + struct rnh *rnh, + struct route_node *prn, + struct route_entry *re) { - struct listnode *node; - int num_resolving_nh = 0; - struct route_node *static_rn; - struct route_entry *sre; - struct nexthop *nexthop; - char bufn[INET6_ADDRSTRLEN]; - char bufp[INET6_ADDRSTRLEN]; - char bufs[INET6_ADDRSTRLEN]; - - if (IS_ZEBRA_DEBUG_NHT) - { - prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); - if (prn) - prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); - } - - if (prn && re) - { - /* Apply route-map for "static" to route resolving this - * nexthop to see if it is filtered or not. - */ - num_resolving_nh = zebra_rnh_apply_nht_rmap(family, prn, re, - ZEBRA_ROUTE_STATIC); - if (num_resolving_nh) - rnh->filtered[ZEBRA_ROUTE_STATIC] = 0; - else - rnh->filtered[ZEBRA_ROUTE_STATIC] = 1; - } - else - rnh->filtered[ZEBRA_ROUTE_STATIC] = 0; - - /* Evaluate each static route associated with this nexthop. */ - for (ALL_LIST_ELEMENTS_RO(rnh->zebra_static_route_list, node, - static_rn)) - { - RNODE_FOREACH_RE(static_rn, sre) - { - if (sre->type != ZEBRA_ROUTE_STATIC) - continue; - - /* Set the filter flag for the correct nexthop - static route may - * be having multiple. We care here only about registered nexthops. - */ - for (nexthop = sre->nexthop; nexthop; nexthop = nexthop->next) - { - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nexthop->gate.ipv4.s_addr == nrn->p.u.prefix4.s_addr) - { - if (num_resolving_nh) - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED); - else - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: + struct listnode *node; + int num_resolving_nh = 0; + struct route_node *static_rn; + struct route_entry *sre; + struct nexthop *nexthop; + char bufn[INET6_ADDRSTRLEN]; + char bufp[INET6_ADDRSTRLEN]; + char bufs[INET6_ADDRSTRLEN]; + + if (IS_ZEBRA_DEBUG_NHT) { + prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); + if (prn) + prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); + } - if (memcmp(&nexthop->gate.ipv6,&nrn->p.u.prefix6, 16) == 0) - { - if (num_resolving_nh) - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED); - else - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED); - } - break; - default: - break; - } - } - - if (IS_ZEBRA_DEBUG_NHT) - { - prefix2str(&static_rn->p, bufs, INET6_ADDRSTRLEN); - if (prn && re) - zlog_debug("%u:%s: NH change %s, scheduling static route %s", - vrfid, bufn, num_resolving_nh ? - "" : "(filtered by route-map)", bufs); - else - zlog_debug("%u:%s: NH unreachable, scheduling static route %s", - vrfid, bufn, bufs); - } - - SET_FLAG(sre->status, ROUTE_ENTRY_CHANGED); - SET_FLAG(sre->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - } - - rib_queue_add(static_rn); - } + if (prn && re) { + /* Apply route-map for "static" to route resolving this + * nexthop to see if it is filtered or not. + */ + num_resolving_nh = zebra_rnh_apply_nht_rmap(family, prn, re, + ZEBRA_ROUTE_STATIC); + if (num_resolving_nh) + rnh->filtered[ZEBRA_ROUTE_STATIC] = 0; + else + rnh->filtered[ZEBRA_ROUTE_STATIC] = 1; + } else + rnh->filtered[ZEBRA_ROUTE_STATIC] = 0; + + /* Evaluate each static route associated with this nexthop. */ + for (ALL_LIST_ELEMENTS_RO(rnh->zebra_static_route_list, node, + static_rn)) { + RNODE_FOREACH_RE(static_rn, sre) + { + if (sre->type != ZEBRA_ROUTE_STATIC) + continue; + + /* Set the filter flag for the correct nexthop - static + * route may + * be having multiple. We care here only about + * registered nexthops. + */ + for (nexthop = sre->nexthop; nexthop; + nexthop = nexthop->next) { + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nexthop->gate.ipv4.s_addr + == nrn->p.u.prefix4.s_addr) { + if (num_resolving_nh) + UNSET_FLAG( + nexthop->flags, + NEXTHOP_FLAG_FILTERED); + else + SET_FLAG( + nexthop->flags, + NEXTHOP_FLAG_FILTERED); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + + if (memcmp(&nexthop->gate.ipv6, + &nrn->p.u.prefix6, 16) + == 0) { + if (num_resolving_nh) + UNSET_FLAG( + nexthop->flags, + NEXTHOP_FLAG_FILTERED); + else + SET_FLAG( + nexthop->flags, + NEXTHOP_FLAG_FILTERED); + } + break; + default: + break; + } + } + + if (IS_ZEBRA_DEBUG_NHT) { + prefix2str(&static_rn->p, bufs, + INET6_ADDRSTRLEN); + if (prn && re) + zlog_debug( + "%u:%s: NH change %s, scheduling static route %s", + vrfid, bufn, + num_resolving_nh + ? "" + : "(filtered by route-map)", + bufs); + else + zlog_debug( + "%u:%s: NH unreachable, scheduling static route %s", + vrfid, bufn, bufs); + } + + SET_FLAG(sre->status, ROUTE_ENTRY_CHANGED); + SET_FLAG(sre->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); + } + + rib_queue_add(static_rn); + } } /* @@ -614,83 +600,78 @@ zebra_rnh_process_static_routes (vrf_id_t vrfid, int family, * take appropriate action; this involves notifying any clients and/or * scheduling dependent static routes for processing. */ -static void -zebra_rnh_eval_nexthop_entry (vrf_id_t vrfid, int family, int force, - struct route_node *nrn, struct rnh *rnh, - struct route_node *prn, struct route_entry *re) +static void zebra_rnh_eval_nexthop_entry(vrf_id_t vrfid, int family, int force, + struct route_node *nrn, + struct rnh *rnh, + struct route_node *prn, + struct route_entry *re) { - int state_changed = 0; - - /* If we're resolving over a different route, resolution has changed or - * the resolving route has some change (e.g., metric), there is a state - * change. - */ - if (!prefix_same(&rnh->resolved_route, &prn->p)) - { - if (prn) - prefix_copy(&rnh->resolved_route, &prn->p); - else - memset(&rnh->resolved_route, 0, sizeof(struct prefix)); - - copy_state(rnh, re, nrn); - state_changed = 1; - } - else if (compare_state(re, rnh->state)) - { - copy_state(rnh, re, nrn); - state_changed = 1; - } - - if (state_changed || force) - { - /* NOTE: Use the "copy" of resolving route stored in 'rnh' i.e., - * rnh->state. - */ - /* Notify registered protocol clients. */ - zebra_rnh_notify_protocol_clients (vrfid, family, nrn, rnh, - prn, rnh->state); - - /* Process static routes attached to this nexthop */ - zebra_rnh_process_static_routes (vrfid, family, nrn, rnh, - prn, rnh->state); - } + int state_changed = 0; + + /* If we're resolving over a different route, resolution has changed or + * the resolving route has some change (e.g., metric), there is a state + * change. + */ + if (!prefix_same(&rnh->resolved_route, &prn->p)) { + if (prn) + prefix_copy(&rnh->resolved_route, &prn->p); + else + memset(&rnh->resolved_route, 0, sizeof(struct prefix)); + + copy_state(rnh, re, nrn); + state_changed = 1; + } else if (compare_state(re, rnh->state)) { + copy_state(rnh, re, nrn); + state_changed = 1; + } + + if (state_changed || force) { + /* NOTE: Use the "copy" of resolving route stored in 'rnh' i.e., + * rnh->state. + */ + /* Notify registered protocol clients. */ + zebra_rnh_notify_protocol_clients(vrfid, family, nrn, rnh, prn, + rnh->state); + + /* Process static routes attached to this nexthop */ + zebra_rnh_process_static_routes(vrfid, family, nrn, rnh, prn, + rnh->state); + } } /* Evaluate one tracked entry */ -static void -zebra_rnh_evaluate_entry (vrf_id_t vrfid, int family, int force, rnh_type_t type, - struct route_node *nrn) +static void zebra_rnh_evaluate_entry(vrf_id_t vrfid, int family, int force, + rnh_type_t type, struct route_node *nrn) { - struct rnh *rnh; - struct route_entry *re; - struct route_node *prn; - char bufn[INET6_ADDRSTRLEN]; - - if (IS_ZEBRA_DEBUG_NHT) - { - prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); - zlog_debug("%u:%s: Evaluate RNH, type %d %s", - vrfid, bufn, type, force ? "(force)" : ""); - } - - rnh = nrn->info; - - /* Identify route entry (RE) resolving this tracked entry. */ - re = zebra_rnh_resolve_entry (vrfid, family, type, nrn, rnh, &prn); - - /* If the entry cannot be resolved and that is also the existing state, - * there is nothing further to do. - */ - if (!re && rnh->state == NULL && !force) - return; - - /* Process based on type of entry. */ - if (type == RNH_IMPORT_CHECK_TYPE) - zebra_rnh_eval_import_check_entry (vrfid, family, force, - nrn, rnh, re); - else - zebra_rnh_eval_nexthop_entry (vrfid, family, force, - nrn, rnh, prn, re); + struct rnh *rnh; + struct route_entry *re; + struct route_node *prn; + char bufn[INET6_ADDRSTRLEN]; + + if (IS_ZEBRA_DEBUG_NHT) { + prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); + zlog_debug("%u:%s: Evaluate RNH, type %d %s", vrfid, bufn, type, + force ? "(force)" : ""); + } + + rnh = nrn->info; + + /* Identify route entry (RE) resolving this tracked entry. */ + re = zebra_rnh_resolve_entry(vrfid, family, type, nrn, rnh, &prn); + + /* If the entry cannot be resolved and that is also the existing state, + * there is nothing further to do. + */ + if (!re && rnh->state == NULL && !force) + return; + + /* Process based on type of entry. */ + if (type == RNH_IMPORT_CHECK_TYPE) + zebra_rnh_eval_import_check_entry(vrfid, family, force, nrn, + rnh, re); + else + zebra_rnh_eval_nexthop_entry(vrfid, family, force, nrn, rnh, + prn, re); } /* @@ -702,328 +683,321 @@ zebra_rnh_evaluate_entry (vrf_id_t vrfid, int family, int force, rnh_type_t type * we can have a situation where one re entry * covers multiple nexthops we are interested in. */ -static void -zebra_rnh_clear_nhc_flag (vrf_id_t vrfid, int family, rnh_type_t type, - struct route_node *nrn) +static void zebra_rnh_clear_nhc_flag(vrf_id_t vrfid, int family, + rnh_type_t type, struct route_node *nrn) { - struct rnh *rnh; - struct route_entry *re; - struct route_node *prn; + struct rnh *rnh; + struct route_entry *re; + struct route_node *prn; - rnh = nrn->info; + rnh = nrn->info; - re = zebra_rnh_resolve_entry (vrfid, family, type, nrn, rnh, &prn); + re = zebra_rnh_resolve_entry(vrfid, family, type, nrn, rnh, &prn); - if (re) - UNSET_FLAG (re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); + if (re) + UNSET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); } /* Evaluate all tracked entries (nexthops or routes for import into BGP) * of a particular VRF and address-family or a specific prefix. */ -void -zebra_evaluate_rnh (vrf_id_t vrfid, int family, int force, rnh_type_t type, - struct prefix *p) +void zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force, rnh_type_t type, + struct prefix *p) { - struct route_table *rnh_table; - struct route_node *nrn; - - rnh_table = get_rnh_table(vrfid, family, type); - if (!rnh_table) // unexpected - return; - - if (p) - { - /* Evaluating a specific entry, make sure it exists. */ - nrn = route_node_lookup (rnh_table, p); - if (nrn && nrn->info) - zebra_rnh_evaluate_entry (vrfid, family, force, type, nrn); - - if (nrn) - route_unlock_node (nrn); - } - else - { - /* Evaluate entire table. */ - nrn = route_top (rnh_table); - while (nrn) - { - if (nrn->info) - zebra_rnh_evaluate_entry (vrfid, family, force, type, nrn); - nrn = route_next(nrn); /* this will also unlock nrn */ - } - nrn = route_top (rnh_table); - while (nrn) - { - if (nrn->info) - zebra_rnh_clear_nhc_flag (vrfid, family, type, nrn); - nrn = route_next(nrn); /* this will also unlock nrn */ - } - } + struct route_table *rnh_table; + struct route_node *nrn; + + rnh_table = get_rnh_table(vrfid, family, type); + if (!rnh_table) // unexpected + return; + + if (p) { + /* Evaluating a specific entry, make sure it exists. */ + nrn = route_node_lookup(rnh_table, p); + if (nrn && nrn->info) + zebra_rnh_evaluate_entry(vrfid, family, force, type, + nrn); + + if (nrn) + route_unlock_node(nrn); + } else { + /* Evaluate entire table. */ + nrn = route_top(rnh_table); + while (nrn) { + if (nrn->info) + zebra_rnh_evaluate_entry(vrfid, family, force, + type, nrn); + nrn = route_next(nrn); /* this will also unlock nrn */ + } + nrn = route_top(rnh_table); + while (nrn) { + if (nrn->info) + zebra_rnh_clear_nhc_flag(vrfid, family, type, + nrn); + nrn = route_next(nrn); /* this will also unlock nrn */ + } + } } -void -zebra_print_rnh_table (vrf_id_t vrfid, int af, struct vty *vty, rnh_type_t type) +void zebra_print_rnh_table(vrf_id_t vrfid, int af, struct vty *vty, + rnh_type_t type) { - struct route_table *table; - struct route_node *rn; - - table = get_rnh_table(vrfid, af, type); - if (!table) - { - zlog_debug("print_rnhs: rnh table not found\n"); - return; - } - - for (rn = route_top(table); rn; rn = route_next(rn)) - if (rn->info) - print_rnh(rn, vty); + struct route_table *table; + struct route_node *rn; + + table = get_rnh_table(vrfid, af, type); + if (!table) { + zlog_debug("print_rnhs: rnh table not found\n"); + return; + } + + for (rn = route_top(table); rn; rn = route_next(rn)) + if (rn->info) + print_rnh(rn, vty); } -int -zebra_cleanup_rnh_client (vrf_id_t vrf_id, int family, struct zserv *client, - rnh_type_t type) +int zebra_cleanup_rnh_client(vrf_id_t vrf_id, int family, struct zserv *client, + rnh_type_t type) { - struct route_table *ntable; - struct route_node *nrn; - struct rnh *rnh; - - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("%u: Client %s RNH cleanup for family %d type %d", - vrf_id, zebra_route_string(client->proto), family, type); - - ntable = get_rnh_table(vrf_id, family, type); - if (!ntable) - { - zlog_debug("cleanup_rnh_client: rnh table not found\n"); - return -1; - } - - for (nrn = route_top (ntable); nrn; nrn = route_next (nrn)) - { - if (!nrn->info) - continue; - - rnh = nrn->info; - zebra_remove_rnh_client(rnh, client, type); - } - return 1; + struct route_table *ntable; + struct route_node *nrn; + struct rnh *rnh; + + if (IS_ZEBRA_DEBUG_NHT) + zlog_debug("%u: Client %s RNH cleanup for family %d type %d", + vrf_id, zebra_route_string(client->proto), family, + type); + + ntable = get_rnh_table(vrf_id, family, type); + if (!ntable) { + zlog_debug("cleanup_rnh_client: rnh table not found\n"); + return -1; + } + + for (nrn = route_top(ntable); nrn; nrn = route_next(nrn)) { + if (!nrn->info) + continue; + + rnh = nrn->info; + zebra_remove_rnh_client(rnh, client, type); + } + return 1; } /** * free_state - free up the re structure associated with the rnh. */ -static void -free_state (vrf_id_t vrf_id, struct route_entry *re, struct route_node *rn) +static void free_state(vrf_id_t vrf_id, struct route_entry *re, + struct route_node *rn) { - if (!re) - return; + if (!re) + return; - /* free RE and nexthops */ - zebra_deregister_rnh_static_nexthops (vrf_id, re->nexthop, rn); - nexthops_free(re->nexthop); - XFREE (MTYPE_RE, re); + /* free RE and nexthops */ + zebra_deregister_rnh_static_nexthops(vrf_id, re->nexthop, rn); + nexthops_free(re->nexthop); + XFREE(MTYPE_RE, re); } -static void -copy_state (struct rnh *rnh, struct route_entry *re, struct route_node *rn) +static void copy_state(struct rnh *rnh, struct route_entry *re, + struct route_node *rn) { - struct route_entry *state; + struct route_entry *state; - if (rnh->state) - { - free_state(rnh->vrf_id, rnh->state, rn); - rnh->state = NULL; - } + if (rnh->state) { + free_state(rnh->vrf_id, rnh->state, rn); + rnh->state = NULL; + } - if (!re) - return; + if (!re) + return; - state = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - state->type = re->type; - state->metric = re->metric; + state = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + state->type = re->type; + state->metric = re->metric; - route_entry_copy_nexthops(state, re->nexthop); - rnh->state = state; + route_entry_copy_nexthops(state, re->nexthop); + rnh->state = state; } -static int -compare_state (struct route_entry *r1, struct route_entry *r2) +static int compare_state(struct route_entry *r1, struct route_entry *r2) { - if (!r1 && !r2) - return 0; + if (!r1 && !r2) + return 0; - if ((!r1 && r2) || (r1 && !r2)) - return 1; + if ((!r1 && r2) || (r1 && !r2)) + return 1; - if (r1->metric != r2->metric) - return 1; + if (r1->metric != r2->metric) + return 1; - if (r1->nexthop_num != r2->nexthop_num) - return 1; + if (r1->nexthop_num != r2->nexthop_num) + return 1; - if (CHECK_FLAG(r1->status, ROUTE_ENTRY_NEXTHOPS_CHANGED)) - return 1; + if (CHECK_FLAG(r1->status, ROUTE_ENTRY_NEXTHOPS_CHANGED)) + return 1; - return 0; + return 0; } -static int -send_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vrf_id) +static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, + vrf_id_t vrf_id) { - struct stream *s; - struct route_entry *re; - unsigned long nump; - u_char num; - struct nexthop *nexthop; - struct route_node *rn; - int cmd = (type == RNH_IMPORT_CHECK_TYPE) - ? ZEBRA_IMPORT_CHECK_UPDATE : ZEBRA_NEXTHOP_UPDATE; - - rn = rnh->node; - re = rnh->state; - - /* Get output stream. */ - s = client->obuf; - stream_reset (s); - - zserv_create_header (s, cmd, vrf_id); - - stream_putw(s, rn->p.family); - switch (rn->p.family) - { - case AF_INET: - stream_putc(s, rn->p.prefixlen); - stream_put_in_addr(s, &rn->p.u.prefix4); - break; - case AF_INET6: - stream_putc(s, rn->p.prefixlen); - stream_put(s, &rn->p.u.prefix6, IPV6_MAX_BYTELEN); - break; - default: - zlog_err("%s: Unknown family (%d) notification attempted\n", - __FUNCTION__, rn->p.family); - break; - } - if (re) - { - stream_putc (s, re->distance); - stream_putl (s, re->metric); - num = 0; - nump = stream_get_endp(s); - stream_putc (s, 0); - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - if ((CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) || - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - { - stream_putc (s, nexthop->type); - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - stream_put_in_addr (s, &nexthop->gate.ipv4); - stream_putl (s, nexthop->ifindex); + struct stream *s; + struct route_entry *re; + unsigned long nump; + u_char num; + struct nexthop *nexthop; + struct route_node *rn; + int cmd = (type == RNH_IMPORT_CHECK_TYPE) ? ZEBRA_IMPORT_CHECK_UPDATE + : ZEBRA_NEXTHOP_UPDATE; + + rn = rnh->node; + re = rnh->state; + + /* Get output stream. */ + s = client->obuf; + stream_reset(s); + + zserv_create_header(s, cmd, vrf_id); + + stream_putw(s, rn->p.family); + switch (rn->p.family) { + case AF_INET: + stream_putc(s, rn->p.prefixlen); + stream_put_in_addr(s, &rn->p.u.prefix4); break; - case NEXTHOP_TYPE_IFINDEX: - stream_putl (s, nexthop->ifindex); + case AF_INET6: + stream_putc(s, rn->p.prefixlen); + stream_put(s, &rn->p.u.prefix6, IPV6_MAX_BYTELEN); break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - stream_put_in_addr (s, &nexthop->gate.ipv4); - stream_putl (s, nexthop->ifindex); + default: + zlog_err("%s: Unknown family (%d) notification attempted\n", + __FUNCTION__, rn->p.family); break; - case NEXTHOP_TYPE_IPV6: - stream_put (s, &nexthop->gate.ipv6, 16); - stream_putl (s, nexthop->ifindex); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_put (s, &nexthop->gate.ipv6, 16); - stream_putl (s, nexthop->ifindex); - break; - default: - /* do nothing */ - break; - } - num++; - } - stream_putc_at (s, nump, num); - } - else - { - stream_putc (s, 0); // distance - stream_putl (s, 0); // metric - stream_putc (s, 0); // nexthops - } - stream_putw_at (s, 0, stream_get_endp (s)); - - client->nh_last_upd_time = monotime(NULL); - client->last_write_cmd = cmd; - return zebra_server_send_message(client); + } + if (re) { + stream_putc(s, re->distance); + stream_putl(s, re->metric); + num = 0; + nump = stream_get_endp(s); + stream_putc(s, 0); + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) + if ((CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) + || CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_RECURSIVE)) + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_ACTIVE)) { + stream_putc(s, nexthop->type); + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + stream_put_in_addr(s, + &nexthop->gate.ipv4); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IFINDEX: + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + stream_put_in_addr(s, + &nexthop->gate.ipv4); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV6: + stream_put(s, &nexthop->gate.ipv6, 16); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_put(s, &nexthop->gate.ipv6, 16); + stream_putl(s, nexthop->ifindex); + break; + default: + /* do nothing */ + break; + } + num++; + } + stream_putc_at(s, nump, num); + } else { + stream_putc(s, 0); // distance + stream_putl(s, 0); // metric + stream_putc(s, 0); // nexthops + } + stream_putw_at(s, 0, stream_get_endp(s)); + + client->nh_last_upd_time = monotime(NULL); + client->last_write_cmd = cmd; + return zebra_server_send_message(client); } -static void -print_nh (struct nexthop *nexthop, struct vty *vty) +static void print_nh(struct nexthop *nexthop, struct vty *vty) { - char buf[BUFSIZ]; - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); - if (nexthop->ifindex) - vty_out (vty, ", %s", ifindex2ifname_per_ns (zns, nexthop->ifindex)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out (vty, " %s", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); - if (nexthop->ifindex) - vty_out (vty, ", via %s", ifindex2ifname_per_ns (zns, nexthop->ifindex)); - break; - case NEXTHOP_TYPE_IFINDEX: - vty_out (vty, " is directly connected, %s", - ifindex2ifname_per_ns (zns, nexthop->ifindex)); - break; - case NEXTHOP_TYPE_BLACKHOLE: - vty_out (vty, " is directly connected, Null0"); - break; - default: - break; - } - vty_out(vty, "\n"); + char buf[BUFSIZ]; + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4)); + if (nexthop->ifindex) + vty_out(vty, ", %s", + ifindex2ifname_per_ns(zns, nexthop->ifindex)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, " %s", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); + if (nexthop->ifindex) + vty_out(vty, ", via %s", + ifindex2ifname_per_ns(zns, nexthop->ifindex)); + break; + case NEXTHOP_TYPE_IFINDEX: + vty_out(vty, " is directly connected, %s", + ifindex2ifname_per_ns(zns, nexthop->ifindex)); + break; + case NEXTHOP_TYPE_BLACKHOLE: + vty_out(vty, " is directly connected, Null0"); + break; + default: + break; + } + vty_out(vty, "\n"); } -static void -print_rnh (struct route_node *rn, struct vty *vty) +static void print_rnh(struct route_node *rn, struct vty *vty) { - struct rnh *rnh; - struct nexthop *nexthop; - struct listnode *node; - struct zserv *client; - char buf[BUFSIZ]; - - rnh = rn->info; - vty_out(vty, "%s%s\n", inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), - CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" : ""); - if (rnh->state) - { - vty_out(vty, " resolved via %s\n", - zebra_route_string(rnh->state->type)); - for (nexthop = rnh->state->nexthop; nexthop; nexthop = nexthop->next) - print_nh(nexthop, vty); - } - else - vty_out(vty, " unresolved%s\n", - CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" : ""); - - vty_out(vty, " Client list:"); - for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) - vty_out(vty, " %s(fd %d)%s", zebra_route_string(client->proto), - client->sock, rnh->filtered[client->proto] ? "(filtered)" : ""); - if (!list_isempty(rnh->zebra_static_route_list)) - vty_out(vty, " zebra%s", rnh->filtered[ZEBRA_ROUTE_STATIC] ? "(filtered)" : ""); - vty_out(vty, "\n"); + struct rnh *rnh; + struct nexthop *nexthop; + struct listnode *node; + struct zserv *client; + char buf[BUFSIZ]; + + rnh = rn->info; + vty_out(vty, "%s%s\n", + inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), + CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" + : ""); + if (rnh->state) { + vty_out(vty, " resolved via %s\n", + zebra_route_string(rnh->state->type)); + for (nexthop = rnh->state->nexthop; nexthop; + nexthop = nexthop->next) + print_nh(nexthop, vty); + } else + vty_out(vty, " unresolved%s\n", + CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) + ? "(Connected)" + : ""); + + vty_out(vty, " Client list:"); + for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) + vty_out(vty, " %s(fd %d)%s", zebra_route_string(client->proto), + client->sock, + rnh->filtered[client->proto] ? "(filtered)" : ""); + if (!list_isempty(rnh->zebra_static_route_list)) + vty_out(vty, " zebra%s", + rnh->filtered[ZEBRA_ROUTE_STATIC] ? "(filtered)" : ""); + vty_out(vty, "\n"); } diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index d26b7be25..f8d89ec8c 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -26,30 +26,28 @@ #include "vty.h" /* Nexthop structure. */ -struct rnh -{ - u_char flags; +struct rnh { + u_char flags; #define ZEBRA_NHT_CONNECTED 0x1 #define ZEBRA_NHT_DELETED 0x2 #define ZEBRA_NHT_EXACT_MATCH 0x4 - /* VRF identifier. */ - vrf_id_t vrf_id; + /* VRF identifier. */ + vrf_id_t vrf_id; - struct route_entry *state; - struct prefix resolved_route; - struct list *client_list; - struct list *zebra_static_route_list; /* static routes dependent on this NH */ - struct route_node *node; - int filtered[ZEBRA_ROUTE_MAX]; /* if this has been filtered for client */ + struct route_entry *state; + struct prefix resolved_route; + struct list *client_list; + struct list * + zebra_static_route_list; /* static routes dependent on this NH + */ + struct route_node *node; + int filtered[ZEBRA_ROUTE_MAX]; /* if this has been filtered for client + */ }; -typedef enum - { - RNH_NEXTHOP_TYPE, - RNH_IMPORT_CHECK_TYPE - } rnh_type_t; +typedef enum { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE } rnh_type_t; extern int zebra_rnh_ip_default_route; extern int zebra_rnh_ipv6_default_route; @@ -58,20 +56,24 @@ extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type); extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type); -extern void zebra_free_rnh (struct rnh *rnh); +extern void zebra_free_rnh(struct rnh *rnh); extern void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type); -extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, - vrf_id_t vrfid); -extern void zebra_register_rnh_static_nh(vrf_id_t, struct prefix *, struct route_node *); -extern void zebra_deregister_rnh_static_nexthops (vrf_id_t, struct nexthop *nexthop, - struct route_node *rn); -extern void zebra_deregister_rnh_static_nh(vrf_id_t, struct prefix *, struct route_node *); +extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, + rnh_type_t type, vrf_id_t vrfid); +extern void zebra_register_rnh_static_nh(vrf_id_t, struct prefix *, + struct route_node *); +extern void zebra_deregister_rnh_static_nexthops(vrf_id_t, + struct nexthop *nexthop, + struct route_node *rn); +extern void zebra_deregister_rnh_static_nh(vrf_id_t, struct prefix *, + struct route_node *); extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, rnh_type_t type); -extern void zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force, rnh_type_t type, - struct prefix *p); -extern void zebra_print_rnh_table(vrf_id_t vrfid, int family, struct vty *vty, rnh_type_t); +extern void zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force, + rnh_type_t type, struct prefix *p); +extern void zebra_print_rnh_table(vrf_id_t vrfid, int family, struct vty *vty, + rnh_type_t); extern char *rnh_str(struct rnh *rnh, char *buf, int size); -extern int zebra_cleanup_rnh_client(vrf_id_t vrf, int family, struct zserv *client, - rnh_type_t type); +extern int zebra_cleanup_rnh_client(vrf_id_t vrf, int family, + struct zserv *client, rnh_type_t type); #endif /*_ZEBRA_RNH_H */ diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index a7b47165d..0176b3684 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -40,185 +40,161 @@ static u_int32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER; static struct thread *zebra_t_rmap_update = NULL; -char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1]; /* "any" == ZEBRA_ROUTE_MAX */ +char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; /* "any" == ZEBRA_ROUTE_MAX */ /* NH Tracking route map */ -char *nht_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1]; /* "any" == ZEBRA_ROUTE_MAX */ +char *nht_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; /* "any" == ZEBRA_ROUTE_MAX */ char *zebra_import_table_routemap[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; -struct nh_rmap_obj -{ - struct nexthop *nexthop; - vrf_id_t vrf_id; - u_int32_t source_protocol; - int metric; - route_tag_t tag; +struct nh_rmap_obj { + struct nexthop *nexthop; + vrf_id_t vrf_id; + u_int32_t source_protocol; + int metric; + route_tag_t tag; }; static void zebra_route_map_set_delay_timer(u_int32_t value); - /* Add zebra route map rule */ -static int -zebra_route_match_add(struct vty *vty, - const char *command, const char *arg, - route_map_event_t type) -{ - VTY_DECLVAR_CONTEXT (route_map_index, index); - int ret; - - ret = route_map_add_match (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% Zebra Can't find rule.\n"); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Zebra Argument is malformed.\n"); - return CMD_WARNING_CONFIG_FAILED; +static int zebra_route_match_add(struct vty *vty, const char *command, + const char *arg, route_map_event_t type) +{ + VTY_DECLVAR_CONTEXT(route_map_index, index); + int ret; + + ret = route_map_add_match(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% Zebra Can't find rule.\n"); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, "%% Zebra Argument is malformed.\n"); + return CMD_WARNING_CONFIG_FAILED; + } } - } - if (type != RMAP_EVENT_MATCH_ADDED) - { - route_map_upd8_dependency (type, arg, index->map->name); - } - return CMD_SUCCESS; + if (type != RMAP_EVENT_MATCH_ADDED) { + route_map_upd8_dependency(type, arg, index->map->name); + } + return CMD_SUCCESS; } /* Delete zebra route map rule. */ -static int -zebra_route_match_delete (struct vty *vty, - const char *command, const char *arg, - route_map_event_t type) -{ - VTY_DECLVAR_CONTEXT (route_map_index, index); - int ret; - char *dep_name = NULL; - const char *tmpstr; - char *rmap_name = NULL; - - if (type != RMAP_EVENT_MATCH_DELETED) - { - /* ignore the mundane, the types without any dependency */ - if (arg == NULL) - { - if ((tmpstr = route_map_get_match_arg(index, command)) != NULL) - dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); - } - else - { - dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg); +static int zebra_route_match_delete(struct vty *vty, const char *command, + const char *arg, route_map_event_t type) +{ + VTY_DECLVAR_CONTEXT(route_map_index, index); + int ret; + char *dep_name = NULL; + const char *tmpstr; + char *rmap_name = NULL; + + if (type != RMAP_EVENT_MATCH_DELETED) { + /* ignore the mundane, the types without any dependency */ + if (arg == NULL) { + if ((tmpstr = route_map_get_match_arg(index, command)) + != NULL) + dep_name = + XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); + } else { + dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg); + } + rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); } - rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); - } - ret = route_map_delete_match (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% Zebra Can't find rule.\n"); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Zebra Argument is malformed.\n"); - return CMD_WARNING_CONFIG_FAILED; + ret = route_map_delete_match(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% Zebra Can't find rule.\n"); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, "%% Zebra Argument is malformed.\n"); + return CMD_WARNING_CONFIG_FAILED; + } } - } - if (type != RMAP_EVENT_MATCH_DELETED && dep_name) - route_map_upd8_dependency(type, dep_name, rmap_name); + if (type != RMAP_EVENT_MATCH_DELETED && dep_name) + route_map_upd8_dependency(type, dep_name, rmap_name); - if (dep_name) - XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); - if (rmap_name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + if (dep_name) + XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); + if (rmap_name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* 'match tag TAG' * Match function return 1 if match is success else return 0 */ -static route_map_result_t -route_match_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - route_tag_t *tag; - struct nh_rmap_obj *nh_data; + route_tag_t *tag; + struct nh_rmap_obj *nh_data; - if (type == RMAP_ZEBRA) - { - tag = rule; - nh_data = object; + if (type == RMAP_ZEBRA) { + tag = rule; + nh_data = object; - if (nh_data->tag == *tag) - return RMAP_MATCH; - } - return RMAP_NOMATCH; + if (nh_data->tag == *tag) + return RMAP_MATCH; + } + return RMAP_NOMATCH; } /* Route map commands for tag matching */ -static struct route_map_rule_cmd route_match_tag_cmd = -{ - "tag", - route_match_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free, +static struct route_map_rule_cmd route_match_tag_cmd = { + "tag", route_match_tag, route_map_rule_tag_compile, + route_map_rule_tag_free, }; /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_interface (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct nh_rmap_obj *nh_data; - char *ifname = rule; - ifindex_t ifindex; - - if (type == RMAP_ZEBRA) - { - if (strcasecmp(ifname, "any") == 0) - return RMAP_MATCH; - nh_data = object; - if (!nh_data || !nh_data->nexthop) - return RMAP_NOMATCH; - ifindex = ifname2ifindex (ifname, nh_data->vrf_id); - if (ifindex == 0) +static route_map_result_t route_match_interface(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct nh_rmap_obj *nh_data; + char *ifname = rule; + ifindex_t ifindex; + + if (type == RMAP_ZEBRA) { + if (strcasecmp(ifname, "any") == 0) + return RMAP_MATCH; + nh_data = object; + if (!nh_data || !nh_data->nexthop) + return RMAP_NOMATCH; + ifindex = ifname2ifindex(ifname, nh_data->vrf_id); + if (ifindex == 0) + return RMAP_NOMATCH; + if (nh_data->nexthop->ifindex == ifindex) + return RMAP_MATCH; + } return RMAP_NOMATCH; - if (nh_data->nexthop->ifindex == ifindex) - return RMAP_MATCH; - } - return RMAP_NOMATCH; } /* Route map `match interface' match statement. `arg' is IFNAME value */ -static void * -route_match_interface_compile (const char *arg) +static void *route_match_interface_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `match interface' value. */ -static void -route_match_interface_free (void *rule) +static void route_match_interface_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for interface matching */ -struct route_map_rule_cmd route_match_interface_cmd = -{ - "interface", - route_match_interface, - route_match_interface_compile, - route_match_interface_free -}; +struct route_map_rule_cmd route_match_interface_cmd = { + "interface", route_match_interface, route_match_interface_compile, + route_match_interface_free}; DEFUN (match_ip_address_prefix_len, match_ip_address_prefix_len_cmd, @@ -229,8 +205,8 @@ DEFUN (match_ip_address_prefix_len, "Match prefix length of ip address\n" "Prefix length\n") { - return zebra_route_match_add (vty, "ip address prefix-len", - argv[4]->arg, RMAP_EVENT_MATCH_ADDED); + return zebra_route_match_add(vty, "ip address prefix-len", argv[4]->arg, + RMAP_EVENT_MATCH_ADDED); } DEFUN (no_match_ip_address_prefix_len, @@ -243,10 +219,9 @@ DEFUN (no_match_ip_address_prefix_len, "Match prefix length of ip address\n" "Prefix length\n") { - char *plen = (argc == 6) ? argv[5]->arg : NULL; - return zebra_route_match_delete (vty, - "ip address prefix-len", plen, - RMAP_EVENT_MATCH_DELETED); + char *plen = (argc == 6) ? argv[5]->arg : NULL; + return zebra_route_match_delete(vty, "ip address prefix-len", plen, + RMAP_EVENT_MATCH_DELETED); } @@ -259,8 +234,8 @@ DEFUN (match_ip_nexthop_prefix_len, "Match prefixlen of given nexthop\n" "Prefix length\n") { - return zebra_route_match_add (vty, "ip next-hop prefix-len", - argv[4]->arg, RMAP_EVENT_MATCH_ADDED); + return zebra_route_match_add(vty, "ip next-hop prefix-len", + argv[4]->arg, RMAP_EVENT_MATCH_ADDED); } DEFUN (no_match_ip_nexthop_prefix_len, @@ -273,10 +248,9 @@ DEFUN (no_match_ip_nexthop_prefix_len, "Match prefix length of nexthop\n" "Prefix length\n") { - char *plen = (argc == 6) ? argv[5]->arg : NULL; - return zebra_route_match_delete (vty, - "ip next-hop prefix-len", plen, - RMAP_EVENT_MATCH_DELETED); + char *plen = (argc == 6) ? argv[5]->arg : NULL; + return zebra_route_match_delete(vty, "ip next-hop prefix-len", plen, + RMAP_EVENT_MATCH_DELETED); } @@ -296,16 +270,16 @@ DEFUN (match_source_protocol, "Routes from kernel\n" "Statically configured routes\n") { - char *proto = argv[2]->text; - int i; + char *proto = argv[2]->text; + int i; - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } - return zebra_route_match_add (vty, "source-protocol", proto, RMAP_EVENT_MATCH_ADDED); + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } + return zebra_route_match_add(vty, "source-protocol", proto, + RMAP_EVENT_MATCH_ADDED); } DEFUN (no_match_source_protocol, @@ -325,8 +299,9 @@ DEFUN (no_match_source_protocol, "Routes from kernel\n" "Statically configured routes\n") { - char *proto = (argc == 4) ? argv[3]->text : NULL; - return zebra_route_match_delete (vty, "source-protocol", proto, RMAP_EVENT_MATCH_DELETED); + char *proto = (argc == 4) ? argv[3]->text : NULL; + return zebra_route_match_delete(vty, "source-protocol", proto, + RMAP_EVENT_MATCH_DELETED); } /* set functions */ @@ -339,59 +314,53 @@ DEFUN (set_src, "IPv4 src address\n" "IPv6 src address\n") { - int idx_ip = 2; - union g_addr src; - struct interface *pif = NULL; - int family; - struct prefix p; - struct vrf *vrf; + int idx_ip = 2; + union g_addr src; + struct interface *pif = NULL; + int family; + struct prefix p; + struct vrf *vrf; + + if (inet_pton(AF_INET, argv[idx_ip]->arg, &src.ipv4) != 1) { + if (inet_pton(AF_INET6, argv[idx_ip]->arg, &src.ipv6) != 1) { + vty_out(vty, "%% not a valid IPv4/v6 address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + p.family = family = AF_INET6; + p.u.prefix6 = src.ipv6; + p.prefixlen = IPV6_MAX_BITLEN; + } else { + p.family = family = AF_INET; + p.u.prefix4 = src.ipv4; + p.prefixlen = IPV4_MAX_BITLEN; + } + + if (!zebra_check_addr(&p)) { + vty_out(vty, "%% not a valid source IPv4/v6 address\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (inet_pton(AF_INET, argv[idx_ip]->arg, &src.ipv4) != 1) - { - if (inet_pton(AF_INET6, argv[idx_ip]->arg, &src.ipv6) != 1) + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) { - vty_out (vty, "%% not a valid IPv4/v6 address\n"); - return CMD_WARNING_CONFIG_FAILED; + if (family == AF_INET) + pif = if_lookup_exact_address((void *)&src.ipv4, + AF_INET, vrf->vrf_id); + else if (family == AF_INET6) + pif = if_lookup_exact_address((void *)&src.ipv6, + AF_INET6, vrf->vrf_id); + + if (pif != NULL) + break; } - p.family = family = AF_INET6; - p.u.prefix6 = src.ipv6; - p.prefixlen = IPV6_MAX_BITLEN; - } - else - { - p.family = family = AF_INET; - p.u.prefix4 = src.ipv4; - p.prefixlen = IPV4_MAX_BITLEN; - } - - if (!zebra_check_addr(&p)) - { - vty_out (vty, "%% not a valid source IPv4/v6 address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - { - if (family == AF_INET) - pif = if_lookup_exact_address ((void *)&src.ipv4, AF_INET, - vrf->vrf_id); - else if (family == AF_INET6) - pif = if_lookup_exact_address ((void *)&src.ipv6, AF_INET6, - vrf->vrf_id); - - if (pif != NULL) - break; - } - - if (!pif) - { - vty_out (vty, "%% not a local address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - VTY_DECLVAR_CONTEXT (route_map_index, index); - return generic_set_add (vty, index, "src", argv[idx_ip]->arg); + if (!pif) { + vty_out(vty, "%% not a local address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + VTY_DECLVAR_CONTEXT(route_map_index, index); + return generic_set_add(vty, index, "src", argv[idx_ip]->arg); } DEFUN (no_set_src, @@ -403,9 +372,9 @@ DEFUN (no_set_src, "IPv4 address\n" "IPv6 address\n") { - char *ip = (argc == 4) ? argv[3]->arg : NULL; - VTY_DECLVAR_CONTEXT (route_map_index, index); - return generic_set_delete (vty, index, "src", ip); + char *ip = (argc == 4) ? argv[3]->arg : NULL; + VTY_DECLVAR_CONTEXT(route_map_index, index); + return generic_set_delete(vty, index, "src", ip); } DEFUN (zebra_route_map_timer, @@ -416,13 +385,13 @@ DEFUN (zebra_route_map_timer, "Time to wait before route-map updates are processed\n" "0 means event-driven updates are disabled\n") { - int idx_number = 3; - u_int32_t rmap_delay_timer; + int idx_number = 3; + u_int32_t rmap_delay_timer; - rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10); - zebra_route_map_set_delay_timer(rmap_delay_timer); + rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10); + zebra_route_map_set_delay_timer(rmap_delay_timer); - return (CMD_SUCCESS); + return (CMD_SUCCESS); } DEFUN (no_zebra_route_map_timer, @@ -434,9 +403,9 @@ DEFUN (no_zebra_route_map_timer, "Reset delay-timer to default value, 30 secs\n" "0 means event-driven updates are disabled\n") { - zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER); + zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER); - return (CMD_SUCCESS); + return (CMD_SUCCESS); } @@ -449,34 +418,33 @@ DEFUN (ip_protocol, "Specify route-map\n" "Route map name\n") { - char *proto = argv[2]->text; - char *rmap = argv[4]->arg; - int i; - - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } - if (proto_rm[AFI_IP][i]) - { - if (strcmp(proto_rm[AFI_IP][i], rmap) == 0) - return CMD_SUCCESS; + char *proto = argv[2]->text; + char *rmap = argv[4]->arg; + int i; + + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } + if (proto_rm[AFI_IP][i]) { + if (strcmp(proto_rm[AFI_IP][i], rmap) == 0) + return CMD_SUCCESS; - XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); - } - proto_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap); + XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); + } + proto_rm[AFI_IP][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IPv4 Routemap config for protocol %s, scheduling RIB processing", - VRF_DEFAULT, proto); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IPv4 Routemap config for protocol %s, scheduling RIB processing", + VRF_DEFAULT, proto); - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - return CMD_SUCCESS; + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); + return CMD_SUCCESS; } DEFUN (no_ip_protocol, @@ -489,35 +457,34 @@ DEFUN (no_ip_protocol, "Specify route map\n" "Route map name\n") { - char *proto = argv[3]->text; - char *rmap = (argc == 6) ? argv[5]->arg : NULL; - int i; + char *proto = argv[3]->text; + char *rmap = (argc == 6) ? argv[5]->arg : NULL; + int i; - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } - if (!proto_rm[AFI_IP][i]) - return CMD_SUCCESS; + if (!proto_rm[AFI_IP][i]) + return CMD_SUCCESS; - if (!rmap || strcmp (rmap, proto_rm[AFI_IP][i]) == 0) - { - XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); - proto_rm[AFI_IP][i] = NULL; + if (!rmap || strcmp(rmap, proto_rm[AFI_IP][i]) == 0) { + XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); + proto_rm[AFI_IP][i] = NULL; - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing", - VRF_DEFAULT, proto); - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - } - return CMD_SUCCESS; + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing", + VRF_DEFAULT, proto); + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); + } + return CMD_SUCCESS; } DEFUN (show_ip_protocol, @@ -527,24 +494,23 @@ DEFUN (show_ip_protocol, IP_STR "IP protocol filtering status\n") { - int i; + int i; - vty_out (vty, "Protocol : route-map \n"); - vty_out (vty, "------------------------\n"); - for (i=0;i<ZEBRA_ROUTE_MAX;i++) - { - if (proto_rm[AFI_IP][i]) - vty_out (vty, "%-10s : %-10s\n", zebra_route_string(i), - proto_rm[AFI_IP][i]); - else - vty_out (vty, "%-10s : none\n", zebra_route_string(i)); - } - if (proto_rm[AFI_IP][i]) - vty_out (vty, "%-10s : %-10s\n", "any",proto_rm[AFI_IP][i]); - else - vty_out (vty, "%-10s : none\n", "any"); + vty_out(vty, "Protocol : route-map \n"); + vty_out(vty, "------------------------\n"); + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (proto_rm[AFI_IP][i]) + vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), + proto_rm[AFI_IP][i]); + else + vty_out(vty, "%-10s : none\n", zebra_route_string(i)); + } + if (proto_rm[AFI_IP][i]) + vty_out(vty, "%-10s : %-10s\n", "any", proto_rm[AFI_IP][i]); + else + vty_out(vty, "%-10s : none\n", "any"); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_protocol, @@ -556,34 +522,33 @@ DEFUN (ipv6_protocol, "Specify route map\n" "Route map name\n") { - char *proto = argv[2]->text; - char *rmap = argv[4]->arg; - int i; - - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } - if (proto_rm[AFI_IP6][i]) - { - if (strcmp(proto_rm[AFI_IP6][i], rmap) == 0) - return CMD_SUCCESS; + char *proto = argv[2]->text; + char *rmap = argv[4]->arg; + int i; + + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } + if (proto_rm[AFI_IP6][i]) { + if (strcmp(proto_rm[AFI_IP6][i], rmap) == 0) + return CMD_SUCCESS; - XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]); - } - proto_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap); + XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]); + } + proto_rm[AFI_IP6][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IPv6 Routemap config for protocol %s, scheduling RIB processing", - VRF_DEFAULT, proto); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IPv6 Routemap config for protocol %s, scheduling RIB processing", + VRF_DEFAULT, proto); - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - return CMD_SUCCESS; + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); + return CMD_SUCCESS; } DEFUN (no_ipv6_protocol, @@ -596,34 +561,33 @@ DEFUN (no_ipv6_protocol, "Specify route map\n" "Route map name\n") { - const char *proto = argv[3]->text; - const char *rmap = (argc == 6) ? argv[5]->arg : NULL; - int i; - - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } - if (!proto_rm[AFI_IP6][i]) - return CMD_SUCCESS; + const char *proto = argv[3]->text; + const char *rmap = (argc == 6) ? argv[5]->arg : NULL; + int i; + + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } + if (!proto_rm[AFI_IP6][i]) + return CMD_SUCCESS; - if (!rmap || strcmp(rmap, proto_rm[AFI_IP6][i]) == 0) - { - XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]); - proto_rm[AFI_IP6][i] = NULL; + if (!rmap || strcmp(rmap, proto_rm[AFI_IP6][i]) == 0) { + XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]); + proto_rm[AFI_IP6][i] = NULL; - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing", - VRF_DEFAULT, proto); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing", + VRF_DEFAULT, proto); - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - } - return CMD_SUCCESS; + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); + } + return CMD_SUCCESS; } DEFUN (show_ipv6_protocol, @@ -633,24 +597,23 @@ DEFUN (show_ipv6_protocol, IP6_STR "IPv6 protocol filtering status\n") { - int i; + int i; - vty_out (vty, "Protocol : route-map \n"); - vty_out (vty, "------------------------\n"); - for (i=0;i<ZEBRA_ROUTE_MAX;i++) - { - if (proto_rm[AFI_IP6][i]) - vty_out (vty, "%-10s : %-10s\n", zebra_route_string(i), - proto_rm[AFI_IP6][i]); - else - vty_out (vty, "%-10s : none\n", zebra_route_string(i)); - } - if (proto_rm[AFI_IP6][i]) - vty_out (vty, "%-10s : %-10s\n", "any",proto_rm[AFI_IP6][i]); - else - vty_out (vty, "%-10s : none\n", "any"); + vty_out(vty, "Protocol : route-map \n"); + vty_out(vty, "------------------------\n"); + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (proto_rm[AFI_IP6][i]) + vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), + proto_rm[AFI_IP6][i]); + else + vty_out(vty, "%-10s : none\n", zebra_route_string(i)); + } + if (proto_rm[AFI_IP6][i]) + vty_out(vty, "%-10s : %-10s\n", "any", proto_rm[AFI_IP6][i]); + else + vty_out(vty, "%-10s : none\n", "any"); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_protocol_nht_rmap, @@ -662,31 +625,29 @@ DEFUN (ip_protocol_nht_rmap, "Specify route map\n" "Route map name\n") { - char *proto = argv[2]->text; - char *rmap = argv[4]->arg; - int i; - - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } - if (nht_rm[AFI_IP][i]) - { - if (strcmp(nht_rm[AFI_IP][i], rmap) == 0) - return CMD_SUCCESS; + char *proto = argv[2]->text; + char *rmap = argv[4]->arg; + int i; + + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } + if (nht_rm[AFI_IP][i]) { + if (strcmp(nht_rm[AFI_IP][i], rmap) == 0) + return CMD_SUCCESS; - XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]); - } + XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]); + } - nht_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap); - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + nht_rm[AFI_IP][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_protocol_nht_rmap, @@ -699,28 +660,28 @@ DEFUN (no_ip_protocol_nht_rmap, "Specify route map\n" "Route map name\n") { - int idx = 0; - char *proto = argv[3]->text; - char *rmap = argv_find (argv, argc, "ROUTE-MAP", &idx) ? argv[idx]->arg : NULL; + int idx = 0; + char *proto = argv[3]->text; + char *rmap = argv_find(argv, argc, "ROUTE-MAP", &idx) ? argv[idx]->arg + : NULL; - int i = strmatch(proto, "any") ? ZEBRA_ROUTE_MAX : proto_name2num(proto); + int i = strmatch(proto, "any") ? ZEBRA_ROUTE_MAX + : proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } - if (!nht_rm[AFI_IP][i]) - return CMD_SUCCESS; + if (!nht_rm[AFI_IP][i]) + return CMD_SUCCESS; - if (!rmap || strcmp(rmap, nht_rm[AFI_IP][i]) == 0) - { - XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]); - nht_rm[AFI_IP][i] = NULL; - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - } - return CMD_SUCCESS; + if (!rmap || strcmp(rmap, nht_rm[AFI_IP][i]) == 0) { + XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]); + nht_rm[AFI_IP][i] = NULL; + zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + } + return CMD_SUCCESS; } DEFUN (show_ip_protocol_nht, @@ -731,24 +692,23 @@ DEFUN (show_ip_protocol_nht, "IP nexthop tracking table\n" "IP Next Hop tracking filtering status\n") { - int i; + int i; - vty_out (vty, "Protocol : route-map \n"); - vty_out (vty, "------------------------\n"); - for (i=0;i<ZEBRA_ROUTE_MAX;i++) - { - if (nht_rm[AFI_IP][i]) - vty_out (vty, "%-10s : %-10s\n", zebra_route_string(i), - nht_rm[AFI_IP][i]); - else - vty_out (vty, "%-10s : none\n", zebra_route_string(i)); - } - if (nht_rm[AFI_IP][i]) - vty_out (vty, "%-10s : %-10s\n", "any",nht_rm[AFI_IP][i]); - else - vty_out (vty, "%-10s : none\n", "any"); + vty_out(vty, "Protocol : route-map \n"); + vty_out(vty, "------------------------\n"); + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (nht_rm[AFI_IP][i]) + vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), + nht_rm[AFI_IP][i]); + else + vty_out(vty, "%-10s : none\n", zebra_route_string(i)); + } + if (nht_rm[AFI_IP][i]) + vty_out(vty, "%-10s : %-10s\n", "any", nht_rm[AFI_IP][i]); + else + vty_out(vty, "%-10s : none\n", "any"); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_protocol_nht_rmap, @@ -760,25 +720,24 @@ DEFUN (ipv6_protocol_nht_rmap, "Specify route map\n" "Route map name\n") { - char *proto = argv[2]->text; - char *rmap = argv[4]->arg; - int i; - - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } - if (nht_rm[AFI_IP6][i]) - XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]); - nht_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap); - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + char *proto = argv[2]->text; + char *rmap = argv[4]->arg; + int i; + + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } + if (nht_rm[AFI_IP6][i]) + XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]); + nht_rm[AFI_IP6][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_protocol_nht_rmap, @@ -791,35 +750,32 @@ DEFUN (no_ipv6_protocol_nht_rmap, "Specify route map\n" "Route map name\n") { - char *proto = argv[3]->text; - char *rmap = (argc == 6) ? argv[5]->arg : NULL; - int i; - - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } + char *proto = argv[3]->text; + char *rmap = (argc == 6) ? argv[5]->arg : NULL; + int i; + + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } - if (nht_rm[AFI_IP6][i] && rmap && strcmp(rmap, nht_rm[AFI_IP6][i])) - { - vty_out (vty, "invalid route-map \"%s\"\n", rmap); - return CMD_WARNING_CONFIG_FAILED; - } + if (nht_rm[AFI_IP6][i] && rmap && strcmp(rmap, nht_rm[AFI_IP6][i])) { + vty_out(vty, "invalid route-map \"%s\"\n", rmap); + return CMD_WARNING_CONFIG_FAILED; + } - if (nht_rm[AFI_IP6][i]) - { - XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]); - nht_rm[AFI_IP6][i] = NULL; - } + if (nht_rm[AFI_IP6][i]) { + XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]); + nht_rm[AFI_IP6][i] = NULL; + } - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_protocol_nht, @@ -830,24 +786,23 @@ DEFUN (show_ipv6_protocol_nht, "Next Hop filtering status\n" "Route-map\n") { - int i; + int i; - vty_out (vty, "Protocol : route-map \n"); - vty_out (vty, "------------------------\n"); - for (i=0;i<ZEBRA_ROUTE_MAX;i++) - { - if (nht_rm[AFI_IP6][i]) - vty_out (vty, "%-10s : %-10s\n", zebra_route_string(i), - nht_rm[AFI_IP6][i]); - else - vty_out (vty, "%-10s : none\n", zebra_route_string(i)); - } - if (nht_rm[AFI_IP][i]) - vty_out (vty, "%-10s : %-10s\n", "any",nht_rm[AFI_IP6][i]); - else - vty_out (vty, "%-10s : none\n", "any"); + vty_out(vty, "Protocol : route-map \n"); + vty_out(vty, "------------------------\n"); + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (nht_rm[AFI_IP6][i]) + vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), + nht_rm[AFI_IP6][i]); + else + vty_out(vty, "%-10s : none\n", zebra_route_string(i)); + } + if (nht_rm[AFI_IP][i]) + vty_out(vty, "%-10s : %-10s\n", "any", nht_rm[AFI_IP6][i]); + else + vty_out(vty, "%-10s : none\n", "any"); - return CMD_SUCCESS; + return CMD_SUCCESS; } /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/ @@ -855,680 +810,634 @@ DEFUN (show_ipv6_protocol_nht, /* `match ip next-hop IP_ACCESS_LIST' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_next_hop (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct access_list *alist; - struct nh_rmap_obj *nh_data; - struct prefix_ipv4 p; - - if (type == RMAP_ZEBRA) - { - nh_data = object; - if (!nh_data) - return RMAP_DENYMATCH; - - switch (nh_data->nexthop->type) { - case NEXTHOP_TYPE_IFINDEX: - /* Interface routes can't match ip next-hop */ - return RMAP_NOMATCH; - case NEXTHOP_TYPE_IPV4_IFINDEX: - case NEXTHOP_TYPE_IPV4: - p.family = AF_INET; - p.prefix = nh_data->nexthop->gate.ipv4; - p.prefixlen = IPV4_MAX_BITLEN; - break; - default: - return RMAP_NOMATCH; - } - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) +static route_map_result_t route_match_ip_next_hop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct access_list *alist; + struct nh_rmap_obj *nh_data; + struct prefix_ipv4 p; + + if (type == RMAP_ZEBRA) { + nh_data = object; + if (!nh_data) + return RMAP_DENYMATCH; + + switch (nh_data->nexthop->type) { + case NEXTHOP_TYPE_IFINDEX: + /* Interface routes can't match ip next-hop */ + return RMAP_NOMATCH; + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + p.family = AF_INET; + p.prefix = nh_data->nexthop->gate.ipv4; + p.prefixlen = IPV4_MAX_BITLEN; + break; + default: + return RMAP_NOMATCH; + } + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; + + return (access_list_apply(alist, &p) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (access_list_apply (alist, &p) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } /* Route map `ip next-hop' match statement. `arg' should be access-list name. */ -static void * -route_match_ip_next_hop_compile (const char *arg) +static void *route_match_ip_next_hop_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `. */ -static void -route_match_ip_next_hop_free (void *rule) +static void route_match_ip_next_hop_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip next-hop matching. */ -static struct route_map_rule_cmd route_match_ip_next_hop_cmd = -{ - "ip next-hop", - route_match_ip_next_hop, - route_match_ip_next_hop_compile, - route_match_ip_next_hop_free -}; +static struct route_map_rule_cmd route_match_ip_next_hop_cmd = { + "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile, + route_match_ip_next_hop_free}; /* `match ip next-hop prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; - struct nh_rmap_obj *nh_data; - struct prefix_ipv4 p; - - if (type == RMAP_ZEBRA) - { - nh_data = (struct nh_rmap_obj *)object; - if (!nh_data) - return RMAP_DENYMATCH; - - switch (nh_data->nexthop->type) { - case NEXTHOP_TYPE_IFINDEX: - /* Interface routes can't match ip next-hop */ - return RMAP_NOMATCH; - case NEXTHOP_TYPE_IPV4_IFINDEX: - case NEXTHOP_TYPE_IPV4: - p.family = AF_INET; - p.prefix = nh_data->nexthop->gate.ipv4; - p.prefixlen = IPV4_MAX_BITLEN; - break; - default: - return RMAP_NOMATCH; - } - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) - return RMAP_NOMATCH; - - return (prefix_list_apply (plist, &p) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + struct prefix_list *plist; + struct nh_rmap_obj *nh_data; + struct prefix_ipv4 p; + + if (type == RMAP_ZEBRA) { + nh_data = (struct nh_rmap_obj *)object; + if (!nh_data) + return RMAP_DENYMATCH; + + switch (nh_data->nexthop->type) { + case NEXTHOP_TYPE_IFINDEX: + /* Interface routes can't match ip next-hop */ + return RMAP_NOMATCH; + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + p.family = AF_INET; + p.prefix = nh_data->nexthop->gate.ipv4; + p.prefixlen = IPV4_MAX_BITLEN; + break; + default: + return RMAP_NOMATCH; + } + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; + + return (prefix_list_apply(plist, &p) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ip_next_hop_prefix_list_compile (const char *arg) +static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_next_hop_prefix_list_free (void *rule) +static void route_match_ip_next_hop_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = -{ - "ip next-hop prefix-list", - route_match_ip_next_hop_prefix_list, - route_match_ip_next_hop_prefix_list_compile, - route_match_ip_next_hop_prefix_list_free -}; +static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { + "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list, + route_match_ip_next_hop_prefix_list_compile, + route_match_ip_next_hop_prefix_list_free}; /* `match ip address IP_ACCESS_LIST' */ /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_address (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_ip_address(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct access_list *alist; + struct access_list *alist; + + if (type == RMAP_ZEBRA) { + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; - if (type == RMAP_ZEBRA) - { - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) + return (access_list_apply(alist, prefix) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (access_list_apply (alist, prefix) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } /* Route map `ip address' match statement. `arg' should be access-list name. */ -static void * -route_match_ip_address_compile (const char *arg) +static void *route_match_ip_address_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `ip address' value. */ -static void -route_match_ip_address_free (void *rule) +static void route_match_ip_address_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip address matching. */ -static struct route_map_rule_cmd route_match_ip_address_cmd = -{ - "ip address", - route_match_ip_address, - route_match_ip_address_compile, - route_match_ip_address_free -}; +static struct route_map_rule_cmd route_match_ip_address_cmd = { + "ip address", route_match_ip_address, route_match_ip_address_compile, + route_match_ip_address_free}; /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; + struct prefix_list *plist; + + if (type == RMAP_ZEBRA) { + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; - if (type == RMAP_ZEBRA) - { - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) + return (prefix_list_apply(plist, prefix) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } -static void * -route_match_ip_address_prefix_list_compile (const char *arg) +static void *route_match_ip_address_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_address_prefix_list_free (void *rule) +static void route_match_ip_address_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = -{ - "ip address prefix-list", - route_match_ip_address_prefix_list, - route_match_ip_address_prefix_list_compile, - route_match_ip_address_prefix_list_free -}; +static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { + "ip address prefix-list", route_match_ip_address_prefix_list, + route_match_ip_address_prefix_list_compile, + route_match_ip_address_prefix_list_free}; /* `match ip address prefix-len PREFIXLEN' */ static route_map_result_t -route_match_ip_address_prefix_len (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address_prefix_len(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - u_int32_t *prefixlen = (u_int32_t *)rule; + u_int32_t *prefixlen = (u_int32_t *)rule; - if (type == RMAP_ZEBRA) - { - return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH); - } - return RMAP_NOMATCH; + if (type == RMAP_ZEBRA) { + return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH + : RMAP_NOMATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ip_address_prefix_len_compile (const char *arg) +static void *route_match_ip_address_prefix_len_compile(const char *arg) { - u_int32_t *prefix_len; - char *endptr = NULL; - unsigned long tmpval; + u_int32_t *prefix_len; + char *endptr = NULL; + unsigned long tmpval; - /* prefix len value shoud be integer. */ - if (! all_digit (arg)) - return NULL; + /* prefix len value shoud be integer. */ + if (!all_digit(arg)) + return NULL; - errno = 0; - tmpval = strtoul (arg, &endptr, 10); - if (*endptr != '\0' || errno || tmpval > UINT32_MAX) - return NULL; + errno = 0; + tmpval = strtoul(arg, &endptr, 10); + if (*endptr != '\0' || errno || tmpval > UINT32_MAX) + return NULL; - prefix_len = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); + prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); - if (!prefix_len) - return prefix_len; + if (!prefix_len) + return prefix_len; - *prefix_len = tmpval; - return prefix_len; + *prefix_len = tmpval; + return prefix_len; } -static void -route_match_ip_address_prefix_len_free (void *rule) +static void route_match_ip_address_prefix_len_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd = -{ - "ip address prefix-len", - route_match_ip_address_prefix_len, - route_match_ip_address_prefix_len_compile, - route_match_ip_address_prefix_len_free -}; +static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd = { + "ip address prefix-len", route_match_ip_address_prefix_len, + route_match_ip_address_prefix_len_compile, + route_match_ip_address_prefix_len_free}; /* `match ip nexthop prefix-len PREFIXLEN' */ static route_map_result_t -route_match_ip_nexthop_prefix_len (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - u_int32_t *prefixlen = (u_int32_t *)rule; - struct nh_rmap_obj *nh_data; - struct prefix_ipv4 p; - - if (type == RMAP_ZEBRA) - { - nh_data = (struct nh_rmap_obj *)object; - if (!nh_data || !nh_data->nexthop) - return RMAP_DENYMATCH; - - switch (nh_data->nexthop->type) { - case NEXTHOP_TYPE_IFINDEX: - /* Interface routes can't match ip next-hop */ - return RMAP_NOMATCH; - case NEXTHOP_TYPE_IPV4_IFINDEX: - case NEXTHOP_TYPE_IPV4: - p.family = AF_INET; - p.prefix = nh_data->nexthop->gate.ipv4; - p.prefixlen = IPV4_MAX_BITLEN; - break; - default: - return RMAP_NOMATCH; - } - return ((p.prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH); - } - return RMAP_NOMATCH; -} - -static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = -{ - "ip next-hop prefix-len", - route_match_ip_nexthop_prefix_len, - route_match_ip_address_prefix_len_compile, /* reuse */ - route_match_ip_address_prefix_len_free /* reuse */ +route_match_ip_nexthop_prefix_len(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_int32_t *prefixlen = (u_int32_t *)rule; + struct nh_rmap_obj *nh_data; + struct prefix_ipv4 p; + + if (type == RMAP_ZEBRA) { + nh_data = (struct nh_rmap_obj *)object; + if (!nh_data || !nh_data->nexthop) + return RMAP_DENYMATCH; + + switch (nh_data->nexthop->type) { + case NEXTHOP_TYPE_IFINDEX: + /* Interface routes can't match ip next-hop */ + return RMAP_NOMATCH; + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + p.family = AF_INET; + p.prefix = nh_data->nexthop->gate.ipv4; + p.prefixlen = IPV4_MAX_BITLEN; + break; + default: + return RMAP_NOMATCH; + } + return ((p.prefixlen == *prefixlen) ? RMAP_MATCH + : RMAP_NOMATCH); + } + return RMAP_NOMATCH; +} + +static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = { + "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len, + route_match_ip_address_prefix_len_compile, /* reuse */ + route_match_ip_address_prefix_len_free /* reuse */ }; /* `match source-protocol PROTOCOL' */ -static route_map_result_t -route_match_source_protocol (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_source_protocol(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - u_int32_t *rib_type = (u_int32_t *)rule; - struct nh_rmap_obj *nh_data; + u_int32_t *rib_type = (u_int32_t *)rule; + struct nh_rmap_obj *nh_data; - if (type == RMAP_ZEBRA) - { - nh_data = (struct nh_rmap_obj *)object; - if (!nh_data) - return RMAP_DENYMATCH; + if (type == RMAP_ZEBRA) { + nh_data = (struct nh_rmap_obj *)object; + if (!nh_data) + return RMAP_DENYMATCH; - return ((nh_data->source_protocol == *rib_type) - ? RMAP_MATCH : RMAP_NOMATCH); - } - return RMAP_NOMATCH; + return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH + : RMAP_NOMATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_source_protocol_compile (const char *arg) +static void *route_match_source_protocol_compile(const char *arg) { - u_int32_t *rib_type; - int i; + u_int32_t *rib_type; + int i; - i = proto_name2num(arg); - rib_type = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); + i = proto_name2num(arg); + rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); - *rib_type = i; + *rib_type = i; - return rib_type; + return rib_type; } -static void -route_match_source_protocol_free (void *rule) +static void route_match_source_protocol_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_source_protocol_cmd = -{ - "source-protocol", - route_match_source_protocol, - route_match_source_protocol_compile, - route_match_source_protocol_free -}; +static struct route_map_rule_cmd route_match_source_protocol_cmd = { + "source-protocol", route_match_source_protocol, + route_match_source_protocol_compile, route_match_source_protocol_free}; /* `set src A.B.C.D' */ /* Set src. */ -static route_map_result_t -route_set_src (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_src(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct nh_rmap_obj *nh_data; + struct nh_rmap_obj *nh_data; - if (type == RMAP_ZEBRA) - { - nh_data = (struct nh_rmap_obj *)object; - nh_data->nexthop->rmap_src = *(union g_addr *)rule; - } - return RMAP_OKAY; + if (type == RMAP_ZEBRA) { + nh_data = (struct nh_rmap_obj *)object; + nh_data->nexthop->rmap_src = *(union g_addr *)rule; + } + return RMAP_OKAY; } /* set src compilation. */ -static void * -route_set_src_compile (const char *arg) +static void *route_set_src_compile(const char *arg) { - union g_addr src, *psrc; + union g_addr src, *psrc; - if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1) || - (src.ipv4.s_addr && (inet_pton(AF_INET, arg, &src.ipv4) == 1))) - { - psrc = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union g_addr)); - *psrc = src; - return psrc; - } - return NULL; + if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1) + || (src.ipv4.s_addr && (inet_pton(AF_INET, arg, &src.ipv4) == 1))) { + psrc = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union g_addr)); + *psrc = src; + return psrc; + } + return NULL; } /* Free route map's compiled `set src' value. */ -static void -route_set_src_free (void *rule) +static void route_set_src_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Set src rule structure. */ -static struct route_map_rule_cmd route_set_src_cmd = -{ - "src", - route_set_src, - route_set_src_compile, - route_set_src_free, +static struct route_map_rule_cmd route_set_src_cmd = { + "src", route_set_src, route_set_src_compile, route_set_src_free, }; -static int -zebra_route_map_update_timer (struct thread *thread) +static int zebra_route_map_update_timer(struct thread *thread) { - zebra_t_rmap_update = NULL; + zebra_t_rmap_update = NULL; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("Event driven route-map update triggered"); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("Event driven route-map update triggered"); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: Routemap update-timer fired, scheduling RIB processing", - VRF_DEFAULT); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: Routemap update-timer fired, scheduling RIB processing", + VRF_DEFAULT); - zebra_import_table_rm_update (); - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_import_table_rm_update(); + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); + zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return (0); + return (0); } -static void -zebra_route_map_set_delay_timer(u_int32_t value) +static void zebra_route_map_set_delay_timer(u_int32_t value) { - zebra_rmap_update_timer = value; - if (!value && zebra_t_rmap_update) - { - /* Event driven route map updates is being disabled */ - /* But there's a pending timer. Fire it off now */ - thread_cancel(zebra_t_rmap_update); - zebra_route_map_update_timer(zebra_t_rmap_update); - } + zebra_rmap_update_timer = value; + if (!value && zebra_t_rmap_update) { + /* Event driven route map updates is being disabled */ + /* But there's a pending timer. Fire it off now */ + thread_cancel(zebra_t_rmap_update); + zebra_route_map_update_timer(zebra_t_rmap_update); + } } -void -zebra_route_map_write_delay_timer (struct vty *vty) +void zebra_route_map_write_delay_timer(struct vty *vty) { - if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)) - vty_out (vty, "zebra route-map delay-timer %d\n", - zebra_rmap_update_timer); - return; + if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)) + vty_out(vty, "zebra route-map delay-timer %d\n", + zebra_rmap_update_timer); + return; } -route_map_result_t -zebra_route_map_check (int family, int rib_type, struct prefix *p, - struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag) +route_map_result_t zebra_route_map_check(int family, int rib_type, + struct prefix *p, + struct nexthop *nexthop, + vrf_id_t vrf_id, route_tag_t tag) { - struct route_map *rmap = NULL; - route_map_result_t ret = RMAP_MATCH; - struct nh_rmap_obj nh_obj; + struct route_map *rmap = NULL; + route_map_result_t ret = RMAP_MATCH; + struct nh_rmap_obj nh_obj; - nh_obj.nexthop = nexthop; - nh_obj.vrf_id = vrf_id; - nh_obj.source_protocol = rib_type; - nh_obj.metric = 0; - nh_obj.tag = tag; + nh_obj.nexthop = nexthop; + nh_obj.vrf_id = vrf_id; + nh_obj.source_protocol = rib_type; + nh_obj.metric = 0; + nh_obj.tag = tag; - if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX) - rmap = route_map_lookup_by_name (proto_rm[family][rib_type]); - if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX]) - rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]); - if (rmap) { - ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); - } + if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX) + rmap = route_map_lookup_by_name(proto_rm[family][rib_type]); + if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX]) + rmap = route_map_lookup_by_name( + proto_rm[family][ZEBRA_ROUTE_MAX]); + if (rmap) { + ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); + } - return (ret); + return (ret); } -char * -zebra_get_import_table_route_map (afi_t afi, uint32_t table) +char *zebra_get_import_table_route_map(afi_t afi, uint32_t table) { - return zebra_import_table_routemap[afi][table]; + return zebra_import_table_routemap[afi][table]; } -void -zebra_add_import_table_route_map (afi_t afi, const char *rmap_name, uint32_t table) +void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name, + uint32_t table) { - zebra_import_table_routemap[afi][table] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap_name); + zebra_import_table_routemap[afi][table] = + XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name); } -void -zebra_del_import_table_route_map (afi_t afi, uint32_t table) +void zebra_del_import_table_route_map(afi_t afi, uint32_t table) { - XFREE (MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]); + XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]); } route_map_result_t -zebra_import_table_route_map_check (int family, int re_type, struct prefix *p, - struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag, const char *rmap_name) -{ - struct route_map *rmap = NULL; - route_map_result_t ret = RMAP_DENYMATCH; - struct nh_rmap_obj nh_obj; - - nh_obj.nexthop = nexthop; - nh_obj.vrf_id = vrf_id; - nh_obj.source_protocol = re_type; - nh_obj.metric = 0; - nh_obj.tag = tag; - - if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX) - rmap = route_map_lookup_by_name (rmap_name); - if (rmap) { - ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); - } +zebra_import_table_route_map_check(int family, int re_type, struct prefix *p, + struct nexthop *nexthop, vrf_id_t vrf_id, + route_tag_t tag, const char *rmap_name) +{ + struct route_map *rmap = NULL; + route_map_result_t ret = RMAP_DENYMATCH; + struct nh_rmap_obj nh_obj; + + nh_obj.nexthop = nexthop; + nh_obj.vrf_id = vrf_id; + nh_obj.source_protocol = re_type; + nh_obj.metric = 0; + nh_obj.tag = tag; + + if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX) + rmap = route_map_lookup_by_name(rmap_name); + if (rmap) { + ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); + } - return (ret); + return (ret); } -route_map_result_t -zebra_nht_route_map_check (int family, int client_proto, struct prefix *p, - struct route_entry * re, struct nexthop *nexthop) +route_map_result_t zebra_nht_route_map_check(int family, int client_proto, + struct prefix *p, + struct route_entry *re, + struct nexthop *nexthop) { - struct route_map *rmap = NULL; - route_map_result_t ret = RMAP_MATCH; - struct nh_rmap_obj nh_obj; + struct route_map *rmap = NULL; + route_map_result_t ret = RMAP_MATCH; + struct nh_rmap_obj nh_obj; - nh_obj.nexthop = nexthop; - nh_obj.vrf_id = re->vrf_id; - nh_obj.source_protocol = re->type; - nh_obj.metric = re->metric; - nh_obj.tag = re->tag; + nh_obj.nexthop = nexthop; + nh_obj.vrf_id = re->vrf_id; + nh_obj.source_protocol = re->type; + nh_obj.metric = re->metric; + nh_obj.tag = re->tag; - if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX) - rmap = route_map_lookup_by_name (nht_rm[family][client_proto]); - if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX]) - rmap = route_map_lookup_by_name (nht_rm[family][ZEBRA_ROUTE_MAX]); - if (rmap) { - ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); - } + if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX) + rmap = route_map_lookup_by_name(nht_rm[family][client_proto]); + if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX]) + rmap = route_map_lookup_by_name( + nht_rm[family][ZEBRA_ROUTE_MAX]); + if (rmap) { + ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); + } - return (ret); + return (ret); } -static void -zebra_route_map_mark_update (const char *rmap_name) +static void zebra_route_map_mark_update(const char *rmap_name) { - /* rmap_update_timer of 0 means don't do route updates */ - if (zebra_rmap_update_timer && !zebra_t_rmap_update) { - zebra_t_rmap_update = NULL; - thread_add_timer(zebrad.master, zebra_route_map_update_timer, NULL, zebra_rmap_update_timer, - &zebra_t_rmap_update); - } + /* rmap_update_timer of 0 means don't do route updates */ + if (zebra_rmap_update_timer && !zebra_t_rmap_update) { + zebra_t_rmap_update = NULL; + thread_add_timer(zebrad.master, zebra_route_map_update_timer, + NULL, zebra_rmap_update_timer, + &zebra_t_rmap_update); + } } -static void -zebra_route_map_add (const char *rmap_name) +static void zebra_route_map_add(const char *rmap_name) { - zebra_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); + zebra_route_map_mark_update(rmap_name); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); } -static void -zebra_route_map_delete (const char *rmap_name) +static void zebra_route_map_delete(const char *rmap_name) { - zebra_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); + zebra_route_map_mark_update(rmap_name); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); } -static void -zebra_route_map_event (route_map_event_t event, const char *rmap_name) +static void zebra_route_map_event(route_map_event_t event, + const char *rmap_name) { - zebra_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); + zebra_route_map_mark_update(rmap_name); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); } /* ip protocol configuration write function */ -void -zebra_routemap_config_write_protocol (struct vty *vty) -{ - int i; - - for (i=0;i<ZEBRA_ROUTE_MAX;i++) - { - if (proto_rm[AFI_IP][i]) - vty_out (vty, "ip protocol %s route-map %s\n", zebra_route_string(i), - proto_rm[AFI_IP][i]); - - if (proto_rm[AFI_IP6][i]) - vty_out (vty, "ipv6 protocol %s route-map %s\n", zebra_route_string(i), - proto_rm[AFI_IP6][i]); - - if (nht_rm[AFI_IP][i]) - vty_out (vty, "ip nht %s route-map %s\n", zebra_route_string(i), - nht_rm[AFI_IP][i]); - - if (nht_rm[AFI_IP6][i]) - vty_out (vty, "ipv6 nht %s route-map %s\n", zebra_route_string(i), - nht_rm[AFI_IP6][i]); - } - - if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX]) - vty_out (vty, "ip protocol %s route-map %s\n", "any", - proto_rm[AFI_IP][ZEBRA_ROUTE_MAX]); - - if (proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX]) - vty_out (vty, "ipv6 protocol %s route-map %s\n", "any", - proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX]); - - if (nht_rm[AFI_IP][ZEBRA_ROUTE_MAX]) - vty_out (vty, "ip nht %s route-map %s\n", "any", - nht_rm[AFI_IP][ZEBRA_ROUTE_MAX]); - - if (nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX]) - vty_out (vty, "ipv6 nht %s route-map %s\n", "any", - nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX]); - - if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER) - vty_out (vty, "zebra route-map delay-timer %d\n", - zebra_rmap_update_timer); -} - -void -zebra_route_map_init () -{ - install_element (CONFIG_NODE, &ip_protocol_cmd); - install_element (CONFIG_NODE, &no_ip_protocol_cmd); - install_element (VIEW_NODE, &show_ip_protocol_cmd); - install_element (CONFIG_NODE, &ipv6_protocol_cmd); - install_element (CONFIG_NODE, &no_ipv6_protocol_cmd); - install_element (VIEW_NODE, &show_ipv6_protocol_cmd); - install_element (CONFIG_NODE, &ip_protocol_nht_rmap_cmd); - install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd); - install_element (VIEW_NODE, &show_ip_protocol_nht_cmd); - install_element (CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd); - install_element (CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd); - install_element (VIEW_NODE, &show_ipv6_protocol_nht_cmd); - install_element (CONFIG_NODE, &zebra_route_map_timer_cmd); - install_element (CONFIG_NODE, &no_zebra_route_map_timer_cmd); - - route_map_init (); - - route_map_add_hook (zebra_route_map_add); - route_map_delete_hook (zebra_route_map_delete); - route_map_event_hook (zebra_route_map_event); - - route_map_match_interface_hook (generic_match_add); - route_map_no_match_interface_hook (generic_match_delete); - - route_map_match_ip_address_hook (generic_match_add); - route_map_no_match_ip_address_hook (generic_match_delete); - - route_map_match_ip_address_prefix_list_hook (generic_match_add); - route_map_no_match_ip_address_prefix_list_hook (generic_match_delete); - - route_map_match_ip_next_hop_hook (generic_match_add); - route_map_no_match_ip_next_hop_hook (generic_match_delete); - - route_map_match_ip_next_hop_prefix_list_hook (generic_match_add); - route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete); - - route_map_match_tag_hook (generic_match_add); - route_map_no_match_tag_hook (generic_match_delete); - - route_map_install_match (&route_match_tag_cmd); - route_map_install_match (&route_match_interface_cmd); - route_map_install_match (&route_match_ip_next_hop_cmd); - route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd); - route_map_install_match (&route_match_ip_address_cmd); - route_map_install_match (&route_match_ip_address_prefix_list_cmd); - route_map_install_match (&route_match_ip_address_prefix_len_cmd); - route_map_install_match (&route_match_ip_nexthop_prefix_len_cmd); - route_map_install_match (&route_match_source_protocol_cmd); -/* */ - route_map_install_set (&route_set_src_cmd); -/* */ - install_element (RMAP_NODE, &match_ip_nexthop_prefix_len_cmd); - install_element (RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd); - install_element (RMAP_NODE, &match_ip_address_prefix_len_cmd); - install_element (RMAP_NODE, &no_match_ip_address_prefix_len_cmd); - install_element (RMAP_NODE, &match_source_protocol_cmd); - install_element (RMAP_NODE, &no_match_source_protocol_cmd); - /* */ - install_element (RMAP_NODE, &set_src_cmd); - install_element (RMAP_NODE, &no_set_src_cmd); +void zebra_routemap_config_write_protocol(struct vty *vty) +{ + int i; + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (proto_rm[AFI_IP][i]) + vty_out(vty, "ip protocol %s route-map %s\n", + zebra_route_string(i), proto_rm[AFI_IP][i]); + + if (proto_rm[AFI_IP6][i]) + vty_out(vty, "ipv6 protocol %s route-map %s\n", + zebra_route_string(i), proto_rm[AFI_IP6][i]); + + if (nht_rm[AFI_IP][i]) + vty_out(vty, "ip nht %s route-map %s\n", + zebra_route_string(i), nht_rm[AFI_IP][i]); + + if (nht_rm[AFI_IP6][i]) + vty_out(vty, "ipv6 nht %s route-map %s\n", + zebra_route_string(i), nht_rm[AFI_IP6][i]); + } + + if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX]) + vty_out(vty, "ip protocol %s route-map %s\n", "any", + proto_rm[AFI_IP][ZEBRA_ROUTE_MAX]); + + if (proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX]) + vty_out(vty, "ipv6 protocol %s route-map %s\n", "any", + proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX]); + + if (nht_rm[AFI_IP][ZEBRA_ROUTE_MAX]) + vty_out(vty, "ip nht %s route-map %s\n", "any", + nht_rm[AFI_IP][ZEBRA_ROUTE_MAX]); + + if (nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX]) + vty_out(vty, "ipv6 nht %s route-map %s\n", "any", + nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX]); + + if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER) + vty_out(vty, "zebra route-map delay-timer %d\n", + zebra_rmap_update_timer); +} + +void zebra_route_map_init() +{ + install_element(CONFIG_NODE, &ip_protocol_cmd); + install_element(CONFIG_NODE, &no_ip_protocol_cmd); + install_element(VIEW_NODE, &show_ip_protocol_cmd); + install_element(CONFIG_NODE, &ipv6_protocol_cmd); + install_element(CONFIG_NODE, &no_ipv6_protocol_cmd); + install_element(VIEW_NODE, &show_ipv6_protocol_cmd); + install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd); + install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd); + install_element(VIEW_NODE, &show_ip_protocol_nht_cmd); + install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd); + install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd); + install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd); + install_element(CONFIG_NODE, &zebra_route_map_timer_cmd); + install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd); + + route_map_init(); + + route_map_add_hook(zebra_route_map_add); + route_map_delete_hook(zebra_route_map_delete); + route_map_event_hook(zebra_route_map_event); + + route_map_match_interface_hook(generic_match_add); + route_map_no_match_interface_hook(generic_match_delete); + + route_map_match_ip_address_hook(generic_match_add); + route_map_no_match_ip_address_hook(generic_match_delete); + + route_map_match_ip_address_prefix_list_hook(generic_match_add); + route_map_no_match_ip_address_prefix_list_hook(generic_match_delete); + + route_map_match_ip_next_hop_hook(generic_match_add); + route_map_no_match_ip_next_hop_hook(generic_match_delete); + + route_map_match_ip_next_hop_prefix_list_hook(generic_match_add); + route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete); + + route_map_match_tag_hook(generic_match_add); + route_map_no_match_tag_hook(generic_match_delete); + + route_map_install_match(&route_match_tag_cmd); + route_map_install_match(&route_match_interface_cmd); + route_map_install_match(&route_match_ip_next_hop_cmd); + route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd); + route_map_install_match(&route_match_ip_address_cmd); + route_map_install_match(&route_match_ip_address_prefix_list_cmd); + route_map_install_match(&route_match_ip_address_prefix_len_cmd); + route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd); + route_map_install_match(&route_match_source_protocol_cmd); + /* */ + route_map_install_set(&route_set_src_cmd); + /* */ + install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd); + install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd); + install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd); + install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd); + install_element(RMAP_NODE, &match_source_protocol_cmd); + install_element(RMAP_NODE, &no_match_source_protocol_cmd); + /* */ + install_element(RMAP_NODE, &set_src_cmd); + install_element(RMAP_NODE, &no_set_src_cmd); } diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h index ac9cc40ef..1f95c7f83 100644 --- a/zebra/zebra_routemap.h +++ b/zebra/zebra_routemap.h @@ -23,28 +23,25 @@ #define __ZEBRA_ROUTEMAP_H__ extern void zebra_routemap_config_write_protocol(struct vty *vty); -extern char *zebra_get_import_table_route_map (afi_t afi, uint32_t table); -extern void zebra_add_import_table_route_map (afi_t afi, const char *rmap_name, uint32_t table); -extern void zebra_del_import_table_route_map (afi_t afi, uint32_t table); +extern char *zebra_get_import_table_route_map(afi_t afi, uint32_t table); +extern void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name, + uint32_t table); +extern void zebra_del_import_table_route_map(afi_t afi, uint32_t table); extern void zebra_route_map_write_delay_timer(struct vty *); -extern route_map_result_t zebra_import_table_route_map_check (int family, int rib_type, - struct prefix *p, - struct nexthop *nexthop, - vrf_id_t vrf_id, - route_tag_t tag, - const char *rmap_name); -extern route_map_result_t zebra_route_map_check (int family, int rib_type, - struct prefix *p, - struct nexthop *nexthop, - vrf_id_t vrf_id, - route_tag_t tag); -extern route_map_result_t zebra_nht_route_map_check (int family, - int client_proto, - struct prefix *p, - struct route_entry *, - struct nexthop *nexthop); +extern route_map_result_t +zebra_import_table_route_map_check(int family, int rib_type, struct prefix *p, + struct nexthop *nexthop, vrf_id_t vrf_id, + route_tag_t tag, const char *rmap_name); +extern route_map_result_t zebra_route_map_check(int family, int rib_type, + struct prefix *p, + struct nexthop *nexthop, + vrf_id_t vrf_id, + route_tag_t tag); +extern route_map_result_t +zebra_nht_route_map_check(int family, int client_proto, struct prefix *p, + struct route_entry *, struct nexthop *nexthop); #endif diff --git a/zebra/zebra_snmp.c b/zebra/zebra_snmp.c index bb1cee784..4d6ba566c 100644 --- a/zebra/zebra_snmp.c +++ b/zebra/zebra_snmp.c @@ -86,510 +86,497 @@ #define IPADDRESS ASN_IPADDRESS #define OBJECTIDENTIFIER ASN_OBJECT_ID -static oid ipfw_oid [] = { IPFWMIB }; +static oid ipfw_oid[] = {IPFWMIB}; /* Hook functions. */ -static u_char * ipFwNumber (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -static u_char * ipFwTable (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -static u_char * ipCidrNumber (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -static u_char * ipCidrTable (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); - -static struct variable zebra_variables[] = - { - {0, GAUGE32, RONLY, ipFwNumber, 1, {1}}, - {IPFORWARDDEST, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 1}}, - {IPFORWARDMASK, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 2}}, - {IPFORWARDPOLICY, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 3}}, - {IPFORWARDNEXTHOP, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 4}}, - {IPFORWARDIFINDEX, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 5}}, - {IPFORWARDTYPE, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 6}}, - {IPFORWARDPROTO, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 7}}, - {IPFORWARDAGE, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 8}}, - {IPFORWARDINFO, OBJECTIDENTIFIER, RONLY, ipFwTable, 3, {2, 1, 9}}, - {IPFORWARDNEXTHOPAS, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 10}}, - {IPFORWARDMETRIC1, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 11}}, - {IPFORWARDMETRIC2, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 12}}, - {IPFORWARDMETRIC3, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 13}}, - {IPFORWARDMETRIC4, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 14}}, - {IPFORWARDMETRIC5, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 15}}, - {0, GAUGE32, RONLY, ipCidrNumber, 1, {3}}, - {IPCIDRROUTEDEST, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 1}}, - {IPCIDRROUTEMASK, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 2}}, - {IPCIDRROUTETOS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 3}}, - {IPCIDRROUTENEXTHOP, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 4}}, - {IPCIDRROUTEIFINDEX, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 5}}, - {IPCIDRROUTETYPE, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 6}}, - {IPCIDRROUTEPROTO, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 7}}, - {IPCIDRROUTEAGE, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 8}}, - {IPCIDRROUTEINFO, OBJECTIDENTIFIER, RONLY, ipCidrTable, 3, {4, 1, 9}}, - {IPCIDRROUTENEXTHOPAS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 10}}, - {IPCIDRROUTEMETRIC1, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 11}}, - {IPCIDRROUTEMETRIC2, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 12}}, - {IPCIDRROUTEMETRIC3, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 13}}, - {IPCIDRROUTEMETRIC4, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 14}}, - {IPCIDRROUTEMETRIC5, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 15}}, - {IPCIDRROUTESTATUS, ROWSTATUS, RONLY, ipCidrTable, 3, {4, 1, 16}} - }; - - -static u_char * -ipFwNumber (struct variable *v, oid objid[], size_t *objid_len, - int exact, size_t *val_len, WriteMethod **write_method) +static u_char *ipFwNumber(struct variable *, oid[], size_t *, int, size_t *, + WriteMethod **); +static u_char *ipFwTable(struct variable *, oid[], size_t *, int, size_t *, + WriteMethod **); +static u_char *ipCidrNumber(struct variable *, oid[], size_t *, int, size_t *, + WriteMethod **); +static u_char *ipCidrTable(struct variable *, oid[], size_t *, int, size_t *, + WriteMethod **); + +static struct variable zebra_variables[] = { + {0, GAUGE32, RONLY, ipFwNumber, 1, {1}}, + {IPFORWARDDEST, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 1}}, + {IPFORWARDMASK, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 2}}, + {IPFORWARDPOLICY, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 3}}, + {IPFORWARDNEXTHOP, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 4}}, + {IPFORWARDIFINDEX, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 5}}, + {IPFORWARDTYPE, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 6}}, + {IPFORWARDPROTO, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 7}}, + {IPFORWARDAGE, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 8}}, + {IPFORWARDINFO, OBJECTIDENTIFIER, RONLY, ipFwTable, 3, {2, 1, 9}}, + {IPFORWARDNEXTHOPAS, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 10}}, + {IPFORWARDMETRIC1, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 11}}, + {IPFORWARDMETRIC2, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 12}}, + {IPFORWARDMETRIC3, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 13}}, + {IPFORWARDMETRIC4, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 14}}, + {IPFORWARDMETRIC5, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 15}}, + {0, GAUGE32, RONLY, ipCidrNumber, 1, {3}}, + {IPCIDRROUTEDEST, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 1}}, + {IPCIDRROUTEMASK, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 2}}, + {IPCIDRROUTETOS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 3}}, + {IPCIDRROUTENEXTHOP, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 4}}, + {IPCIDRROUTEIFINDEX, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 5}}, + {IPCIDRROUTETYPE, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 6}}, + {IPCIDRROUTEPROTO, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 7}}, + {IPCIDRROUTEAGE, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 8}}, + {IPCIDRROUTEINFO, OBJECTIDENTIFIER, RONLY, ipCidrTable, 3, {4, 1, 9}}, + {IPCIDRROUTENEXTHOPAS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 10}}, + {IPCIDRROUTEMETRIC1, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 11}}, + {IPCIDRROUTEMETRIC2, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 12}}, + {IPCIDRROUTEMETRIC3, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 13}}, + {IPCIDRROUTEMETRIC4, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 14}}, + {IPCIDRROUTEMETRIC5, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 15}}, + {IPCIDRROUTESTATUS, ROWSTATUS, RONLY, ipCidrTable, 3, {4, 1, 16}}}; + + +static u_char *ipFwNumber(struct variable *v, oid objid[], size_t *objid_len, + int exact, size_t *val_len, + WriteMethod **write_method) { - static int result; - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - - if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED) - return NULL; - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); - if (! table) - return NULL; - - /* Return number of routing entries. */ - result = 0; - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RE (rn, re) - result++; - - return (u_char *)&result; + static int result; + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + + if (smux_header_generic(v, objid, objid_len, exact, val_len, + write_method) + == MATCH_FAILED) + return NULL; + + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (!table) + return NULL; + + /* Return number of routing entries. */ + result = 0; + for (rn = route_top(table); rn; rn = route_next(rn)) + RNODE_FOREACH_RE(rn, re) + result++; + + return (u_char *)&result; } -static u_char * -ipCidrNumber (struct variable *v, oid objid[], size_t *objid_len, - int exact, size_t *val_len, WriteMethod **write_method) +static u_char *ipCidrNumber(struct variable *v, oid objid[], size_t *objid_len, + int exact, size_t *val_len, + WriteMethod **write_method) { - static int result; - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - - if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED) - return NULL; - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); - if (! table) - return 0; - - /* Return number of routing entries. */ - result = 0; - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RE (rn, re) - result++; - - return (u_char *)&result; + static int result; + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + + if (smux_header_generic(v, objid, objid_len, exact, val_len, + write_method) + == MATCH_FAILED) + return NULL; + + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (!table) + return 0; + + /* Return number of routing entries. */ + result = 0; + for (rn = route_top(table); rn; rn = route_next(rn)) + RNODE_FOREACH_RE(rn, re) + result++; + + return (u_char *)&result; } -static int -in_addr_cmp(u_char *p1, u_char *p2) +static int in_addr_cmp(u_char *p1, u_char *p2) { - int i; - - for (i=0; i<4; i++) - { - if (*p1 < *p2) - return -1; - if (*p1 > *p2) - return 1; - p1++; p2++; - } - return 0; + int i; + + for (i = 0; i < 4; i++) { + if (*p1 < *p2) + return -1; + if (*p1 > *p2) + return 1; + p1++; + p2++; + } + return 0; } -static int -in_addr_add(u_char *p, int num) +static int in_addr_add(u_char *p, int num) { - int i, ip0; - - ip0 = *p; - p += 4; - for (i = 3; 0 <= i; i--) { - p--; - if (*p + num > 255) { - *p += num; - num = 1; - } else { - *p += num; - return 1; - } - } - if (ip0 > *p) { - /* ip + num > 0xffffffff */ - return 0; - } - - return 1; -} + int i, ip0; + + ip0 = *p; + p += 4; + for (i = 3; 0 <= i; i--) { + p--; + if (*p + num > 255) { + *p += num; + num = 1; + } else { + *p += num; + return 1; + } + } + if (ip0 > *p) { + /* ip + num > 0xffffffff */ + return 0; + } -static int -proto_trans(int type) -{ - switch (type) - { - case ZEBRA_ROUTE_SYSTEM: - return 1; /* other */ - case ZEBRA_ROUTE_KERNEL: - return 1; /* other */ - case ZEBRA_ROUTE_CONNECT: - return 2; /* local interface */ - case ZEBRA_ROUTE_STATIC: - return 3; /* static route */ - case ZEBRA_ROUTE_RIP: - return 8; /* rip */ - case ZEBRA_ROUTE_RIPNG: - return 1; /* shouldn't happen */ - case ZEBRA_ROUTE_OSPF: - return 13; /* ospf */ - case ZEBRA_ROUTE_OSPF6: - return 1; /* shouldn't happen */ - case ZEBRA_ROUTE_BGP: - return 14; /* bgp */ - default: - return 1; /* other */ - } + return 1; } -static void -check_replace(struct route_node *np2, struct route_entry *re2, - struct route_node **np, struct route_entry **re) +static int proto_trans(int type) { - int proto, proto2; - - if (!*np) - { - *np = np2; - *re = re2; - return; - } - - if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0) - return; - if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0) - { - *np = np2; - *re = re2; - return; - } - - proto = proto_trans((*re)->type); - proto2 = proto_trans(re2->type); - - if (proto2 > proto) - return; - if (proto2 < proto) - { - *np = np2; - *re = re2; - return; - } - - if (in_addr_cmp((u_char *)&(*re)->nexthop->gate.ipv4, - (u_char *)&re2->nexthop->gate.ipv4) <= 0) - return; - - *np = np2; - *re = re2; - return; + switch (type) { + case ZEBRA_ROUTE_SYSTEM: + return 1; /* other */ + case ZEBRA_ROUTE_KERNEL: + return 1; /* other */ + case ZEBRA_ROUTE_CONNECT: + return 2; /* local interface */ + case ZEBRA_ROUTE_STATIC: + return 3; /* static route */ + case ZEBRA_ROUTE_RIP: + return 8; /* rip */ + case ZEBRA_ROUTE_RIPNG: + return 1; /* shouldn't happen */ + case ZEBRA_ROUTE_OSPF: + return 13; /* ospf */ + case ZEBRA_ROUTE_OSPF6: + return 1; /* shouldn't happen */ + case ZEBRA_ROUTE_BGP: + return 14; /* bgp */ + default: + return 1; /* other */ + } } -static void -get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len, - int exact, struct route_node **np, struct route_entry **re) +static void check_replace(struct route_node *np2, struct route_entry *re2, + struct route_node **np, struct route_entry **re) { - struct in_addr dest; - struct route_table *table; - struct route_node *np2; - struct route_entry *re2; - int proto; - int policy; - struct in_addr nexthop; - u_char *pnt; - int i; + int proto, proto2; - /* Init index variables */ + if (!*np) { + *np = np2; + *re = re2; + return; + } - pnt = (u_char *) &dest; - for (i = 0; i < 4; i++) - *pnt++ = 0; + if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0) + return; + if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0) { + *np = np2; + *re = re2; + return; + } - pnt = (u_char *) &nexthop; - for (i = 0; i < 4; i++) - *pnt++ = 0; + proto = proto_trans((*re)->type); + proto2 = proto_trans(re2->type); - proto = 0; - policy = 0; - - /* Init return variables */ + if (proto2 > proto) + return; + if (proto2 < proto) { + *np = np2; + *re = re2; + return; + } - *np = NULL; - *re = NULL; + if (in_addr_cmp((u_char *)&(*re)->nexthop->gate.ipv4, + (u_char *)&re2->nexthop->gate.ipv4) + <= 0) + return; - /* Short circuit exact matches of wrong length */ + *np = np2; + *re = re2; + return; +} - if (exact && (*objid_len != (unsigned) v->namelen + 10)) - return; +static void get_fwtable_route_node(struct variable *v, oid objid[], + size_t *objid_len, int exact, + struct route_node **np, + struct route_entry **re) +{ + struct in_addr dest; + struct route_table *table; + struct route_node *np2; + struct route_entry *re2; + int proto; + int policy; + struct in_addr nexthop; + u_char *pnt; + int i; + + /* Init index variables */ + + pnt = (u_char *)&dest; + for (i = 0; i < 4; i++) + *pnt++ = 0; - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); - if (! table) - return; + pnt = (u_char *)&nexthop; + for (i = 0; i < 4; i++) + *pnt++ = 0; - /* Get INDEX information out of OID. - * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop - */ + proto = 0; + policy = 0; - if (*objid_len > (unsigned) v->namelen) - oid2in_addr (objid + v->namelen, MIN(4U, *objid_len - v->namelen), &dest); + /* Init return variables */ - if (*objid_len > (unsigned) v->namelen + 4) - proto = objid[v->namelen + 4]; + *np = NULL; + *re = NULL; - if (*objid_len > (unsigned) v->namelen + 5) - policy = objid[v->namelen + 5]; + /* Short circuit exact matches of wrong length */ - if (*objid_len > (unsigned) v->namelen + 6) - oid2in_addr (objid + v->namelen + 6, MIN(4U, *objid_len - v->namelen - 6), - &nexthop); + if (exact && (*objid_len != (unsigned)v->namelen + 10)) + return; - /* Apply GETNEXT on not exact search */ + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (!table) + return; - if (!exact && (*objid_len >= (unsigned) v->namelen + 10)) - { - if (! in_addr_add((u_char *) &nexthop, 1)) - return; - } + /* Get INDEX information out of OID. + * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop + */ - /* For exact: search matching entry in rib table. */ + if (*objid_len > (unsigned)v->namelen) + oid2in_addr(objid + v->namelen, + MIN(4U, *objid_len - v->namelen), &dest); - if (exact) - { - if (policy) /* Not supported (yet?) */ - return; - for (*np = route_top (table); *np; *np = route_next (*np)) - { - if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest)) - { - RNODE_FOREACH_RE (*np, *re) - { - if (!in_addr_cmp((u_char *)&(*re)->nexthop->gate.ipv4, - (u_char *)&nexthop)) - if (proto == proto_trans((*re)->type)) - return; + if (*objid_len > (unsigned)v->namelen + 4) + proto = objid[v->namelen + 4]; + + if (*objid_len > (unsigned)v->namelen + 5) + policy = objid[v->namelen + 5]; + + if (*objid_len > (unsigned)v->namelen + 6) + oid2in_addr(objid + v->namelen + 6, + MIN(4U, *objid_len - v->namelen - 6), &nexthop); + + /* Apply GETNEXT on not exact search */ + + if (!exact && (*objid_len >= (unsigned)v->namelen + 10)) { + if (!in_addr_add((u_char *)&nexthop, 1)) + return; + } + + /* For exact: search matching entry in rib table. */ + + if (exact) { + if (policy) /* Not supported (yet?) */ + return; + for (*np = route_top(table); *np; *np = route_next(*np)) { + if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest)) { + RNODE_FOREACH_RE(*np, *re) + { + if (!in_addr_cmp((u_char *)&(*re) + ->nexthop->gate + .ipv4, + (u_char *)&nexthop)) + if (proto + == proto_trans((*re)->type)) + return; + } + } } - } + return; } - return; - } - - /* Search next best entry */ - - for (np2 = route_top (table); np2; np2 = route_next (np2)) - { - - /* Check destination first */ - if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0) - RNODE_FOREACH_RE (np2, re2) - check_replace(np2, re2, np, re); - - if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0) - { /* have to look at each re individually */ - RNODE_FOREACH_RE (np2, re2) - { - int proto2, policy2; - - proto2 = proto_trans(re2->type); - policy2 = 0; - - if ((policy < policy2) - || ((policy == policy2) && (proto < proto2)) - || ((policy == policy2) && (proto == proto2) - && (in_addr_cmp((u_char *)&re2->nexthop->gate.ipv4, - (u_char *) &nexthop) >= 0) - )) + + /* Search next best entry */ + + for (np2 = route_top(table); np2; np2 = route_next(np2)) { + + /* Check destination first */ + if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0) + RNODE_FOREACH_RE(np2, re2) check_replace(np2, re2, np, re); - } + + if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) + == 0) { /* have to look at each re individually */ + RNODE_FOREACH_RE(np2, re2) + { + int proto2, policy2; + + proto2 = proto_trans(re2->type); + policy2 = 0; + + if ((policy < policy2) + || ((policy == policy2) && (proto < proto2)) + || ((policy == policy2) && (proto == proto2) + && (in_addr_cmp((u_char *)&re2->nexthop + ->gate.ipv4, + (u_char *)&nexthop) + >= 0))) + check_replace(np2, re2, np, re); + } + } } - } - if (!*re) - return; + if (!*re) + return; - policy = 0; - proto = proto_trans((*re)->type); + policy = 0; + proto = proto_trans((*re)->type); - *objid_len = v->namelen + 10; - pnt = (u_char *) &(*np)->p.u.prefix; - for (i = 0; i < 4; i++) - objid[v->namelen + i] = *pnt++; + *objid_len = v->namelen + 10; + pnt = (u_char *)&(*np)->p.u.prefix; + for (i = 0; i < 4; i++) + objid[v->namelen + i] = *pnt++; - objid[v->namelen + 4] = proto; - objid[v->namelen + 5] = policy; + objid[v->namelen + 4] = proto; + objid[v->namelen + 5] = policy; - { - struct nexthop *nexthop; + { + struct nexthop *nexthop; - nexthop = (*re)->nexthop; - if (nexthop) - { - pnt = (u_char *) &nexthop->gate.ipv4; - for (i = 0; i < 4; i++) - objid[i + v->namelen + 6] = *pnt++; - } - } + nexthop = (*re)->nexthop; + if (nexthop) { + pnt = (u_char *)&nexthop->gate.ipv4; + for (i = 0; i < 4; i++) + objid[i + v->namelen + 6] = *pnt++; + } + } - return; + return; } -static u_char * -ipFwTable (struct variable *v, oid objid[], size_t *objid_len, - int exact, size_t *val_len, WriteMethod **write_method) +static u_char *ipFwTable(struct variable *v, oid objid[], size_t *objid_len, + int exact, size_t *val_len, WriteMethod **write_method) { - struct route_node *np; - struct route_entry *re; - static int result; - static int resarr[2]; - static struct in_addr netmask; - struct nexthop *nexthop; - - if (smux_header_table(v, objid, objid_len, exact, val_len, write_method) - == MATCH_FAILED) - return NULL; - - get_fwtable_route_node(v, objid, objid_len, exact, &np, &re); - if (!np) - return NULL; - - nexthop = re->nexthop; - if (! nexthop) - return NULL; - - switch (v->magic) - { - case IPFORWARDDEST: - *val_len = 4; - return &np->p.u.prefix; - break; - case IPFORWARDMASK: - masklen2ip(np->p.prefixlen, &netmask); - *val_len = 4; - return (u_char *)&netmask; - break; - case IPFORWARDPOLICY: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDNEXTHOP: - *val_len = 4; - return (u_char *)&nexthop->gate.ipv4; - break; - case IPFORWARDIFINDEX: - *val_len = sizeof(int); - return (u_char *)&nexthop->ifindex; - break; - case IPFORWARDTYPE: - if (nexthop->type == NEXTHOP_TYPE_IFINDEX) - result = 3; - else - result = 4; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDPROTO: - result = proto_trans(re->type); - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDAGE: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDINFO: - resarr[0] = 0; - resarr[1] = 0; - *val_len = 2 * sizeof(int); - return (u_char *)resarr; - break; - case IPFORWARDNEXTHOPAS: - result = -1; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDMETRIC1: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDMETRIC2: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDMETRIC3: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDMETRIC4: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDMETRIC5: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - default: - return NULL; - break; - } - return NULL; + struct route_node *np; + struct route_entry *re; + static int result; + static int resarr[2]; + static struct in_addr netmask; + struct nexthop *nexthop; + + if (smux_header_table(v, objid, objid_len, exact, val_len, write_method) + == MATCH_FAILED) + return NULL; + + get_fwtable_route_node(v, objid, objid_len, exact, &np, &re); + if (!np) + return NULL; + + nexthop = re->nexthop; + if (!nexthop) + return NULL; + + switch (v->magic) { + case IPFORWARDDEST: + *val_len = 4; + return &np->p.u.prefix; + break; + case IPFORWARDMASK: + masklen2ip(np->p.prefixlen, &netmask); + *val_len = 4; + return (u_char *)&netmask; + break; + case IPFORWARDPOLICY: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDNEXTHOP: + *val_len = 4; + return (u_char *)&nexthop->gate.ipv4; + break; + case IPFORWARDIFINDEX: + *val_len = sizeof(int); + return (u_char *)&nexthop->ifindex; + break; + case IPFORWARDTYPE: + if (nexthop->type == NEXTHOP_TYPE_IFINDEX) + result = 3; + else + result = 4; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDPROTO: + result = proto_trans(re->type); + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDAGE: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDINFO: + resarr[0] = 0; + resarr[1] = 0; + *val_len = 2 * sizeof(int); + return (u_char *)resarr; + break; + case IPFORWARDNEXTHOPAS: + result = -1; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDMETRIC1: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDMETRIC2: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDMETRIC3: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDMETRIC4: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDMETRIC5: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + default: + return NULL; + break; + } + return NULL; } -static u_char * -ipCidrTable (struct variable *v, oid objid[], size_t *objid_len, - int exact, size_t *val_len, WriteMethod **write_method) +static u_char *ipCidrTable(struct variable *v, oid objid[], size_t *objid_len, + int exact, size_t *val_len, + WriteMethod **write_method) { - if (smux_header_table(v, objid, objid_len, exact, val_len, write_method) - == MATCH_FAILED) - return NULL; - - switch (v->magic) - { - case IPCIDRROUTEDEST: - break; - default: - return NULL; - break; - } - return NULL; + if (smux_header_table(v, objid, objid_len, exact, val_len, write_method) + == MATCH_FAILED) + return NULL; + + switch (v->magic) { + case IPCIDRROUTEDEST: + break; + default: + return NULL; + break; + } + return NULL; } -static int -zebra_snmp_init (struct thread_master *tm) +static int zebra_snmp_init(struct thread_master *tm) { - smux_init (tm); - REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid); - return 0; + smux_init(tm); + REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid); + return 0; } -static int -zebra_snmp_module_init (void) +static int zebra_snmp_module_init(void) { - hook_register(frr_late_init, zebra_snmp_init); - return 0; + hook_register(frr_late_init, zebra_snmp_init); + return 0; } -FRR_MODULE_SETUP( - .name = "zebra_snmp", - .version = FRR_VERSION, - .description = "zebra AgentX SNMP module", - .init = zebra_snmp_module_init, -) +FRR_MODULE_SETUP(.name = "zebra_snmp", .version = FRR_VERSION, + .description = "zebra AgentX SNMP module", + .init = zebra_snmp_module_init, ) diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index 05336ca6b..ae3239516 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -36,484 +36,486 @@ #include "zebra/zebra_memory.h" /* Install static route into rib. */ -void -static_install_route (afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct static_route *si) +void static_install_route(afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, struct static_route *si) { - struct route_entry *re; - struct route_node *rn; - struct route_table *table; - struct prefix nh_p; - struct nexthop *nexthop = NULL; - - /* Lookup table. */ - table = zebra_vrf_table (afi, safi, si->vrf_id); - if (! table) - return; - - memset (&nh_p, 0, sizeof (nh_p)); - - /* Lookup existing route */ - rn = srcdest_rnode_get (table, p, src_p); - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (re->type == ZEBRA_ROUTE_STATIC && re->distance == si->distance) - break; - } - - if (re) - { - /* if tag value changed , update old value in RIB */ - if (re->tag != si->tag) - re->tag = si->tag; - - /* Same distance static route is there. Update it with new - nexthop. */ - route_unlock_node (rn); - switch (si->type) - { - case STATIC_IPV4_GATEWAY: - nexthop = route_entry_nexthop_ipv4_add (re, &si->addr.ipv4, NULL); - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = si->addr.ipv4; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IFINDEX: - nexthop = route_entry_nexthop_ifindex_add (re, si->ifindex); - break; - case STATIC_BLACKHOLE: - nexthop = route_entry_nexthop_blackhole_add (re); - break; - case STATIC_IPV6_GATEWAY: - nexthop = route_entry_nexthop_ipv6_add (re, &si->addr.ipv6); - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = si->addr.ipv6; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - nexthop = route_entry_nexthop_ipv6_ifindex_add (re, &si->addr.ipv6, - si->ifindex); - break; - } - /* Update label(s), if present. */ - if (si->snh_label.num_labels) - nexthop_add_labels (nexthop, ZEBRA_LSP_STATIC, si->snh_label.num_labels, - &si->snh_label.label[0]); - - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Modifying route rn %p, re %p (type %d)", - si->vrf_id, buf, p->prefixlen, rn, re, re->type); - } - } - /* Schedule route for processing or invoke NHT, as appropriate. */ - if (si->type == STATIC_IPV4_GATEWAY || - si->type == STATIC_IPV6_GATEWAY) - zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p); - else - rib_queue_add (rn); - } - else - { - /* This is new static route. */ - re = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - - re->type = ZEBRA_ROUTE_STATIC; - re->instance = 0; - re->distance = si->distance; - re->metric = 0; - re->mtu = 0; - re->vrf_id = si->vrf_id; - re->table = si->vrf_id ? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id : zebrad.rtm_table_default; - re->nexthop_num = 0; - re->tag = si->tag; - - switch (si->type) - { - case STATIC_IPV4_GATEWAY: - nexthop = route_entry_nexthop_ipv4_add (re, &si->addr.ipv4, NULL); - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = si->addr.ipv4; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IFINDEX: - nexthop = route_entry_nexthop_ifindex_add (re, si->ifindex); - break; - case STATIC_BLACKHOLE: - nexthop = route_entry_nexthop_blackhole_add (re); - break; - case STATIC_IPV6_GATEWAY: - nexthop = route_entry_nexthop_ipv6_add (re, &si->addr.ipv6); - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = si->addr.ipv6; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - nexthop = route_entry_nexthop_ipv6_ifindex_add (re, &si->addr.ipv6, - si->ifindex); - break; - } - /* Update label(s), if present. */ - if (si->snh_label.num_labels) - nexthop_add_labels (nexthop, ZEBRA_LSP_STATIC, si->snh_label.num_labels, - &si->snh_label.label[0]); - - /* Save the flags of this static routes (reject, blackhole) */ - re->flags = si->flags; - - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Inserting route rn %p, re %p (type %d)", - si->vrf_id, buf, p->prefixlen, rn, re, re->type); - } - } - /* Link this re to the tree. Schedule for processing or invoke NHT, - * as appropriate. - */ - if (si->type == STATIC_IPV4_GATEWAY || - si->type == STATIC_IPV6_GATEWAY) - { - rib_addnode (rn, re, 0); - zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p); - } - else - rib_addnode (rn, re, 1); - } + struct route_entry *re; + struct route_node *rn; + struct route_table *table; + struct prefix nh_p; + struct nexthop *nexthop = NULL; + + /* Lookup table. */ + table = zebra_vrf_table(afi, safi, si->vrf_id); + if (!table) + return; + + memset(&nh_p, 0, sizeof(nh_p)); + + /* Lookup existing route */ + rn = srcdest_rnode_get(table, p, src_p); + RNODE_FOREACH_RE(rn, re) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + if (re->type == ZEBRA_ROUTE_STATIC + && re->distance == si->distance) + break; + } + + if (re) { + /* if tag value changed , update old value in RIB */ + if (re->tag != si->tag) + re->tag = si->tag; + + /* Same distance static route is there. Update it with new + nexthop. */ + route_unlock_node(rn); + switch (si->type) { + case STATIC_IPV4_GATEWAY: + nexthop = route_entry_nexthop_ipv4_add( + re, &si->addr.ipv4, NULL); + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = si->addr.ipv4; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IFINDEX: + nexthop = route_entry_nexthop_ifindex_add(re, + si->ifindex); + break; + case STATIC_BLACKHOLE: + nexthop = route_entry_nexthop_blackhole_add(re); + break; + case STATIC_IPV6_GATEWAY: + nexthop = route_entry_nexthop_ipv6_add(re, + &si->addr.ipv6); + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = si->addr.ipv6; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + nexthop = route_entry_nexthop_ipv6_ifindex_add( + re, &si->addr.ipv6, si->ifindex); + break; + } + /* Update label(s), if present. */ + if (si->snh_label.num_labels) + nexthop_add_labels(nexthop, ZEBRA_LSP_STATIC, + si->snh_label.num_labels, + &si->snh_label.label[0]); + + if (IS_ZEBRA_DEBUG_RIB) { + char buf[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_RIB) { + inet_ntop(p->family, &p->u.prefix, buf, + INET6_ADDRSTRLEN); + zlog_debug( + "%u:%s/%d: Modifying route rn %p, re %p (type %d)", + si->vrf_id, buf, p->prefixlen, rn, re, + re->type); + } + } + /* Schedule route for processing or invoke NHT, as appropriate. + */ + if (si->type == STATIC_IPV4_GATEWAY + || si->type == STATIC_IPV6_GATEWAY) + zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, + RNH_NEXTHOP_TYPE, &nh_p); + else + rib_queue_add(rn); + } else { + /* This is new static route. */ + re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + + re->type = ZEBRA_ROUTE_STATIC; + re->instance = 0; + re->distance = si->distance; + re->metric = 0; + re->mtu = 0; + re->vrf_id = si->vrf_id; + re->table = + si->vrf_id + ? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id + : zebrad.rtm_table_default; + re->nexthop_num = 0; + re->tag = si->tag; + + switch (si->type) { + case STATIC_IPV4_GATEWAY: + nexthop = route_entry_nexthop_ipv4_add( + re, &si->addr.ipv4, NULL); + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = si->addr.ipv4; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IFINDEX: + nexthop = route_entry_nexthop_ifindex_add(re, + si->ifindex); + break; + case STATIC_BLACKHOLE: + nexthop = route_entry_nexthop_blackhole_add(re); + break; + case STATIC_IPV6_GATEWAY: + nexthop = route_entry_nexthop_ipv6_add(re, + &si->addr.ipv6); + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = si->addr.ipv6; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + nexthop = route_entry_nexthop_ipv6_ifindex_add( + re, &si->addr.ipv6, si->ifindex); + break; + } + /* Update label(s), if present. */ + if (si->snh_label.num_labels) + nexthop_add_labels(nexthop, ZEBRA_LSP_STATIC, + si->snh_label.num_labels, + &si->snh_label.label[0]); + + /* Save the flags of this static routes (reject, blackhole) */ + re->flags = si->flags; + + if (IS_ZEBRA_DEBUG_RIB) { + char buf[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_RIB) { + inet_ntop(p->family, &p->u.prefix, buf, + INET6_ADDRSTRLEN); + zlog_debug( + "%u:%s/%d: Inserting route rn %p, re %p (type %d)", + si->vrf_id, buf, p->prefixlen, rn, re, + re->type); + } + } + /* Link this re to the tree. Schedule for processing or invoke + * NHT, + * as appropriate. + */ + if (si->type == STATIC_IPV4_GATEWAY + || si->type == STATIC_IPV6_GATEWAY) { + rib_addnode(rn, re, 0); + zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, + RNH_NEXTHOP_TYPE, &nh_p); + } else + rib_addnode(rn, re, 1); + } } -static int -static_nexthop_same (struct nexthop *nexthop, struct static_route *si) +static int static_nexthop_same(struct nexthop *nexthop, struct static_route *si) { - if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE - && si->type == STATIC_BLACKHOLE) - return 1; - - if (nexthop->type == NEXTHOP_TYPE_IPV4 - && si->type == STATIC_IPV4_GATEWAY - && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4)) - return 1; - else if (nexthop->type == NEXTHOP_TYPE_IFINDEX - && si->type == STATIC_IFINDEX - && nexthop->ifindex == si->ifindex) - return 1; - else if (nexthop->type == NEXTHOP_TYPE_IPV6 - && si->type == STATIC_IPV6_GATEWAY - && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)) - return 1; - else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX - && si->type == STATIC_IPV6_GATEWAY_IFINDEX - && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6) - && nexthop->ifindex == si->ifindex) - return 1; - - return 0; + if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE + && si->type == STATIC_BLACKHOLE) + return 1; + + if (nexthop->type == NEXTHOP_TYPE_IPV4 + && si->type == STATIC_IPV4_GATEWAY + && IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4)) + return 1; + else if (nexthop->type == NEXTHOP_TYPE_IFINDEX + && si->type == STATIC_IFINDEX + && nexthop->ifindex == si->ifindex) + return 1; + else if (nexthop->type == NEXTHOP_TYPE_IPV6 + && si->type == STATIC_IPV6_GATEWAY + && IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6)) + return 1; + else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX + && si->type == STATIC_IPV6_GATEWAY_IFINDEX + && IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6) + && nexthop->ifindex == si->ifindex) + return 1; + + return 0; } /* Uninstall static route from RIB. */ -void -static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct static_route *si) +void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, struct static_route *si) { - struct route_node *rn; - struct route_entry *re; - struct nexthop *nexthop; - struct route_table *table; - struct prefix nh_p; - - /* Lookup table. */ - table = zebra_vrf_table (afi, safi, si->vrf_id); - if (! table) - return; - - /* Lookup existing route with type and distance. */ - rn = srcdest_rnode_lookup (table, p, src_p); - if (! rn) - return; - - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (re->type == ZEBRA_ROUTE_STATIC && re->distance == si->distance && - re->tag == si->tag) - break; - } - - if (! re) - { - route_unlock_node (rn); - return; - } - - /* Lookup nexthop. */ - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - if (static_nexthop_same (nexthop, si)) - break; - - /* Can't find nexthop. */ - if (! nexthop) - { - route_unlock_node (rn); - return; - } - - /* Check nexthop. */ - if (re->nexthop_num == 1) - rib_delnode (rn, re); - else - { - /* Mark this nexthop as inactive and reinstall the route. Then, delete - * the nexthop. There is no need to re-evaluate the route for this - * scenario. - */ - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Modifying route rn %p, re %p (type %d)", - si->vrf_id, buf, p->prefixlen, rn, re, re->type); - } - } - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - /* If there are other active nexthops, do an update. */ - if (re->nexthop_active_num > 1) - { - /* Update route in kernel if it's in fib */ - if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) - rib_install_kernel (rn, re, re); - /* Update redistribution if it's selected */ - if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) - redistribute_update (p, (struct prefix*)src_p, re, NULL); - } - else - { - /* Remove from redistribute if selected route becomes inactive */ - if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) - redistribute_delete (p, (struct prefix*)src_p, re); - /* Remove from kernel if fib route becomes inactive */ - if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) - rib_uninstall_kernel (rn, re); - } - } - - if (afi == AFI_IP) + struct route_node *rn; + struct route_entry *re; + struct nexthop *nexthop; + struct route_table *table; + struct prefix nh_p; + + /* Lookup table. */ + table = zebra_vrf_table(afi, safi, si->vrf_id); + if (!table) + return; + + /* Lookup existing route with type and distance. */ + rn = srcdest_rnode_lookup(table, p, src_p); + if (!rn) + return; + + RNODE_FOREACH_RE(rn, re) { - /* Delete the nexthop and dereg from NHT */ - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = nexthop->gate.ipv4; + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + if (re->type == ZEBRA_ROUTE_STATIC + && re->distance == si->distance && re->tag == si->tag) + break; } - else - { - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = nexthop->gate.ipv6; + + if (!re) { + route_unlock_node(rn); + return; } - route_entry_nexthop_delete (re, nexthop); - zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn); - nexthop_free (nexthop); - } - /* Unlock node. */ - route_unlock_node (rn); -} -int -static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, - struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, - const char *ifname, u_char flags, route_tag_t tag, - u_char distance, struct zebra_vrf *zvrf, - struct static_nh_label *snh_label) -{ - struct route_node *rn; - struct static_route *si; - struct static_route *pp; - struct static_route *cp; - struct static_route *update = NULL; - struct route_table *stable = zvrf->stable[afi][safi]; - - if (! stable) - return -1; - - if (!gate && - (type == STATIC_IPV4_GATEWAY || - type == STATIC_IPV6_GATEWAY || - type == STATIC_IPV6_GATEWAY_IFINDEX)) - return -1; - - if (!ifindex && - (type == STATIC_IFINDEX || - type == STATIC_IPV6_GATEWAY_IFINDEX)) - return -1; - - /* Lookup static route prefix. */ - rn = srcdest_rnode_get (stable, p, src_p); - - /* Do nothing if there is a same static route. */ - for (si = rn->info; si; si = si->next) - { - if (type == si->type - && (! gate || - ((afi == AFI_IP && IPV4_ADDR_SAME (gate, &si->addr.ipv4)) || - (afi == AFI_IP6 && IPV6_ADDR_SAME (gate, &si->addr.ipv6)))) - && (! ifindex || ifindex == si->ifindex)) - { - if ((distance == si->distance) && (tag == si->tag) && - !memcmp (&si->snh_label, snh_label, sizeof (struct static_nh_label)) && - si->flags == flags) - { - route_unlock_node (rn); - return 0; - } - else - update = si; + /* Lookup nexthop. */ + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) + if (static_nexthop_same(nexthop, si)) + break; + + /* Can't find nexthop. */ + if (!nexthop) { + route_unlock_node(rn); + return; } - } - - /* Distance or tag or label changed, delete existing first. */ - if (update) - static_delete_route (afi, safi, type, p, src_p, gate, ifindex, update->tag, - update->distance, zvrf, &update->snh_label); - - /* Make new static route structure. */ - si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route)); - - si->type = type; - si->distance = distance; - si->flags = flags; - si->tag = tag; - si->vrf_id = zvrf_id (zvrf); - si->ifindex = ifindex; - if (si->ifindex) - strcpy(si->ifname, ifname); - - switch (type) - { - case STATIC_IPV4_GATEWAY: - si->addr.ipv4 = gate->ipv4; - break; - case STATIC_IPV6_GATEWAY: - si->addr.ipv6 = gate->ipv6; - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - si->addr.ipv6 = gate->ipv6; - break; - case STATIC_IFINDEX: - break; - } - - /* Save labels, if any. */ - memcpy (&si->snh_label, snh_label, sizeof (struct static_nh_label)); - - /* Add new static route information to the tree with sort by - distance value and gateway address. */ - for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) - { - if (si->distance < cp->distance) - break; - if (si->distance > cp->distance) - continue; - if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY) - { - if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr)) - break; - if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr)) - continue; + + /* Check nexthop. */ + if (re->nexthop_num == 1) + rib_delnode(rn, re); + else { + /* Mark this nexthop as inactive and reinstall the route. Then, + * delete + * the nexthop. There is no need to re-evaluate the route for + * this + * scenario. + */ + if (IS_ZEBRA_DEBUG_RIB) { + char buf[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_RIB) { + inet_ntop(p->family, &p->u.prefix, buf, + INET6_ADDRSTRLEN); + zlog_debug( + "%u:%s/%d: Modifying route rn %p, re %p (type %d)", + si->vrf_id, buf, p->prefixlen, rn, re, + re->type); + } + } + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) { + /* If there are other active nexthops, do an update. */ + if (re->nexthop_active_num > 1) { + /* Update route in kernel if it's in fib */ + if (CHECK_FLAG(re->status, + ROUTE_ENTRY_SELECTED_FIB)) + rib_install_kernel(rn, re, re); + /* Update redistribution if it's selected */ + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) + redistribute_update( + p, (struct prefix *)src_p, re, + NULL); + } else { + /* Remove from redistribute if selected route + * becomes inactive */ + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) + redistribute_delete( + p, (struct prefix *)src_p, re); + /* Remove from kernel if fib route becomes + * inactive */ + if (CHECK_FLAG(re->status, + ROUTE_ENTRY_SELECTED_FIB)) + rib_uninstall_kernel(rn, re); + } + } + + if (afi == AFI_IP) { + /* Delete the nexthop and dereg from NHT */ + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = nexthop->gate.ipv4; + } else { + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = nexthop->gate.ipv6; + } + route_entry_nexthop_delete(re, nexthop); + zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn); + nexthop_free(nexthop); } - } - - /* Make linked list. */ - if (pp) - pp->next = si; - else - rn->info = si; - if (cp) - cp->prev = si; - si->prev = pp; - si->next = cp; - - /* Install into rib. */ - static_install_route (afi, safi, p, src_p, si); - - return 1; + /* Unlock node. */ + route_unlock_node(rn); } -int -static_delete_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, - struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, +int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, + ifindex_t ifindex, const char *ifname, u_char flags, route_tag_t tag, u_char distance, struct zebra_vrf *zvrf, struct static_nh_label *snh_label) { - struct route_node *rn; - struct static_route *si; - struct route_table *stable; - - /* Lookup table. */ - stable = zebra_vrf_static_table (afi, safi, zvrf); - if (! stable) - return -1; - - /* Lookup static route prefix. */ - rn = srcdest_rnode_lookup (stable, p, src_p); - if (! rn) - return 0; - - /* Find same static route is the tree */ - for (si = rn->info; si; si = si->next) - if (type == si->type - && (! gate || ( - (afi == AFI_IP && IPV4_ADDR_SAME (gate, &si->addr.ipv4)) || - (afi == AFI_IP6 && IPV6_ADDR_SAME (gate, &si->addr.ipv6)))) - && (! ifindex || ifindex == si->ifindex) - && (! tag || (tag == si->tag)) - && (! snh_label->num_labels || - !memcmp (&si->snh_label, snh_label, sizeof (struct static_nh_label)))) - break; - - /* Can't find static route. */ - if (! si) - { - route_unlock_node (rn); - return 0; - } - - /* Install into rib. */ - static_uninstall_route (afi, safi, p, src_p, si); - - /* Unlink static route from linked list. */ - if (si->prev) - si->prev->next = si->next; - else - rn->info = si->next; - if (si->next) - si->next->prev = si->prev; - route_unlock_node (rn); - - /* Free static route configuration. */ - XFREE (MTYPE_STATIC_ROUTE, si); - - route_unlock_node (rn); - - return 1; + struct route_node *rn; + struct static_route *si; + struct static_route *pp; + struct static_route *cp; + struct static_route *update = NULL; + struct route_table *stable = zvrf->stable[afi][safi]; + + if (!stable) + return -1; + + if (!gate && (type == STATIC_IPV4_GATEWAY || type == STATIC_IPV6_GATEWAY + || type == STATIC_IPV6_GATEWAY_IFINDEX)) + return -1; + + if (!ifindex + && (type == STATIC_IFINDEX || type == STATIC_IPV6_GATEWAY_IFINDEX)) + return -1; + + /* Lookup static route prefix. */ + rn = srcdest_rnode_get(stable, p, src_p); + + /* Do nothing if there is a same static route. */ + for (si = rn->info; si; si = si->next) { + if (type == si->type + && (!gate || ((afi == AFI_IP + && IPV4_ADDR_SAME(gate, &si->addr.ipv4)) + || (afi == AFI_IP6 + && IPV6_ADDR_SAME(gate, &si->addr.ipv6)))) + && (!ifindex || ifindex == si->ifindex)) { + if ((distance == si->distance) && (tag == si->tag) + && !memcmp(&si->snh_label, snh_label, + sizeof(struct static_nh_label)) + && si->flags == flags) { + route_unlock_node(rn); + return 0; + } else + update = si; + } + } + + /* Distance or tag or label changed, delete existing first. */ + if (update) + static_delete_route(afi, safi, type, p, src_p, gate, ifindex, + update->tag, update->distance, zvrf, + &update->snh_label); + + /* Make new static route structure. */ + si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route)); + + si->type = type; + si->distance = distance; + si->flags = flags; + si->tag = tag; + si->vrf_id = zvrf_id(zvrf); + si->ifindex = ifindex; + if (si->ifindex) + strcpy(si->ifname, ifname); + + switch (type) { + case STATIC_IPV4_GATEWAY: + si->addr.ipv4 = gate->ipv4; + break; + case STATIC_IPV6_GATEWAY: + si->addr.ipv6 = gate->ipv6; + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + si->addr.ipv6 = gate->ipv6; + break; + case STATIC_IFINDEX: + break; + } + + /* Save labels, if any. */ + memcpy(&si->snh_label, snh_label, sizeof(struct static_nh_label)); + + /* Add new static route information to the tree with sort by + distance value and gateway address. */ + for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) { + if (si->distance < cp->distance) + break; + if (si->distance > cp->distance) + continue; + if (si->type == STATIC_IPV4_GATEWAY + && cp->type == STATIC_IPV4_GATEWAY) { + if (ntohl(si->addr.ipv4.s_addr) + < ntohl(cp->addr.ipv4.s_addr)) + break; + if (ntohl(si->addr.ipv4.s_addr) + > ntohl(cp->addr.ipv4.s_addr)) + continue; + } + } + + /* Make linked list. */ + if (pp) + pp->next = si; + else + rn->info = si; + if (cp) + cp->prev = si; + si->prev = pp; + si->next = cp; + + /* Install into rib. */ + static_install_route(afi, safi, p, src_p, si); + + return 1; +} + +int static_delete_route(afi_t afi, safi_t safi, u_char type, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, + ifindex_t ifindex, route_tag_t tag, u_char distance, + struct zebra_vrf *zvrf, + struct static_nh_label *snh_label) +{ + struct route_node *rn; + struct static_route *si; + struct route_table *stable; + + /* Lookup table. */ + stable = zebra_vrf_static_table(afi, safi, zvrf); + if (!stable) + return -1; + + /* Lookup static route prefix. */ + rn = srcdest_rnode_lookup(stable, p, src_p); + if (!rn) + return 0; + + /* Find same static route is the tree */ + for (si = rn->info; si; si = si->next) + if (type == si->type + && (!gate || ((afi == AFI_IP + && IPV4_ADDR_SAME(gate, &si->addr.ipv4)) + || (afi == AFI_IP6 + && IPV6_ADDR_SAME(gate, &si->addr.ipv6)))) + && (!ifindex || ifindex == si->ifindex) + && (!tag || (tag == si->tag)) + && (!snh_label->num_labels + || !memcmp(&si->snh_label, snh_label, + sizeof(struct static_nh_label)))) + break; + + /* Can't find static route. */ + if (!si) { + route_unlock_node(rn); + return 0; + } + + /* Install into rib. */ + static_uninstall_route(afi, safi, p, src_p, si); + + /* Unlink static route from linked list. */ + if (si->prev) + si->prev->next = si->next; + else + rn->info = si->next; + if (si->next) + si->next->prev = si->prev; + route_unlock_node(rn); + + /* Free static route configuration. */ + XFREE(MTYPE_STATIC_ROUTE, si); + + route_unlock_node(rn); + + return 1; } diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h index 9f76ab5f5..91ac0a33c 100644 --- a/zebra/zebra_static.h +++ b/zebra/zebra_static.h @@ -23,99 +23,93 @@ #define __ZEBRA_STATIC_H__ /* Static route label information */ -struct static_nh_label -{ - u_int8_t num_labels; - u_int8_t reserved[3]; - mpls_label_t label[2]; +struct static_nh_label { + u_int8_t num_labels; + u_int8_t reserved[3]; + mpls_label_t label[2]; }; typedef enum { - STATIC_IFINDEX, - STATIC_IPV4_GATEWAY, - STATIC_BLACKHOLE, - STATIC_IPV6_GATEWAY, - STATIC_IPV6_GATEWAY_IFINDEX, + STATIC_IFINDEX, + STATIC_IPV4_GATEWAY, + STATIC_BLACKHOLE, + STATIC_IPV6_GATEWAY, + STATIC_IPV6_GATEWAY_IFINDEX, } zebra_static_types; /* Static route information. */ -struct static_route -{ - /* For linked list. */ - struct static_route *prev; - struct static_route *next; - - /* VRF identifier. */ - vrf_id_t vrf_id; - - /* Administrative distance. */ - u_char distance; - - /* Tag */ - route_tag_t tag; - - /* Flag for this static route's type. */ - zebra_static_types type; - - /* - * Nexthop value. - * - * Under IPv4 addr and ifindex are - * used independentyly. - * STATIC_IPV4_GATEWAY uses addr - * STATIC_IFINDEX uses ifindex - */ - union g_addr addr; - ifindex_t ifindex; - - char ifname[INTERFACE_NAMSIZ + 1]; - - /* bit flags */ - u_char flags; -/* - see ZEBRA_FLAG_REJECT - ZEBRA_FLAG_BLACKHOLE - */ - - /* Label information */ - struct static_nh_label snh_label; +struct static_route { + /* For linked list. */ + struct static_route *prev; + struct static_route *next; + + /* VRF identifier. */ + vrf_id_t vrf_id; + + /* Administrative distance. */ + u_char distance; + + /* Tag */ + route_tag_t tag; + + /* Flag for this static route's type. */ + zebra_static_types type; + + /* + * Nexthop value. + * + * Under IPv4 addr and ifindex are + * used independentyly. + * STATIC_IPV4_GATEWAY uses addr + * STATIC_IFINDEX uses ifindex + */ + union g_addr addr; + ifindex_t ifindex; + + char ifname[INTERFACE_NAMSIZ + 1]; + + /* bit flags */ + u_char flags; + /* + see ZEBRA_FLAG_REJECT + ZEBRA_FLAG_BLACKHOLE + */ + + /* Label information */ + struct static_nh_label snh_label; }; -extern void -static_install_route (afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct static_route *si); -extern void -static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct static_route *si); - -extern int -static_add_route (afi_t, safi_t safi, u_char type, struct prefix *p, - struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, - const char *ifname, u_char flags, route_tag_t tag, - u_char distance, struct zebra_vrf *zvrf, - struct static_nh_label *snh_label); - -extern int -static_delete_route (afi_t, safi_t safi, u_char type, struct prefix *p, - struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, route_tag_t tag, - u_char distance, struct zebra_vrf *zvrf, - struct static_nh_label *snh_label); - -int -zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, - const char *dest_str, const char *mask_str, - const char *gate_str, const char *flag_str, - const char *tag_str, const char *distance_str, - const char *vrf_id_str, const char *label_str); - -int -static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, - const char *src_str, - const char *gate_str, const char *ifname, - const char *flag_str, const char *tag_str, - const char *distance_str, const char *vrf_id_str, - const char *label_str); +extern void static_install_route(afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, + struct static_route *si); +extern void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, + struct static_route *si); + +extern int static_add_route(afi_t, safi_t safi, u_char type, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, + ifindex_t ifindex, const char *ifname, u_char flags, + route_tag_t tag, u_char distance, + struct zebra_vrf *zvrf, + struct static_nh_label *snh_label); + +extern int static_delete_route(afi_t, safi_t safi, u_char type, + struct prefix *p, struct prefix_ipv6 *src_p, + union g_addr *gate, ifindex_t ifindex, + route_tag_t tag, u_char distance, + struct zebra_vrf *zvrf, + struct static_nh_label *snh_label); + +int zebra_static_ipv4(struct vty *vty, safi_t safi, int add_cmd, + const char *dest_str, const char *mask_str, + const char *gate_str, const char *flag_str, + const char *tag_str, const char *distance_str, + const char *vrf_id_str, const char *label_str); + +int static_ipv6_func(struct vty *vty, int add_cmd, const char *dest_str, + const char *src_str, const char *gate_str, + const char *ifname, const char *flag_str, + const char *tag_str, const char *distance_str, + const char *vrf_id_str, const char *label_str); #endif diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index b5d6f8c06..feca13d3a 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -42,60 +42,57 @@ extern struct zebra_t zebrad; /* VRF information update. */ -static void -zebra_vrf_add_update (struct zebra_vrf *zvrf) +static void zebra_vrf_add_update(struct zebra_vrf *zvrf) { - struct listnode *node, *nnode; - struct zserv *client; + struct listnode *node, *nnode; + struct zserv *client; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_VRF_ADD %s", zvrf_name (zvrf)); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_VRF_ADD %s", zvrf_name(zvrf)); - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - zsend_vrf_add (client, zvrf); + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + zsend_vrf_add(client, zvrf); } -static void -zebra_vrf_delete_update (struct zebra_vrf *zvrf) +static void zebra_vrf_delete_update(struct zebra_vrf *zvrf) { - struct listnode *node, *nnode; - struct zserv *client; + struct listnode *node, *nnode; + struct zserv *client; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf_name (zvrf)); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf_name(zvrf)); - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - zsend_vrf_delete (client, zvrf); + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + zsend_vrf_delete(client, zvrf); } -void -zebra_vrf_update_all (struct zserv *client) +void zebra_vrf_update_all(struct zserv *client) { - struct vrf *vrf; + struct vrf *vrf; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - { - if (vrf->vrf_id) - zsend_vrf_add (client, vrf_info_lookup (vrf->vrf_id)); - } + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + { + if (vrf->vrf_id) + zsend_vrf_add(client, vrf_info_lookup(vrf->vrf_id)); + } } /* Callback upon creating a new VRF. */ -static int -zebra_vrf_new (struct vrf *vrf) +static int zebra_vrf_new(struct vrf *vrf) { - struct zebra_vrf *zvrf; + struct zebra_vrf *zvrf; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_info ("ZVRF %s with id %u", vrf->name, vrf->vrf_id); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_info("ZVRF %s with id %u", vrf->name, vrf->vrf_id); - zvrf = zebra_vrf_alloc (); - zvrf->zns = zebra_ns_lookup (NS_DEFAULT); /* Point to the global (single) NS */ - router_id_init (zvrf); - vrf->info = zvrf; - zvrf->vrf = vrf; + zvrf = zebra_vrf_alloc(); + zvrf->zns = zebra_ns_lookup( + NS_DEFAULT); /* Point to the global (single) NS */ + router_id_init(zvrf); + vrf->info = zvrf; + zvrf->vrf = vrf; - return 0; + return 0; } /* @@ -105,445 +102,430 @@ zebra_vrf_new (struct vrf *vrf) * the old ifindex and replace with new * ifindex to insert back into the table */ -void -zebra_vrf_static_route_interface_fixup (struct interface *ifp) +void zebra_vrf_static_route_interface_fixup(struct interface *ifp) { - afi_t afi; - safi_t safi; - struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id (ifp->vrf_id); - struct route_table *stable = NULL; - struct route_node *rn = NULL; - struct static_route *si = NULL; - - if (!zvrf) - return; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - stable = zvrf->stable[afi][safi]; - if (stable) - for (rn = route_top (stable); rn; rn = route_next (rn)) - { - if (rn->info) - { - si = rn->info; - if ((strcmp (si->ifname, ifp->name) == 0) && - (si->ifindex != ifp->ifindex)) - { - si->ifindex = ifp->ifindex; - static_install_route (afi, safi, &rn->p, NULL, si); - } - } - } + afi_t afi; + safi_t safi; + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); + struct route_table *stable = NULL; + struct route_node *rn = NULL; + struct static_route *si = NULL; + + if (!zvrf) + return; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + stable = zvrf->stable[afi][safi]; + if (stable) + for (rn = route_top(stable); rn; + rn = route_next(rn)) { + if (rn->info) { + si = rn->info; + if ((strcmp(si->ifname, + ifp->name) + == 0) + && (si->ifindex + != ifp->ifindex)) { + si->ifindex = + ifp->ifindex; + static_install_route( + afi, safi, + &rn->p, NULL, + si); + } + } + } + } } - } - } /* Callback upon enabling a VRF. */ -static int -zebra_vrf_enable (struct vrf *vrf) +static int zebra_vrf_enable(struct vrf *vrf) { - struct zebra_vrf *zvrf = vrf->info; - struct route_table *stable; - struct route_node *rn; - struct static_route *si; - struct interface *ifp; - afi_t afi; - safi_t safi; - - assert (zvrf); - - zebra_vrf_add_update (zvrf); - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - stable = zvrf->stable[afi][safi]; - if (! stable) - continue; - - for (rn = route_top (stable); rn; rn = route_next (rn)) - for (si = rn->info; si; si = si->next) - { - si->vrf_id = vrf->vrf_id; - if (si->ifindex) - { - ifp = if_lookup_by_name (si->ifname, si->vrf_id); - if (ifp) - si->ifindex = ifp->ifindex; - else - continue; + struct zebra_vrf *zvrf = vrf->info; + struct route_table *stable; + struct route_node *rn; + struct static_route *si; + struct interface *ifp; + afi_t afi; + safi_t safi; + + assert(zvrf); + + zebra_vrf_add_update(zvrf); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + stable = zvrf->stable[afi][safi]; + if (!stable) + continue; + + for (rn = route_top(stable); rn; rn = route_next(rn)) + for (si = rn->info; si; si = si->next) { + si->vrf_id = vrf->vrf_id; + if (si->ifindex) { + ifp = if_lookup_by_name( + si->ifname, si->vrf_id); + if (ifp) + si->ifindex = + ifp->ifindex; + else + continue; + } + static_install_route(afi, safi, &rn->p, + NULL, si); + } } - static_install_route (afi, safi, &rn->p, NULL, si); - } - } - return 0; + return 0; } /* Callback upon disabling a VRF. */ -static int -zebra_vrf_disable (struct vrf *vrf) +static int zebra_vrf_disable(struct vrf *vrf) { - struct zebra_vrf *zvrf = vrf->info; - struct route_table *stable; - struct route_node *rn; - struct static_route *si; - afi_t afi; - safi_t safi; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("VRF %s id %u is now disabled.", - zvrf_name (zvrf), zvrf_id (zvrf)); - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - stable = zvrf->stable[afi][safi]; - if (! stable) - continue; - - for (rn = route_top (stable); rn; rn = route_next (rn)) - for (si = rn->info; si; si = si->next) - static_uninstall_route(afi, safi, &rn->p, NULL, si); - } - - return 0; + struct zebra_vrf *zvrf = vrf->info; + struct route_table *stable; + struct route_node *rn; + struct static_route *si; + afi_t afi; + safi_t safi; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("VRF %s id %u is now disabled.", zvrf_name(zvrf), + zvrf_id(zvrf)); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + stable = zvrf->stable[afi][safi]; + if (!stable) + continue; + + for (rn = route_top(stable); rn; rn = route_next(rn)) + for (si = rn->info; si; si = si->next) + static_uninstall_route( + afi, safi, &rn->p, NULL, si); + } + + return 0; } -static int -zebra_vrf_delete (struct vrf *vrf) +static int zebra_vrf_delete(struct vrf *vrf) { - struct zebra_vrf *zvrf = vrf->info; - struct route_table *table; - u_int32_t table_id; - afi_t afi; - safi_t safi; - unsigned i; - - assert (zvrf); - - zebra_vrf_delete_update (zvrf); + struct zebra_vrf *zvrf = vrf->info; + struct route_table *table; + u_int32_t table_id; + afi_t afi; + safi_t safi; + unsigned i; + + assert(zvrf); + + zebra_vrf_delete_update(zvrf); + + /* uninstall everything */ + if (!CHECK_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN)) { + struct listnode *node; + struct interface *ifp; + + for (afi = AFI_IP; afi <= AFI_IP6; afi++) { + for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; + safi++) + rib_close_table(zvrf->table[afi][safi]); + + if (vrf->vrf_id == VRF_DEFAULT) + for (table_id = 0; + table_id < ZEBRA_KERNEL_TABLE_MAX; + table_id++) + if (zvrf->other_table[afi][table_id]) + rib_close_table( + zvrf->other_table + [afi] + [table_id]); + } - /* uninstall everything */ - if (! CHECK_FLAG (zvrf->flags, ZEBRA_VRF_RETAIN)) - { - struct listnode *node; - struct interface *ifp; + /* Cleanup Vxlan table and update kernel */ + zebra_vxlan_close_tables(zvrf); - for (afi = AFI_IP; afi <= AFI_IP6; afi++) - { - for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) - rib_close_table (zvrf->table[afi][safi]); + zebra_mpls_close_tables(zvrf); - if (vrf->vrf_id == VRF_DEFAULT) - for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++) - if (zvrf->other_table[afi][table_id]) - rib_close_table (zvrf->other_table[afi][table_id]); + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, ifp)) + if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); } - /* Cleanup Vxlan table and update kernel */ - zebra_vxlan_close_tables (zvrf); - - zebra_mpls_close_tables (zvrf); - - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) - if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp); - } - - /* clean-up work queues */ - for (i = 0; i < MQ_SIZE; i++) - { - struct listnode *lnode, *nnode; - struct route_node *rnode; - rib_dest_t *dest; - - for (ALL_LIST_ELEMENTS (zebrad.mq->subq[i], lnode, nnode, rnode)) - { - dest = rib_dest_from_rnode (rnode); - if (dest && rib_dest_vrf (dest) == zvrf) - { - route_unlock_node (rnode); - list_delete_node (zebrad.mq->subq[i], lnode); - zebrad.mq->size--; - } + /* clean-up work queues */ + for (i = 0; i < MQ_SIZE; i++) { + struct listnode *lnode, *nnode; + struct route_node *rnode; + rib_dest_t *dest; + + for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode, + rnode)) { + dest = rib_dest_from_rnode(rnode); + if (dest && rib_dest_vrf(dest) == zvrf) { + route_unlock_node(rnode); + list_delete_node(zebrad.mq->subq[i], lnode); + zebrad.mq->size--; + } + } } - } - /* release allocated memory */ - for (afi = AFI_IP; afi <= AFI_IP6; afi++) - { - void *table_info; + /* release allocated memory */ + for (afi = AFI_IP; afi <= AFI_IP6; afi++) { + void *table_info; - for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) - { - table = zvrf->table[afi][safi]; - table_info = table->info; - route_table_finish (table); - XFREE (MTYPE_RIB_TABLE_INFO, table_info); + for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { + table = zvrf->table[afi][safi]; + table_info = table->info; + route_table_finish(table); + XFREE(MTYPE_RIB_TABLE_INFO, table_info); + + table = zvrf->stable[afi][safi]; + route_table_finish(table); + } - table = zvrf->stable[afi][safi]; - route_table_finish (table); + for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; + table_id++) + if (zvrf->other_table[afi][table_id]) { + table = zvrf->other_table[afi][table_id]; + table_info = table->info; + route_table_finish(table); + XFREE(MTYPE_RIB_TABLE_INFO, table_info); + } + + route_table_finish(zvrf->rnh_table[afi]); + route_table_finish(zvrf->import_check_table[afi]); } + list_delete_all_node(zvrf->rid_all_sorted_list); + list_delete_all_node(zvrf->rid_lo_sorted_list); + XFREE(MTYPE_ZEBRA_VRF, zvrf); + vrf->info = NULL; - for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++) - if (zvrf->other_table[afi][table_id]) - { - table = zvrf->other_table[afi][table_id]; - table_info = table->info; - route_table_finish (table); - XFREE (MTYPE_RIB_TABLE_INFO, table_info); - } - - route_table_finish (zvrf->rnh_table[afi]); - route_table_finish (zvrf->import_check_table[afi]); - } - list_delete_all_node (zvrf->rid_all_sorted_list); - list_delete_all_node (zvrf->rid_lo_sorted_list); - XFREE (MTYPE_ZEBRA_VRF, zvrf); - vrf->info = NULL; - - return 0; + return 0; } /* Lookup the routing table in a VRF based on both VRF-Id and table-id. * NOTE: Table-id is relevant only in the Default VRF. */ -struct route_table * -zebra_vrf_table_with_table_id (afi_t afi, safi_t safi, - vrf_id_t vrf_id, u_int32_t table_id) +struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, + vrf_id_t vrf_id, + u_int32_t table_id) { - struct route_table *table = NULL; - - if (afi >= AFI_MAX || safi >= SAFI_MAX) - return NULL; - - if (vrf_id == VRF_DEFAULT) - { - if (table_id == RT_TABLE_MAIN || - table_id == zebrad.rtm_table_default) - table = zebra_vrf_table (afi, safi, vrf_id); - else - table = zebra_vrf_other_route_table (afi, table_id, vrf_id); - } - else - table = zebra_vrf_table (afi, safi, vrf_id); - - return table; + struct route_table *table = NULL; + + if (afi >= AFI_MAX || safi >= SAFI_MAX) + return NULL; + + if (vrf_id == VRF_DEFAULT) { + if (table_id == RT_TABLE_MAIN + || table_id == zebrad.rtm_table_default) + table = zebra_vrf_table(afi, safi, vrf_id); + else + table = zebra_vrf_other_route_table(afi, table_id, + vrf_id); + } else + table = zebra_vrf_table(afi, safi, vrf_id); + + return table; } -static void -zebra_rtable_node_cleanup (struct route_table *table, struct route_node *node) +static void zebra_rtable_node_cleanup(struct route_table *table, + struct route_node *node) { - struct route_entry *re, *next; + struct route_entry *re, *next; - RNODE_FOREACH_RE_SAFE (node, re, next) - rib_unlink (node, re); + RNODE_FOREACH_RE_SAFE(node, re, next) + rib_unlink(node, re); - if (node->info) - XFREE (MTYPE_RIB_DEST, node->info); + if (node->info) + XFREE(MTYPE_RIB_DEST, node->info); } -static void -zebra_stable_node_cleanup (struct route_table *table, struct route_node *node) +static void zebra_stable_node_cleanup(struct route_table *table, + struct route_node *node) { - struct static_route *si, *next; - - if (node->info) - for (si = node->info; si; si = next) - { - next = si->next; - XFREE (MTYPE_STATIC_ROUTE, si); - } + struct static_route *si, *next; + + if (node->info) + for (si = node->info; si; si = next) { + next = si->next; + XFREE(MTYPE_STATIC_ROUTE, si); + } } -static void -zebra_rnhtable_node_cleanup (struct route_table *table, struct route_node *node) +static void zebra_rnhtable_node_cleanup(struct route_table *table, + struct route_node *node) { - if (node->info) - zebra_free_rnh (node->info); + if (node->info) + zebra_free_rnh(node->info); } /* * Create a routing table for the specific AFI/SAFI in the given VRF. */ -static void -zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi) +static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi, + safi_t safi) { - rib_table_info_t *info; - struct route_table *table; - - assert (!zvrf->table[afi][safi]); - - if (afi == AFI_IP6) - table = srcdest_table_init(); - else - table = route_table_init(); - table->cleanup = zebra_rtable_node_cleanup; - zvrf->table[afi][safi] = table; - - info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info)); - info->zvrf = zvrf; - info->afi = afi; - info->safi = safi; - table->info = info; + rib_table_info_t *info; + struct route_table *table; + + assert(!zvrf->table[afi][safi]); + + if (afi == AFI_IP6) + table = srcdest_table_init(); + else + table = route_table_init(); + table->cleanup = zebra_rtable_node_cleanup; + zvrf->table[afi][safi] = table; + + info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info)); + info->zvrf = zvrf; + info->afi = afi; + info->safi = safi; + table->info = info; } /* Allocate new zebra VRF. */ -struct zebra_vrf * -zebra_vrf_alloc (void) +struct zebra_vrf *zebra_vrf_alloc(void) { - struct zebra_vrf *zvrf; - afi_t afi; - safi_t safi; - struct route_table *table; - - zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf)); - - for (afi = AFI_IP; afi <= AFI_IP6; afi++) - { - for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) - { - zebra_vrf_table_create (zvrf, afi, safi); - if (afi == AFI_IP6) - table = srcdest_table_init(); - else - table = route_table_init(); - table->cleanup = zebra_stable_node_cleanup; - zvrf->stable[afi][safi] = table; - } - - table = route_table_init(); - table->cleanup = zebra_rnhtable_node_cleanup; - zvrf->rnh_table[afi] = table; - - table = route_table_init(); - table->cleanup = zebra_rnhtable_node_cleanup; - zvrf->import_check_table[afi] = table; - } - - zebra_vxlan_init_tables (zvrf); - zebra_mpls_init_tables (zvrf); - - return zvrf; + struct zebra_vrf *zvrf; + afi_t afi; + safi_t safi; + struct route_table *table; + + zvrf = XCALLOC(MTYPE_ZEBRA_VRF, sizeof(struct zebra_vrf)); + + for (afi = AFI_IP; afi <= AFI_IP6; afi++) { + for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { + zebra_vrf_table_create(zvrf, afi, safi); + if (afi == AFI_IP6) + table = srcdest_table_init(); + else + table = route_table_init(); + table->cleanup = zebra_stable_node_cleanup; + zvrf->stable[afi][safi] = table; + } + + table = route_table_init(); + table->cleanup = zebra_rnhtable_node_cleanup; + zvrf->rnh_table[afi] = table; + + table = route_table_init(); + table->cleanup = zebra_rnhtable_node_cleanup; + zvrf->import_check_table[afi] = table; + } + + zebra_vxlan_init_tables(zvrf); + zebra_mpls_init_tables(zvrf); + + return zvrf; } /* Lookup VRF by identifier. */ -struct zebra_vrf * -zebra_vrf_lookup_by_id (vrf_id_t vrf_id) +struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id) { - return vrf_info_lookup (vrf_id); + return vrf_info_lookup(vrf_id); } /* Lookup VRF by name. */ -struct zebra_vrf * -zebra_vrf_lookup_by_name (const char *name) +struct zebra_vrf *zebra_vrf_lookup_by_name(const char *name) { - struct vrf *vrf; + struct vrf *vrf; - if (!name) - name = VRF_DEFAULT_NAME; + if (!name) + name = VRF_DEFAULT_NAME; - vrf = vrf_lookup_by_name (name); - if (vrf) - return ((struct zebra_vrf *) vrf->info); + vrf = vrf_lookup_by_name(name); + if (vrf) + return ((struct zebra_vrf *)vrf->info); - return NULL; + return NULL; } /* Lookup the routing table in an enabled VRF. */ -struct route_table * -zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id) +struct route_table *zebra_vrf_table(afi_t afi, safi_t safi, vrf_id_t vrf_id) { - struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id); + struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id); - if (!zvrf) - return NULL; + if (!zvrf) + return NULL; - if (afi >= AFI_MAX || safi >= SAFI_MAX) - return NULL; + if (afi >= AFI_MAX || safi >= SAFI_MAX) + return NULL; - return zvrf->table[afi][safi]; + return zvrf->table[afi][safi]; } /* Lookup the static routing table in a VRF. */ -struct route_table * -zebra_vrf_static_table (afi_t afi, safi_t safi, struct zebra_vrf *zvrf) +struct route_table *zebra_vrf_static_table(afi_t afi, safi_t safi, + struct zebra_vrf *zvrf) { - if (!zvrf) - return NULL; + if (!zvrf) + return NULL; - if (afi >= AFI_MAX || safi >= SAFI_MAX) - return NULL; + if (afi >= AFI_MAX || safi >= SAFI_MAX) + return NULL; - return zvrf->stable[afi][safi]; + return zvrf->stable[afi][safi]; } -struct route_table * -zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id) +struct route_table *zebra_vrf_other_route_table(afi_t afi, u_int32_t table_id, + vrf_id_t vrf_id) { - struct zebra_vrf *zvrf; - rib_table_info_t *info; - struct route_table *table; - - zvrf = vrf_info_lookup (vrf_id); - if (! zvrf) - return NULL; - - if(afi >= AFI_MAX) - return NULL; - - if (table_id >= ZEBRA_KERNEL_TABLE_MAX) - return NULL; - - if ((vrf_id == VRF_DEFAULT) && (table_id != RT_TABLE_MAIN) && (table_id != zebrad.rtm_table_default)) - { - if (zvrf->other_table[afi][table_id] == NULL) - { - table = (afi == AFI_IP6) ? srcdest_table_init() : route_table_init(); - info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info)); - info->zvrf = zvrf; - info->afi = afi; - info->safi = SAFI_UNICAST; - table->info = info; - zvrf->other_table[afi][table_id] = table; - } - - return (zvrf->other_table[afi][table_id]); - } - - return zvrf->table[afi][SAFI_UNICAST]; + struct zebra_vrf *zvrf; + rib_table_info_t *info; + struct route_table *table; + + zvrf = vrf_info_lookup(vrf_id); + if (!zvrf) + return NULL; + + if (afi >= AFI_MAX) + return NULL; + + if (table_id >= ZEBRA_KERNEL_TABLE_MAX) + return NULL; + + if ((vrf_id == VRF_DEFAULT) && (table_id != RT_TABLE_MAIN) + && (table_id != zebrad.rtm_table_default)) { + if (zvrf->other_table[afi][table_id] == NULL) { + table = (afi == AFI_IP6) ? srcdest_table_init() + : route_table_init(); + info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info)); + info->zvrf = zvrf; + info->afi = afi; + info->safi = SAFI_UNICAST; + table->info = info; + zvrf->other_table[afi][table_id] = table; + } + + return (zvrf->other_table[afi][table_id]); + } + + return zvrf->table[afi][SAFI_UNICAST]; } -static int -vrf_config_write (struct vty *vty) +static int vrf_config_write(struct vty *vty) { - struct vrf *vrf; - struct zebra_vrf *zvrf; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - zvrf = vrf->info; - if (! zvrf || strcmp (zvrf_name (zvrf), VRF_DEFAULT_NAME)) - { - vty_out (vty, "vrf %s\n", zvrf_name(zvrf)); - vty_out (vty, "!\n"); - } - } - return 0; + struct vrf *vrf; + struct zebra_vrf *zvrf; + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + zvrf = vrf->info; + if (!zvrf || strcmp(zvrf_name(zvrf), VRF_DEFAULT_NAME)) { + vty_out(vty, "vrf %s\n", zvrf_name(zvrf)); + vty_out(vty, "!\n"); + } + } + return 0; } /* Zebra VRF initialization. */ -void -zebra_vrf_init (void) +void zebra_vrf_init(void) { - vrf_init (zebra_vrf_new, - zebra_vrf_enable, - zebra_vrf_disable, - zebra_vrf_delete); + vrf_init(zebra_vrf_new, zebra_vrf_enable, zebra_vrf_disable, + zebra_vrf_delete); - vrf_cmd_init (vrf_config_write); + vrf_cmd_init(vrf_config_write); } diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 29f7df00f..eb0687bf8 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -25,117 +25,114 @@ #include <zebra/zebra_ns.h> /* MPLS (Segment Routing) global block */ -typedef struct mpls_srgb_t_ -{ - u_int32_t start_label; - u_int32_t end_label; +typedef struct mpls_srgb_t_ { + u_int32_t start_label; + u_int32_t end_label; } mpls_srgb_t; /* Routing table instance. */ -struct zebra_vrf -{ - /* Back pointer */ - struct vrf *vrf; +struct zebra_vrf { + /* Back pointer */ + struct vrf *vrf; - /* Description. */ - char *desc; + /* Description. */ + char *desc; - /* FIB identifier. */ - u_char fib_id; + /* FIB identifier. */ + u_char fib_id; - /* Flags. */ - u_int16_t flags; + /* Flags. */ + u_int16_t flags; #define ZEBRA_VRF_RIB_SCHEDULED (1 << 0) #define ZEBRA_VRF_RETAIN (2 << 0) - u_int32_t table_id; + u_int32_t table_id; - /* Routing table. */ - struct route_table *table[AFI_MAX][SAFI_MAX]; + /* Routing table. */ + struct route_table *table[AFI_MAX][SAFI_MAX]; - /* Static route configuration. */ - struct route_table *stable[AFI_MAX][SAFI_MAX]; + /* Static route configuration. */ + struct route_table *stable[AFI_MAX][SAFI_MAX]; - /* Recursive Nexthop table */ - struct route_table *rnh_table[AFI_MAX]; + /* Recursive Nexthop table */ + struct route_table *rnh_table[AFI_MAX]; - /* Import check table (used mostly by BGP */ - struct route_table *import_check_table[AFI_MAX]; + /* Import check table (used mostly by BGP */ + struct route_table *import_check_table[AFI_MAX]; - /* Routing tables off of main table for redistribute table */ - struct route_table *other_table[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; + /* Routing tables off of main table for redistribute table */ + struct route_table *other_table[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; - /* 2nd pointer type used primarily to quell a warning on - * ALL_LIST_ELEMENTS_RO - */ - struct list _rid_all_sorted_list; - struct list _rid_lo_sorted_list; - struct list *rid_all_sorted_list; - struct list *rid_lo_sorted_list; - struct prefix rid_user_assigned; + /* 2nd pointer type used primarily to quell a warning on + * ALL_LIST_ELEMENTS_RO + */ + struct list _rid_all_sorted_list; + struct list _rid_lo_sorted_list; + struct list *rid_all_sorted_list; + struct list *rid_lo_sorted_list; + struct prefix rid_user_assigned; - /* - * Back pointer to the owning namespace. - */ - struct zebra_ns *zns; + /* + * Back pointer to the owning namespace. + */ + struct zebra_ns *zns; - /* MPLS static LSP config table */ - struct hash *slsp_table; + /* MPLS static LSP config table */ + struct hash *slsp_table; - /* MPLS label forwarding table */ - struct hash *lsp_table; + /* MPLS label forwarding table */ + struct hash *lsp_table; - /* MPLS FEC binding table */ - struct route_table *fec_table[AFI_MAX]; + /* MPLS FEC binding table */ + struct route_table *fec_table[AFI_MAX]; - /* MPLS Segment Routing Global block */ - mpls_srgb_t mpls_srgb; + /* MPLS Segment Routing Global block */ + mpls_srgb_t mpls_srgb; - /* MPLS processing flags */ - u_int16_t mpls_flags; + /* MPLS processing flags */ + u_int16_t mpls_flags; #define MPLS_FLAG_SCHEDULE_LSPS (1 << 0) - /* - * VNI hash table (for EVPN). Only in default instance. - */ - struct hash *vni_table; - /* - * Whether EVPN is enabled or not. - */ - int advertise_all_vni; - - /* Route Installs */ - uint64_t installs; - uint64_t removals; - uint64_t neigh_updates; - uint64_t lsp_installs; - uint64_t lsp_removals; + /* + * VNI hash table (for EVPN). Only in default instance. + */ + struct hash *vni_table; + /* + * Whether EVPN is enabled or not. + */ + int advertise_all_vni; + + /* Route Installs */ + uint64_t installs; + uint64_t removals; + uint64_t neigh_updates; + uint64_t lsp_installs; + uint64_t lsp_removals; }; -static inline vrf_id_t -zvrf_id (struct zebra_vrf *zvrf) +static inline vrf_id_t zvrf_id(struct zebra_vrf *zvrf) { - return zvrf->vrf->vrf_id; + return zvrf->vrf->vrf_id; } -static inline const char * -zvrf_name (struct zebra_vrf *zvrf) +static inline const char *zvrf_name(struct zebra_vrf *zvrf) { - return zvrf->vrf->name; + return zvrf->vrf->name; } -struct route_table * -zebra_vrf_table_with_table_id (afi_t afi, safi_t safi, - vrf_id_t vrf_id, u_int32_t table_id); - -extern void zebra_vrf_static_route_interface_fixup (struct interface *ifp); -extern void zebra_vrf_update_all (struct zserv *client); -extern struct zebra_vrf *zebra_vrf_lookup_by_id (vrf_id_t vrf_id); -extern struct zebra_vrf *zebra_vrf_lookup_by_name (const char *); -extern struct zebra_vrf *zebra_vrf_alloc (void); -extern struct route_table *zebra_vrf_table (afi_t, safi_t, vrf_id_t); -extern struct route_table *zebra_vrf_static_table (afi_t, safi_t, struct zebra_vrf *zvrf); -extern struct route_table *zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, - vrf_id_t vrf_id); -extern void zebra_vrf_init (void); +struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, + vrf_id_t vrf_id, + u_int32_t table_id); + +extern void zebra_vrf_static_route_interface_fixup(struct interface *ifp); +extern void zebra_vrf_update_all(struct zserv *client); +extern struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id); +extern struct zebra_vrf *zebra_vrf_lookup_by_name(const char *); +extern struct zebra_vrf *zebra_vrf_alloc(void); +extern struct route_table *zebra_vrf_table(afi_t, safi_t, vrf_id_t); +extern struct route_table *zebra_vrf_static_table(afi_t, safi_t, + struct zebra_vrf *zvrf); +extern struct route_table * +zebra_vrf_other_route_table(afi_t afi, u_int32_t table_id, vrf_id_t vrf_id); +extern void zebra_vrf_init(void); #endif diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index b1da38a7b..3978664db 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -46,12 +46,13 @@ extern int allow_delete; -static int do_show_ip_route(struct vty *vty, const char *vrf_name, - afi_t afi, safi_t safi, bool use_fib, u_char use_json, - route_tag_t tag, struct prefix *longer_prefix_p, - bool supernets_only, int type, u_short ospf_instance_id); -static void vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, - int mcast); +static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, + safi_t safi, bool use_fib, u_char use_json, + route_tag_t tag, struct prefix *longer_prefix_p, + bool supernets_only, int type, + u_short ospf_instance_id); +static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, + int mcast); #define ONE_DAY_SECOND 60*60*24 #define ONE_WEEK_SECOND 60*60*24*7 @@ -60,173 +61,169 @@ static void vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, #define CMD_VNI_RANGE "(1-16777215)" /* General function for static route. */ -int -zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, - const char *dest_str, const char *mask_str, - const char *gate_str, const char *flag_str, - const char *tag_str, const char *distance_str, - const char *vrf_id_str, const char *label_str) -{ - int ret; - u_char distance; - struct prefix p; - struct in_addr gate; - struct in_addr mask; - u_char flag = 0; - route_tag_t tag = 0; - struct zebra_vrf *zvrf = NULL; - unsigned int ifindex = 0; - const char *ifname = NULL; - u_char type = STATIC_BLACKHOLE; - struct static_nh_label snh_label; - - memset (&snh_label, 0, sizeof (struct static_nh_label)); - ret = str2prefix (dest_str, &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Cisco like mask notation. */ - if (mask_str) - { - ret = inet_aton (mask_str, &mask); - if (ret == 0) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - p.prefixlen = ip_masklen (mask); - } - - /* Apply mask for given prefix. */ - apply_mask (&p); - - /* Administrative distance. */ - if (distance_str) - distance = atoi (distance_str); - else - distance = ZEBRA_STATIC_DISTANCE_DEFAULT; - - /* tag */ - if (tag_str) - tag = strtoul(tag_str, NULL, 10); - - /* VRF id */ - zvrf = zebra_vrf_lookup_by_name (vrf_id_str); - - if (!zvrf) - { - vty_out (vty, "%% vrf %s is not defined\n", vrf_id_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Labels */ - if (label_str) - { - if (!mpls_enabled) - { - vty_out (vty, - "%% MPLS not turned on in kernel, ignoring command\n"); - return CMD_WARNING_CONFIG_FAILED; - } - int rc = mpls_str2label (label_str, &snh_label.num_labels, - snh_label.label); - if (rc < 0) - { - switch (rc) { - case -1: - vty_out (vty, "%% Malformed label(s)\n"); - break; - case -2: - vty_out (vty, "%% Cannot use reserved label(s) (%d-%d)\n", - MPLS_MIN_RESERVED_LABEL,MPLS_MAX_RESERVED_LABEL); - break; - case -3: - vty_out (vty, "%% Too many labels. Enter %d or fewer\n", - MPLS_MAX_LABELS); - break; - } - return CMD_WARNING_CONFIG_FAILED; - } - } - - /* Null0 static route. */ - if ((gate_str != NULL) && (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)) - { - if (flag_str) - { - vty_out (vty, "%% can not have flag %s with Null0\n", flag_str); - return CMD_WARNING_CONFIG_FAILED; - } - if (add_cmd) - static_add_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, ifname, - ZEBRA_FLAG_BLACKHOLE, tag, distance, zvrf, &snh_label); - else - static_delete_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, tag, - distance, zvrf, &snh_label); - return CMD_SUCCESS; - } - - /* Route flags */ - if (flag_str) { - switch(flag_str[0]) { - case 'r': - case 'R': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_REJECT); - break; - case 'b': - case 'B': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE); - break; - default: - vty_out (vty, "%% Malformed flag %s \n", flag_str); - return CMD_WARNING_CONFIG_FAILED; - } - } - - if (gate_str == NULL) - { - if (add_cmd) - static_add_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, ifname, flag, - tag, distance, zvrf, &snh_label); - else - static_delete_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, tag, distance, - zvrf, &snh_label); - - return CMD_SUCCESS; - } - - /* When gateway is A.B.C.D format, gate is treated as nexthop - address other case gate is treated as interface name. */ - ret = inet_aton (gate_str, &gate); - if (!ret) - { - struct interface *ifp = if_lookup_by_name (gate_str, zvrf_id (zvrf)); - if (!ifp) - { - vty_out (vty, "%% Unknown interface: %s\n", gate_str); - ifindex = IFINDEX_DELETED; - } - else - ifindex = ifp->ifindex; - ifname = gate_str; - type = STATIC_IFINDEX; - } - else - type = STATIC_IPV4_GATEWAY; - - if (add_cmd) - static_add_route (AFI_IP, safi, type, &p, NULL, - ifindex ? NULL : (union g_addr *)&gate, ifindex, ifname, - flag, tag, distance, zvrf, &snh_label); - else - static_delete_route (AFI_IP, safi, type, &p, NULL, - ifindex ? NULL : (union g_addr *)&gate, ifindex, tag, - distance, zvrf, &snh_label); - - return CMD_SUCCESS; +int zebra_static_ipv4(struct vty *vty, safi_t safi, int add_cmd, + const char *dest_str, const char *mask_str, + const char *gate_str, const char *flag_str, + const char *tag_str, const char *distance_str, + const char *vrf_id_str, const char *label_str) +{ + int ret; + u_char distance; + struct prefix p; + struct in_addr gate; + struct in_addr mask; + u_char flag = 0; + route_tag_t tag = 0; + struct zebra_vrf *zvrf = NULL; + unsigned int ifindex = 0; + const char *ifname = NULL; + u_char type = STATIC_BLACKHOLE; + struct static_nh_label snh_label; + + memset(&snh_label, 0, sizeof(struct static_nh_label)); + ret = str2prefix(dest_str, &p); + if (ret <= 0) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Cisco like mask notation. */ + if (mask_str) { + ret = inet_aton(mask_str, &mask); + if (ret == 0) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + p.prefixlen = ip_masklen(mask); + } + + /* Apply mask for given prefix. */ + apply_mask(&p); + + /* Administrative distance. */ + if (distance_str) + distance = atoi(distance_str); + else + distance = ZEBRA_STATIC_DISTANCE_DEFAULT; + + /* tag */ + if (tag_str) + tag = strtoul(tag_str, NULL, 10); + + /* VRF id */ + zvrf = zebra_vrf_lookup_by_name(vrf_id_str); + + if (!zvrf) { + vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Labels */ + if (label_str) { + if (!mpls_enabled) { + vty_out(vty, + "%% MPLS not turned on in kernel, ignoring command\n"); + return CMD_WARNING_CONFIG_FAILED; + } + int rc = mpls_str2label(label_str, &snh_label.num_labels, + snh_label.label); + if (rc < 0) { + switch (rc) { + case -1: + vty_out(vty, "%% Malformed label(s)\n"); + break; + case -2: + vty_out(vty, + "%% Cannot use reserved label(s) (%d-%d)\n", + MPLS_MIN_RESERVED_LABEL, + MPLS_MAX_RESERVED_LABEL); + break; + case -3: + vty_out(vty, + "%% Too many labels. Enter %d or fewer\n", + MPLS_MAX_LABELS); + break; + } + return CMD_WARNING_CONFIG_FAILED; + } + } + + /* Null0 static route. */ + if ((gate_str != NULL) + && (strncasecmp(gate_str, "Null0", strlen(gate_str)) == 0)) { + if (flag_str) { + vty_out(vty, "%% can not have flag %s with Null0\n", + flag_str); + return CMD_WARNING_CONFIG_FAILED; + } + if (add_cmd) + static_add_route(AFI_IP, safi, type, &p, NULL, NULL, + ifindex, ifname, ZEBRA_FLAG_BLACKHOLE, + tag, distance, zvrf, &snh_label); + else + static_delete_route(AFI_IP, safi, type, &p, NULL, NULL, + ifindex, tag, distance, zvrf, + &snh_label); + return CMD_SUCCESS; + } + + /* Route flags */ + if (flag_str) { + switch (flag_str[0]) { + case 'r': + case 'R': /* XXX */ + SET_FLAG(flag, ZEBRA_FLAG_REJECT); + break; + case 'b': + case 'B': /* XXX */ + SET_FLAG(flag, ZEBRA_FLAG_BLACKHOLE); + break; + default: + vty_out(vty, "%% Malformed flag %s \n", flag_str); + return CMD_WARNING_CONFIG_FAILED; + } + } + + if (gate_str == NULL) { + if (add_cmd) + static_add_route(AFI_IP, safi, type, &p, NULL, NULL, + ifindex, ifname, flag, tag, distance, + zvrf, &snh_label); + else + static_delete_route(AFI_IP, safi, type, &p, NULL, NULL, + ifindex, tag, distance, zvrf, + &snh_label); + + return CMD_SUCCESS; + } + + /* When gateway is A.B.C.D format, gate is treated as nexthop + address other case gate is treated as interface name. */ + ret = inet_aton(gate_str, &gate); + if (!ret) { + struct interface *ifp = + if_lookup_by_name(gate_str, zvrf_id(zvrf)); + if (!ifp) { + vty_out(vty, "%% Unknown interface: %s\n", gate_str); + ifindex = IFINDEX_DELETED; + } else + ifindex = ifp->ifindex; + ifname = gate_str; + type = STATIC_IFINDEX; + } else + type = STATIC_IPV4_GATEWAY; + + if (add_cmd) + static_add_route(AFI_IP, safi, type, &p, NULL, + ifindex ? NULL : (union g_addr *)&gate, + ifindex, ifname, flag, tag, distance, zvrf, + &snh_label); + else + static_delete_route(AFI_IP, safi, type, &p, NULL, + ifindex ? NULL : (union g_addr *)&gate, + ifindex, tag, distance, zvrf, &snh_label); + + return CMD_SUCCESS; } /* Static unicast routes for multicast RPF lookup. */ @@ -240,11 +237,12 @@ DEFUN (ip_mroute_dist, "Nexthop interface name\n" "Distance\n") { - char *destprefix = argv[2]->arg; - char *nexthop = argv[3]->arg; - char *distance = (argc == 5) ? argv[4]->arg : NULL; + char *destprefix = argv[2]->arg; + char *nexthop = argv[3]->arg; + char *distance = (argc == 5) ? argv[4]->arg : NULL; - return zebra_static_ipv4 (vty, SAFI_MULTICAST, 1, destprefix, NULL, nexthop, NULL, NULL, distance, NULL, NULL); + return zebra_static_ipv4(vty, SAFI_MULTICAST, 1, destprefix, NULL, + nexthop, NULL, NULL, distance, NULL, NULL); } DEFUN (no_ip_mroute_dist, @@ -258,11 +256,12 @@ DEFUN (no_ip_mroute_dist, "Nexthop interface name\n" "Distance\n") { - char *destprefix = argv[3]->arg; - char *nexthop = argv[4]->arg; - char *distance = (argc == 6) ? argv[5]->arg : NULL; + char *destprefix = argv[3]->arg; + char *nexthop = argv[4]->arg; + char *distance = (argc == 6) ? argv[5]->arg : NULL; - return zebra_static_ipv4 (vty, SAFI_MULTICAST, 0, destprefix, NULL, nexthop, NULL, NULL, distance, NULL, NULL); + return zebra_static_ipv4(vty, SAFI_MULTICAST, 0, destprefix, NULL, + nexthop, NULL, NULL, distance, NULL, NULL); } DEFUN (ip_multicast_mode, @@ -277,25 +276,24 @@ DEFUN (ip_multicast_mode, "Lookup both, use entry with lower distance\n" "Lookup both, use entry with longer prefix\n") { - char *mode = argv[3]->text; - - if (strmatch (mode, "urib-only")) - multicast_mode_ipv4_set (MCAST_URIB_ONLY); - else if (strmatch (mode, "mrib-only")) - multicast_mode_ipv4_set (MCAST_MRIB_ONLY); - else if (strmatch (mode, "mrib-then-urib")) - multicast_mode_ipv4_set (MCAST_MIX_MRIB_FIRST); - else if (strmatch (mode, "lower-distance")) - multicast_mode_ipv4_set (MCAST_MIX_DISTANCE); - else if (strmatch (mode, "longer-prefix")) - multicast_mode_ipv4_set (MCAST_MIX_PFXLEN); - else - { - vty_out (vty, "Invalid mode specified\n"); - return CMD_WARNING_CONFIG_FAILED; - } + char *mode = argv[3]->text; + + if (strmatch(mode, "urib-only")) + multicast_mode_ipv4_set(MCAST_URIB_ONLY); + else if (strmatch(mode, "mrib-only")) + multicast_mode_ipv4_set(MCAST_MRIB_ONLY); + else if (strmatch(mode, "mrib-then-urib")) + multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST); + else if (strmatch(mode, "lower-distance")) + multicast_mode_ipv4_set(MCAST_MIX_DISTANCE); + else if (strmatch(mode, "longer-prefix")) + multicast_mode_ipv4_set(MCAST_MIX_PFXLEN); + else { + vty_out(vty, "Invalid mode specified\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_multicast_mode, @@ -311,8 +309,8 @@ DEFUN (no_ip_multicast_mode, "Lookup both, use entry with lower distance\n" "Lookup both, use entry with longer prefix\n") { - multicast_mode_ipv4_set (MCAST_NO_CONFIG); - return CMD_SUCCESS; + multicast_mode_ipv4_set(MCAST_NO_CONFIG); + return CMD_SUCCESS; } @@ -324,8 +322,9 @@ DEFUN (show_ip_rpf, "Display RPF information for multicast source\n" JSON_STR) { - int uj = use_json(argc, argv); - return do_show_ip_route (vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST, false, uj, 0, NULL, false, -1, 0); + int uj = use_json(argc, argv); + return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST, + false, uj, 0, NULL, false, -1, 0); } DEFUN (show_ip_rpf_addr, @@ -336,64 +335,55 @@ DEFUN (show_ip_rpf_addr, "Display RPF information for multicast source\n" "IP multicast source address (e.g. 10.0.0.0)\n") { - int idx_ipv4 = 3; - struct in_addr addr; - struct route_node *rn; - struct route_entry *re; - int ret; - - ret = inet_aton (argv[idx_ipv4]->arg, &addr); - if (ret == 0) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING; - } - - re = rib_match_ipv4_multicast (VRF_DEFAULT, addr, &rn); - - if (re) - vty_show_ip_route_detail (vty, rn, 1); - else - vty_out (vty, "%% No match for RPF lookup\n"); - - return CMD_SUCCESS; -} - -static void -zebra_vty_ip_route_tdv_helper (int argc, struct cmd_token *argv[], - int idx_curr, char **tag, - char **distance, char **vrf, char **labels) -{ - *distance = NULL; - while (idx_curr < argc) - { - if (strmatch (argv[idx_curr]->text, "tag")) - { - if (tag) - *tag = argv[idx_curr+1]->arg; - idx_curr += 2; - } - else if (strmatch (argv[idx_curr]->text, "vrf")) - { - if (vrf) - *vrf = argv[idx_curr+1]->arg; - idx_curr += 2; - } - else if (strmatch (argv[idx_curr]->text, "label")) - { - if (labels) - *labels = argv[idx_curr+1]->arg; - idx_curr += 2; - } - else - { - if (distance) - *distance = argv[idx_curr]->arg; - idx_curr++; - } - } - - return; + int idx_ipv4 = 3; + struct in_addr addr; + struct route_node *rn; + struct route_entry *re; + int ret; + + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (ret == 0) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING; + } + + re = rib_match_ipv4_multicast(VRF_DEFAULT, addr, &rn); + + if (re) + vty_show_ip_route_detail(vty, rn, 1); + else + vty_out(vty, "%% No match for RPF lookup\n"); + + return CMD_SUCCESS; +} + +static void zebra_vty_ip_route_tdv_helper(int argc, struct cmd_token *argv[], + int idx_curr, char **tag, + char **distance, char **vrf, + char **labels) +{ + *distance = NULL; + while (idx_curr < argc) { + if (strmatch(argv[idx_curr]->text, "tag")) { + if (tag) + *tag = argv[idx_curr + 1]->arg; + idx_curr += 2; + } else if (strmatch(argv[idx_curr]->text, "vrf")) { + if (vrf) + *vrf = argv[idx_curr + 1]->arg; + idx_curr += 2; + } else if (strmatch(argv[idx_curr]->text, "label")) { + if (labels) + *labels = argv[idx_curr + 1]->arg; + idx_curr += 2; + } else { + if (distance) + *distance = argv[idx_curr]->arg; + idx_curr++; + } + } + + return; } /* Static route configuration. */ @@ -411,20 +401,19 @@ DEFUN (ip_route, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4_prefixlen = 2; - int idx_ipv4_ifname_null = 3; - int idx_curr = 4; - char *tag, *distance, *vrf; + int idx_ipv4_prefixlen = 2; + int idx_ipv4_ifname_null = 3; + int idx_curr = 4; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, - argv[idx_ipv4_prefixlen]->arg, - NULL, - argv[idx_ipv4_ifname_null]->arg, - NULL, - tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, + argv[idx_ipv4_prefixlen]->arg, NULL, + argv[idx_ipv4_ifname_null]->arg, NULL, tag, + distance, vrf, NULL); } DEFUN (ip_route_flags, @@ -440,20 +429,18 @@ DEFUN (ip_route_flags, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4_prefixlen = 2; - int idx_reject_blackhole = 3; - int idx_curr = 4; - char *tag, *distance, *vrf; + int idx_ipv4_prefixlen = 2; + int idx_reject_blackhole = 3; + int idx_curr = 4; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, - argv[idx_ipv4_prefixlen]->arg, - NULL, - NULL, - argv[idx_reject_blackhole]->arg, - tag, distance, vrf, NULL); + return zebra_static_ipv4( + vty, SAFI_UNICAST, 1, argv[idx_ipv4_prefixlen]->arg, NULL, NULL, + argv[idx_reject_blackhole]->arg, tag, distance, vrf, NULL); } /* Mask as A.B.C.D format. */ @@ -472,20 +459,20 @@ DEFUN (ip_route_mask, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4 = 2; - int idx_ipv4_2 = 3; - int idx_ipv4_ifname_null = 4; - int idx_curr = 5; - char *tag, *distance, *vrf; + int idx_ipv4 = 2; + int idx_ipv4_2 = 3; + int idx_ipv4_ifname_null = 4; + int idx_curr = 5; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, - argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, - argv[idx_ipv4_ifname_null]->arg, - NULL, tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, + argv[idx_ipv4_ifname_null]->arg, NULL, tag, + distance, vrf, NULL); } DEFUN (ip_route_mask_flags, @@ -502,21 +489,20 @@ DEFUN (ip_route_mask_flags, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4 = 2; - int idx_ipv4_2 = 3; - int idx_reject_blackhole = 4; - int idx_curr = 5; - char *tag, *distance, *vrf; + int idx_ipv4 = 2; + int idx_ipv4_2 = 3; + int idx_reject_blackhole = 4; + int idx_curr = 5; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, - argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, - NULL, - argv[idx_reject_blackhole]->arg, - tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, NULL, + argv[idx_reject_blackhole]->arg, tag, distance, + vrf, NULL); } DEFUN (no_ip_route, @@ -534,20 +520,19 @@ DEFUN (no_ip_route, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4_prefixlen = 3; - int idx_ipv4_ifname_null = 4; - int idx_curr = 5; - char *tag, *distance, *vrf; + int idx_ipv4_prefixlen = 3; + int idx_ipv4_ifname_null = 4; + int idx_curr = 5; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, - argv[idx_ipv4_prefixlen]->arg, - NULL, - argv[idx_ipv4_ifname_null]->arg, - NULL, - tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, + argv[idx_ipv4_prefixlen]->arg, NULL, + argv[idx_ipv4_ifname_null]->arg, NULL, tag, + distance, vrf, NULL); } DEFUN (no_ip_route_flags, @@ -564,17 +549,17 @@ DEFUN (no_ip_route_flags, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4_prefixlen = 3; - int idx_curr = 5; - char *tag, *distance, *vrf; + int idx_ipv4_prefixlen = 3; + int idx_curr = 5; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, - argv[idx_ipv4_prefixlen]->arg, - NULL, NULL, NULL, - tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, + argv[idx_ipv4_prefixlen]->arg, NULL, NULL, + NULL, tag, distance, vrf, NULL); } DEFUN (no_ip_route_mask, @@ -593,21 +578,20 @@ DEFUN (no_ip_route_mask, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4 = 3; - int idx_ipv4_2 = 4; - int idx_ipv4_ifname_null = 5; - int idx_curr = 6; - char *tag, *distance, *vrf; + int idx_ipv4 = 3; + int idx_ipv4_2 = 4; + int idx_ipv4_ifname_null = 5; + int idx_curr = 6; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, - argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, - argv[idx_ipv4_ifname_null]->arg, - NULL, - tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, + argv[idx_ipv4_ifname_null]->arg, NULL, tag, + distance, vrf, NULL); } DEFUN (no_ip_route_mask_flags, @@ -625,592 +609,634 @@ DEFUN (no_ip_route_mask_flags, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4 = 3; - int idx_ipv4_2 = 4; - int idx_curr = 6; - char *tag, *distance, *vrf; + int idx_ipv4 = 3; + int idx_ipv4_2 = 4; + int idx_curr = 6; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, - argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, - NULL, NULL, - tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, NULL, NULL, tag, + distance, vrf, NULL); } /* New RIB. Detailed information for IPv4 route. */ -static void -vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast) -{ - struct route_entry *re; - struct nexthop *nexthop; - char buf[SRCDEST2STR_BUFFER]; - struct zebra_vrf *zvrf; - - RNODE_FOREACH_RE (rn, re) - { - const char *mcast_info = ""; - if (mcast) - { - rib_table_info_t *info = srcdest_rnode_table_info(rn); - mcast_info = (info->safi == SAFI_MULTICAST) - ? " using Multicast RIB" - : " using Unicast RIB"; - } - - vty_out (vty, "Routing entry for %s%s\n", - srcdest_rnode2str(rn, buf, sizeof(buf)), mcast_info); - vty_out (vty, " Known via \"%s", zebra_route_string (re->type)); - if (re->instance) - vty_out (vty, "[%d]", re->instance); - vty_out (vty, "\""); - vty_out (vty, ", distance %u, metric %u", re->distance, re->metric); - if (re->tag) - vty_out (vty, ", tag %d", re->tag); - if (re->mtu) - vty_out (vty, ", mtu %u", re->mtu); - if (re->vrf_id != VRF_DEFAULT) - { - zvrf = vrf_info_lookup(re->vrf_id); - vty_out (vty, ", vrf %s", zvrf_name (zvrf)); - } - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED)) - vty_out (vty, ", best"); - if (re->refcnt) - vty_out (vty, ", refcnt %ld", re->refcnt); - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, ", blackhole"); - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, ", reject"); - vty_out (vty, "\n"); - - if (re->type == ZEBRA_ROUTE_RIP - || re->type == ZEBRA_ROUTE_OSPF - || re->type == ZEBRA_ROUTE_ISIS - || re->type == ZEBRA_ROUTE_NHRP - || re->type == ZEBRA_ROUTE_TABLE - || re->type == ZEBRA_ROUTE_BGP) - { - time_t uptime; - struct tm *tm; - - uptime = time (NULL); - uptime -= re->uptime; - tm = gmtime (&uptime); - - vty_out (vty, " Last update "); - - if (uptime < ONE_DAY_SECOND) - vty_out (vty, "%02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (uptime < ONE_WEEK_SECOND) - vty_out (vty, "%dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - else - vty_out (vty, "%02dw%dd%02dh", - tm->tm_yday/7, - tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - vty_out (vty, " ago\n"); - } - - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - char addrstr[32]; - - vty_out (vty, " %c%s", - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ', - nexthop->rparent ? " " : ""); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4)); - if (nexthop->ifindex) - vty_out (vty, ", via %s", - ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out (vty, " %s", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, sizeof buf)); - if (nexthop->ifindex) - vty_out (vty, ", via %s", - ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - case NEXTHOP_TYPE_IFINDEX: - vty_out (vty, " directly connected, %s", - ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - case NEXTHOP_TYPE_BLACKHOLE: - vty_out (vty, " directly connected, Null0"); - break; - default: - break; - } - if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - vty_out (vty, " inactive"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) - vty_out (vty, " onlink"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - vty_out (vty, " (recursive)"); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nexthop->src.ipv4.s_addr) - { - if (inet_ntop(AF_INET, &nexthop->src.ipv4, addrstr, - sizeof addrstr)) - vty_out (vty, ", src %s", addrstr); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) - { - if (inet_ntop(AF_INET6, &nexthop->src.ipv6, addrstr, - sizeof addrstr)) - vty_out (vty, ", src %s", addrstr); - } - break; - default: - break; - } - - /* Label information */ - if (nexthop->nh_label && nexthop->nh_label->num_labels) - { - vty_out (vty, ", label %s", - mpls_label2str (nexthop->nh_label->num_labels, - nexthop->nh_label->label, buf, sizeof buf, 1)); - } - - vty_out (vty, "\n"); - } - vty_out (vty, "\n"); - } -} - -static void -vty_show_ip_route (struct vty *vty, struct route_node *rn, struct route_entry *re, - json_object *json) -{ - struct nexthop *nexthop; - int len = 0; - char buf[SRCDEST2STR_BUFFER]; - json_object *json_nexthops = NULL; - json_object *json_nexthop = NULL; - json_object *json_route = NULL; - json_object *json_labels = NULL; - - if (json) - { - json_route = json_object_new_object(); - json_nexthops = json_object_new_array(); - - json_object_string_add(json_route, "prefix", srcdest_rnode2str (rn, buf, sizeof buf)); - json_object_string_add(json_route, "protocol", zebra_route_string(re->type)); - - if (re->instance) - json_object_int_add(json_route, "instance", re->instance); - - if (re->vrf_id) - json_object_int_add(json_route, "vrfId", re->vrf_id); - - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED)) - json_object_boolean_true_add(json_route, "selected"); - - if (re->type != ZEBRA_ROUTE_CONNECT && re->type != ZEBRA_ROUTE_KERNEL) - { - json_object_int_add(json_route, "distance", re->distance); - json_object_int_add(json_route, "metric", re->metric); - } - - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_BLACKHOLE)) - json_object_boolean_true_add(json_route, "blackhole"); - - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_REJECT)) - json_object_boolean_true_add(json_route, "reject"); - - if (re->type == ZEBRA_ROUTE_RIP - || re->type == ZEBRA_ROUTE_OSPF - || re->type == ZEBRA_ROUTE_ISIS - || re->type == ZEBRA_ROUTE_NHRP - || re->type == ZEBRA_ROUTE_TABLE - || re->type == ZEBRA_ROUTE_BGP) - { - time_t uptime; - struct tm *tm; - - uptime = time (NULL); - uptime -= re->uptime; - tm = gmtime (&uptime); - - if (uptime < ONE_DAY_SECOND) - sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (uptime < ONE_WEEK_SECOND) - sprintf(buf, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, tm->tm_min); - else - sprintf(buf, "%02dw%dd%02dh", tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - - json_object_string_add(json_route, "uptime", buf); - } - - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - json_nexthop = json_object_new_object(); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - json_object_boolean_true_add(json_nexthop, "fib"); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - json_object_string_add(json_nexthop, "ip", inet_ntoa (nexthop->gate.ipv4)); - json_object_string_add(json_nexthop, "afi", "ipv4"); - - if (nexthop->ifindex) - { - json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); - json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname (nexthop->ifindex, re->vrf_id)); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - json_object_string_add(json_nexthop, "ip", inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, sizeof buf)); - json_object_string_add(json_nexthop, "afi", "ipv6"); - - if (nexthop->ifindex) - { - json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); - json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname (nexthop->ifindex, re->vrf_id)); - } - break; - - case NEXTHOP_TYPE_IFINDEX: - json_object_boolean_true_add(json_nexthop, "directlyConnected"); - json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); - json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - case NEXTHOP_TYPE_BLACKHOLE: - json_object_boolean_true_add(json_nexthop, "blackhole"); - break; - default: - break; - } - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - json_object_boolean_true_add(json_nexthop, "active"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) - json_object_boolean_true_add(json_nexthop, "onLink"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - json_object_boolean_true_add(json_nexthop, "recursive"); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nexthop->src.ipv4.s_addr) - { - if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, sizeof buf)) - json_object_string_add(json_nexthop, "source", buf); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) - { - if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, sizeof buf)) - json_object_string_add(json_nexthop, "source", buf); - } - break; - default: - break; - } - - if (nexthop->nh_label && nexthop->nh_label->num_labels) - { - json_labels = json_object_new_array(); - - for (int label_index = 0; label_index < nexthop->nh_label->num_labels; label_index++) - json_object_array_add(json_labels, json_object_new_int(nexthop->nh_label->label[label_index])); - - json_object_object_add(json_nexthop, "labels", json_labels); - } - - json_object_array_add(json_nexthops, json_nexthop); - } - - json_object_object_add(json_route, "nexthops", json_nexthops); - json_object_array_add(json, json_route); - return; - } - - /* Nexthop information. */ - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (nexthop == re->nexthop) - { - /* Prefix information. */ - len = vty_out (vty, "%c", zebra_route_char (re->type)); - if (re->instance) - len += vty_out (vty, "[%d]", re->instance); - len += vty_out (vty, "%c%c %s", - CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED) - ? '>' : ' ', - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) - ? '*' : ' ', - srcdest_rnode2str (rn, buf, sizeof buf)); - - /* Distance and metric display. */ - if (re->type != ZEBRA_ROUTE_CONNECT - && re->type != ZEBRA_ROUTE_KERNEL) - len += vty_out (vty, " [%d/%d]", re->distance, - re->metric); - } - else - vty_out (vty, " %c%*c", - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) - ? '*' : ' ', - len - 3 + (2 * nexthop_level(nexthop)), ' '); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); - if (nexthop->ifindex) - vty_out (vty, ", %s", - ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out (vty, " via %s", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, sizeof buf)); - if (nexthop->ifindex) - vty_out (vty, ", %s", - ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - - case NEXTHOP_TYPE_IFINDEX: - vty_out (vty, " is directly connected, %s", - ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - case NEXTHOP_TYPE_BLACKHOLE: - vty_out (vty, " is directly connected, Null0"); - break; - default: - break; - } - if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - vty_out (vty, " inactive"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) - vty_out (vty, " onlink"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - vty_out (vty, " (recursive)"); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nexthop->src.ipv4.s_addr) - { - if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, sizeof buf)) - vty_out (vty, ", src %s", buf); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) - { - if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, sizeof buf)) - vty_out (vty, ", src %s", buf); - } - break; - default: - break; - } - - /* Label information */ - if (nexthop->nh_label && nexthop->nh_label->num_labels) - { - vty_out (vty, ", label %s", - mpls_label2str (nexthop->nh_label->num_labels, - nexthop->nh_label->label, buf, sizeof buf, 1)); - } - - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, ", bh"); - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, ", rej"); - - if (re->type == ZEBRA_ROUTE_RIP - || re->type == ZEBRA_ROUTE_OSPF - || re->type == ZEBRA_ROUTE_ISIS - || re->type == ZEBRA_ROUTE_NHRP - || re->type == ZEBRA_ROUTE_TABLE - || re->type == ZEBRA_ROUTE_BGP) +static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, + int mcast) +{ + struct route_entry *re; + struct nexthop *nexthop; + char buf[SRCDEST2STR_BUFFER]; + struct zebra_vrf *zvrf; + + RNODE_FOREACH_RE(rn, re) { - time_t uptime; - struct tm *tm; - - uptime = time (NULL); - uptime -= re->uptime; - tm = gmtime (&uptime); - - if (uptime < ONE_DAY_SECOND) - vty_out (vty, ", %02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (uptime < ONE_WEEK_SECOND) - vty_out (vty, ", %dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - else - vty_out (vty, ", %02dw%dd%02dh", - tm->tm_yday/7, - tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - } - vty_out (vty, "\n"); - } -} - -static bool -use_fib (struct cmd_token *token) -{ - return strncmp(token->arg, "route", strlen(token->arg)); -} - -static int -do_show_ip_route (struct vty *vty, const char *vrf_name, afi_t afi, safi_t safi, - bool use_fib, u_char use_json, route_tag_t tag, - struct prefix *longer_prefix_p, bool supernets_only, - int type, u_short ospf_instance_id) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - int first = 1; - struct zebra_vrf *zvrf = NULL; - char buf[BUFSIZ]; - json_object *json = NULL; - json_object *json_prefix = NULL; - u_int32_t addr; - - if (!(zvrf = zebra_vrf_lookup_by_name (vrf_name))) - { - if (use_json) - vty_out (vty, "{}\n"); - else - vty_out (vty, "vrf %s not defined\n", vrf_name); - return CMD_SUCCESS; - } - - if (zvrf_id (zvrf) == VRF_UNKNOWN) - { - if (use_json) - vty_out (vty, "{}\n"); - else - vty_out (vty, "vrf %s inactive\n", vrf_name); - return CMD_SUCCESS; - } - - table = zebra_vrf_table (afi, safi, zvrf_id (zvrf)); - if (! table) - { - if (use_json) - vty_out (vty, "{}\n"); - return CMD_SUCCESS; - } - - if (use_json) - json = json_object_new_object(); - - /* Show all routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - { - RNODE_FOREACH_RE (rn, re) - { - if (use_fib && !CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) - continue; - - if (tag && re->tag != tag) - continue; - - if (longer_prefix_p && ! prefix_match (longer_prefix_p, &rn->p)) - continue; - - /* This can only be true when the afi is IPv4 */ - if (supernets_only) - { - addr = ntohl (rn->p.u.prefix4.s_addr); - - if (IN_CLASSC (addr) && rn->p.prefixlen >= 24) - continue; - - if (IN_CLASSB (addr) && rn->p.prefixlen >= 16) - continue; - - if (IN_CLASSA (addr) && rn->p.prefixlen >= 8) - continue; - } - - if (type && re->type != type) - continue; - - if (ospf_instance_id && (re->type != ZEBRA_ROUTE_OSPF || re->instance != ospf_instance_id)) - continue; - - if (use_json) - { - if (!json_prefix) - json_prefix = json_object_new_array(); - } - else - { - if (first) - { - if (afi == AFI_IP) - vty_out (vty, SHOW_ROUTE_V4_HEADER); - else - vty_out (vty, SHOW_ROUTE_V6_HEADER); - - if (zvrf_id (zvrf) != VRF_DEFAULT) - vty_out (vty, "\nVRF %s:\n", - zvrf_name(zvrf)); - - first = 0; - } - } - - vty_show_ip_route (vty, rn, re, json_prefix); - } - - if (json_prefix) - { - prefix2str (&rn->p, buf, sizeof buf); - json_object_object_add(json, buf, json_prefix); - json_prefix = NULL; - } - } - - if (use_json) - { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - - return CMD_SUCCESS; + const char *mcast_info = ""; + if (mcast) { + rib_table_info_t *info = srcdest_rnode_table_info(rn); + mcast_info = (info->safi == SAFI_MULTICAST) + ? " using Multicast RIB" + : " using Unicast RIB"; + } + + vty_out(vty, "Routing entry for %s%s\n", + srcdest_rnode2str(rn, buf, sizeof(buf)), mcast_info); + vty_out(vty, " Known via \"%s", zebra_route_string(re->type)); + if (re->instance) + vty_out(vty, "[%d]", re->instance); + vty_out(vty, "\""); + vty_out(vty, ", distance %u, metric %u", re->distance, + re->metric); + if (re->tag) + vty_out(vty, ", tag %d", re->tag); + if (re->mtu) + vty_out(vty, ", mtu %u", re->mtu); + if (re->vrf_id != VRF_DEFAULT) { + zvrf = vrf_info_lookup(re->vrf_id); + vty_out(vty, ", vrf %s", zvrf_name(zvrf)); + } + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) + vty_out(vty, ", best"); + if (re->refcnt) + vty_out(vty, ", refcnt %ld", re->refcnt); + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE)) + vty_out(vty, ", blackhole"); + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT)) + vty_out(vty, ", reject"); + vty_out(vty, "\n"); + + if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF + || re->type == ZEBRA_ROUTE_ISIS + || re->type == ZEBRA_ROUTE_NHRP + || re->type == ZEBRA_ROUTE_TABLE + || re->type == ZEBRA_ROUTE_BGP) { + time_t uptime; + struct tm *tm; + + uptime = time(NULL); + uptime -= re->uptime; + tm = gmtime(&uptime); + + vty_out(vty, " Last update "); + + if (uptime < ONE_DAY_SECOND) + vty_out(vty, "%02d:%02d:%02d", tm->tm_hour, + tm->tm_min, tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + vty_out(vty, "%dd%02dh%02dm", tm->tm_yday, + tm->tm_hour, tm->tm_min); + else + vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), + tm->tm_hour); + vty_out(vty, " ago\n"); + } + + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + char addrstr[32]; + + vty_out(vty, " %c%s", + CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) + ? '*' + : ' ', + nexthop->rparent ? " " : ""); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, " %s", + inet_ntoa(nexthop->gate.ipv4)); + if (nexthop->ifindex) + vty_out(vty, ", via %s", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, " %s", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, + buf, sizeof buf)); + if (nexthop->ifindex) + vty_out(vty, ", via %s", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + break; + case NEXTHOP_TYPE_IFINDEX: + vty_out(vty, " directly connected, %s", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + break; + case NEXTHOP_TYPE_BLACKHOLE: + vty_out(vty, " directly connected, Null0"); + break; + default: + break; + } + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + vty_out(vty, " inactive"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) + vty_out(vty, " onlink"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + vty_out(vty, " (recursive)"); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nexthop->src.ipv4.s_addr) { + if (inet_ntop(AF_INET, + &nexthop->src.ipv4, + addrstr, sizeof addrstr)) + vty_out(vty, ", src %s", + addrstr); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, + &in6addr_any)) { + if (inet_ntop(AF_INET6, + &nexthop->src.ipv6, + addrstr, sizeof addrstr)) + vty_out(vty, ", src %s", + addrstr); + } + break; + default: + break; + } + + /* Label information */ + if (nexthop->nh_label + && nexthop->nh_label->num_labels) { + vty_out(vty, ", label %s", + mpls_label2str( + nexthop->nh_label->num_labels, + nexthop->nh_label->label, buf, + sizeof buf, 1)); + } + + vty_out(vty, "\n"); + } + vty_out(vty, "\n"); + } +} + +static void vty_show_ip_route(struct vty *vty, struct route_node *rn, + struct route_entry *re, json_object *json) +{ + struct nexthop *nexthop; + int len = 0; + char buf[SRCDEST2STR_BUFFER]; + json_object *json_nexthops = NULL; + json_object *json_nexthop = NULL; + json_object *json_route = NULL; + json_object *json_labels = NULL; + + if (json) { + json_route = json_object_new_object(); + json_nexthops = json_object_new_array(); + + json_object_string_add(json_route, "prefix", + srcdest_rnode2str(rn, buf, sizeof buf)); + json_object_string_add(json_route, "protocol", + zebra_route_string(re->type)); + + if (re->instance) + json_object_int_add(json_route, "instance", + re->instance); + + if (re->vrf_id) + json_object_int_add(json_route, "vrfId", re->vrf_id); + + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) + json_object_boolean_true_add(json_route, "selected"); + + if (re->type != ZEBRA_ROUTE_CONNECT + && re->type != ZEBRA_ROUTE_KERNEL) { + json_object_int_add(json_route, "distance", + re->distance); + json_object_int_add(json_route, "metric", re->metric); + } + + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE)) + json_object_boolean_true_add(json_route, "blackhole"); + + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT)) + json_object_boolean_true_add(json_route, "reject"); + + if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF + || re->type == ZEBRA_ROUTE_ISIS + || re->type == ZEBRA_ROUTE_NHRP + || re->type == ZEBRA_ROUTE_TABLE + || re->type == ZEBRA_ROUTE_BGP) { + time_t uptime; + struct tm *tm; + + uptime = time(NULL); + uptime -= re->uptime; + tm = gmtime(&uptime); + + if (uptime < ONE_DAY_SECOND) + sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, + tm->tm_min, tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + sprintf(buf, "%dd%02dh%02dm", tm->tm_yday, + tm->tm_hour, tm->tm_min); + else + sprintf(buf, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), + tm->tm_hour); + + json_object_string_add(json_route, "uptime", buf); + } + + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + json_nexthop = json_object_new_object(); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) + json_object_boolean_true_add(json_nexthop, + "fib"); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + json_object_string_add( + json_nexthop, "ip", + inet_ntoa(nexthop->gate.ipv4)); + json_object_string_add(json_nexthop, "afi", + "ipv4"); + + if (nexthop->ifindex) { + json_object_int_add(json_nexthop, + "interfaceIndex", + nexthop->ifindex); + json_object_string_add( + json_nexthop, "interfaceName", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + json_object_string_add( + json_nexthop, "ip", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, + buf, sizeof buf)); + json_object_string_add(json_nexthop, "afi", + "ipv6"); + + if (nexthop->ifindex) { + json_object_int_add(json_nexthop, + "interfaceIndex", + nexthop->ifindex); + json_object_string_add( + json_nexthop, "interfaceName", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + } + break; + + case NEXTHOP_TYPE_IFINDEX: + json_object_boolean_true_add( + json_nexthop, "directlyConnected"); + json_object_int_add(json_nexthop, + "interfaceIndex", + nexthop->ifindex); + json_object_string_add( + json_nexthop, "interfaceName", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + break; + case NEXTHOP_TYPE_BLACKHOLE: + json_object_boolean_true_add(json_nexthop, + "blackhole"); + break; + default: + break; + } + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + json_object_boolean_true_add(json_nexthop, + "active"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) + json_object_boolean_true_add(json_nexthop, + "onLink"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + json_object_boolean_true_add(json_nexthop, + "recursive"); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nexthop->src.ipv4.s_addr) { + if (inet_ntop(AF_INET, + &nexthop->src.ipv4, buf, + sizeof buf)) + json_object_string_add( + json_nexthop, "source", + buf); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, + &in6addr_any)) { + if (inet_ntop(AF_INET6, + &nexthop->src.ipv6, buf, + sizeof buf)) + json_object_string_add( + json_nexthop, "source", + buf); + } + break; + default: + break; + } + + if (nexthop->nh_label + && nexthop->nh_label->num_labels) { + json_labels = json_object_new_array(); + + for (int label_index = 0; + label_index + < nexthop->nh_label->num_labels; + label_index++) + json_object_array_add( + json_labels, + json_object_new_int( + nexthop->nh_label->label + [label_index])); + + json_object_object_add(json_nexthop, "labels", + json_labels); + } + + json_object_array_add(json_nexthops, json_nexthop); + } + + json_object_object_add(json_route, "nexthops", json_nexthops); + json_object_array_add(json, json_route); + return; + } + + /* Nexthop information. */ + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (nexthop == re->nexthop) { + /* Prefix information. */ + len = vty_out(vty, "%c", zebra_route_char(re->type)); + if (re->instance) + len += vty_out(vty, "[%d]", re->instance); + len += vty_out( + vty, "%c%c %s", + CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) + ? '>' + : ' ', + CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) + ? '*' + : ' ', + srcdest_rnode2str(rn, buf, sizeof buf)); + + /* Distance and metric display. */ + if (re->type != ZEBRA_ROUTE_CONNECT + && re->type != ZEBRA_ROUTE_KERNEL) + len += vty_out(vty, " [%d/%d]", re->distance, + re->metric); + } else + vty_out(vty, " %c%*c", + CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) + ? '*' + : ' ', + len - 3 + (2 * nexthop_level(nexthop)), ' '); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4)); + if (nexthop->ifindex) + vty_out(vty, ", %s", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, " via %s", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, + sizeof buf)); + if (nexthop->ifindex) + vty_out(vty, ", %s", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + break; + + case NEXTHOP_TYPE_IFINDEX: + vty_out(vty, " is directly connected, %s", + ifindex2ifname(nexthop->ifindex, re->vrf_id)); + break; + case NEXTHOP_TYPE_BLACKHOLE: + vty_out(vty, " is directly connected, Null0"); + break; + default: + break; + } + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + vty_out(vty, " inactive"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) + vty_out(vty, " onlink"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + vty_out(vty, " (recursive)"); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nexthop->src.ipv4.s_addr) { + if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, + sizeof buf)) + vty_out(vty, ", src %s", buf); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) { + if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, + sizeof buf)) + vty_out(vty, ", src %s", buf); + } + break; + default: + break; + } + + /* Label information */ + if (nexthop->nh_label && nexthop->nh_label->num_labels) { + vty_out(vty, ", label %s", + mpls_label2str(nexthop->nh_label->num_labels, + nexthop->nh_label->label, buf, + sizeof buf, 1)); + } + + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE)) + vty_out(vty, ", bh"); + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT)) + vty_out(vty, ", rej"); + + if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF + || re->type == ZEBRA_ROUTE_ISIS + || re->type == ZEBRA_ROUTE_NHRP + || re->type == ZEBRA_ROUTE_TABLE + || re->type == ZEBRA_ROUTE_BGP) { + time_t uptime; + struct tm *tm; + + uptime = time(NULL); + uptime -= re->uptime; + tm = gmtime(&uptime); + + if (uptime < ONE_DAY_SECOND) + vty_out(vty, ", %02d:%02d:%02d", tm->tm_hour, + tm->tm_min, tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + vty_out(vty, ", %dd%02dh%02dm", tm->tm_yday, + tm->tm_hour, tm->tm_min); + else + vty_out(vty, ", %02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), + tm->tm_hour); + } + vty_out(vty, "\n"); + } +} + +static bool use_fib(struct cmd_token *token) +{ + return strncmp(token->arg, "route", strlen(token->arg)); +} + +static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, + safi_t safi, bool use_fib, u_char use_json, + route_tag_t tag, struct prefix *longer_prefix_p, + bool supernets_only, int type, + u_short ospf_instance_id) +{ + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + int first = 1; + struct zebra_vrf *zvrf = NULL; + char buf[BUFSIZ]; + json_object *json = NULL; + json_object *json_prefix = NULL; + u_int32_t addr; + + if (!(zvrf = zebra_vrf_lookup_by_name(vrf_name))) { + if (use_json) + vty_out(vty, "{}\n"); + else + vty_out(vty, "vrf %s not defined\n", vrf_name); + return CMD_SUCCESS; + } + + if (zvrf_id(zvrf) == VRF_UNKNOWN) { + if (use_json) + vty_out(vty, "{}\n"); + else + vty_out(vty, "vrf %s inactive\n", vrf_name); + return CMD_SUCCESS; + } + + table = zebra_vrf_table(afi, safi, zvrf_id(zvrf)); + if (!table) { + if (use_json) + vty_out(vty, "{}\n"); + return CMD_SUCCESS; + } + + if (use_json) + json = json_object_new_object(); + + /* Show all routes. */ + for (rn = route_top(table); rn; rn = route_next(rn)) { + RNODE_FOREACH_RE(rn, re) + { + if (use_fib + && !CHECK_FLAG(re->status, + ROUTE_ENTRY_SELECTED_FIB)) + continue; + + if (tag && re->tag != tag) + continue; + + if (longer_prefix_p + && !prefix_match(longer_prefix_p, &rn->p)) + continue; + + /* This can only be true when the afi is IPv4 */ + if (supernets_only) { + addr = ntohl(rn->p.u.prefix4.s_addr); + + if (IN_CLASSC(addr) && rn->p.prefixlen >= 24) + continue; + + if (IN_CLASSB(addr) && rn->p.prefixlen >= 16) + continue; + + if (IN_CLASSA(addr) && rn->p.prefixlen >= 8) + continue; + } + + if (type && re->type != type) + continue; + + if (ospf_instance_id + && (re->type != ZEBRA_ROUTE_OSPF + || re->instance != ospf_instance_id)) + continue; + + if (use_json) { + if (!json_prefix) + json_prefix = json_object_new_array(); + } else { + if (first) { + if (afi == AFI_IP) + vty_out(vty, + SHOW_ROUTE_V4_HEADER); + else + vty_out(vty, + SHOW_ROUTE_V6_HEADER); + + if (zvrf_id(zvrf) != VRF_DEFAULT) + vty_out(vty, "\nVRF %s:\n", + zvrf_name(zvrf)); + + first = 0; + } + } + + vty_show_ip_route(vty, rn, re, json_prefix); + } + + if (json_prefix) { + prefix2str(&rn->p, buf, sizeof buf); + json_object_object_add(json, buf, json_prefix); + json_prefix = NULL; + } + } + + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } + + return CMD_SUCCESS; } DEFUN (show_ip_nht, @@ -1221,14 +1247,14 @@ DEFUN (show_ip_nht, "IP nexthop tracking table\n" VRF_CMD_HELP_STR) { - int idx_vrf = 4; - vrf_id_t vrf_id = VRF_DEFAULT; + int idx_vrf = 4; + vrf_id_t vrf_id = VRF_DEFAULT; - if (argc == 5) - VRF_GET_ID (vrf_id, argv[idx_vrf]->arg); + if (argc == 5) + VRF_GET_ID(vrf_id, argv[idx_vrf]->arg); - zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE); - return CMD_SUCCESS; + zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE); + return CMD_SUCCESS; } @@ -1240,17 +1266,17 @@ DEFUN (show_ip_nht_vrf_all, "IP nexthop tracking table\n" VRF_ALL_CMD_HELP_STR) { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - { - vty_out (vty, "\nVRF %s:\n", zvrf_name(zvrf)); - zebra_print_rnh_table(zvrf_id (zvrf), AF_INET, vty, RNH_NEXTHOP_TYPE); - } + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) { + vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); + zebra_print_rnh_table(zvrf_id(zvrf), AF_INET, vty, + RNH_NEXTHOP_TYPE); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_nht, @@ -1261,14 +1287,14 @@ DEFUN (show_ipv6_nht, "IPv6 nexthop tracking table\n" VRF_CMD_HELP_STR) { - int idx_vrf = 4; - vrf_id_t vrf_id = VRF_DEFAULT; + int idx_vrf = 4; + vrf_id_t vrf_id = VRF_DEFAULT; - if (argc == 5) - VRF_GET_ID (vrf_id, argv[idx_vrf]->arg); + if (argc == 5) + VRF_GET_ID(vrf_id, argv[idx_vrf]->arg); - zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE); - return CMD_SUCCESS; + zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE); + return CMD_SUCCESS; } @@ -1280,17 +1306,17 @@ DEFUN (show_ipv6_nht_vrf_all, "IPv6 nexthop tracking table\n" VRF_ALL_CMD_HELP_STR) { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - { - vty_out (vty, "\nVRF %s:\n", zvrf_name(zvrf)); - zebra_print_rnh_table(zvrf_id (zvrf), AF_INET6, vty, RNH_NEXTHOP_TYPE); - } + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) { + vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); + zebra_print_rnh_table(zvrf_id(zvrf), AF_INET6, vty, + RNH_NEXTHOP_TYPE); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_nht_default_route, @@ -1300,12 +1326,12 @@ DEFUN (ip_nht_default_route, "Filter Next Hop tracking route resolution\n" "Resolve via default route\n") { - if (zebra_rnh_ip_default_route) - return CMD_SUCCESS; + if (zebra_rnh_ip_default_route) + return CMD_SUCCESS; - zebra_rnh_ip_default_route = 1; - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + zebra_rnh_ip_default_route = 1; + zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + return CMD_SUCCESS; } DEFUN (no_ip_nht_default_route, @@ -1316,12 +1342,12 @@ DEFUN (no_ip_nht_default_route, "Filter Next Hop tracking route resolution\n" "Resolve via default route\n") { - if (!zebra_rnh_ip_default_route) - return CMD_SUCCESS; + if (!zebra_rnh_ip_default_route) + return CMD_SUCCESS; - zebra_rnh_ip_default_route = 0; - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + zebra_rnh_ip_default_route = 0; + zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + return CMD_SUCCESS; } DEFUN (ipv6_nht_default_route, @@ -1331,12 +1357,12 @@ DEFUN (ipv6_nht_default_route, "Filter Next Hop tracking route resolution\n" "Resolve via default route\n") { - if (zebra_rnh_ipv6_default_route) - return CMD_SUCCESS; + if (zebra_rnh_ipv6_default_route) + return CMD_SUCCESS; - zebra_rnh_ipv6_default_route = 1; - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + zebra_rnh_ipv6_default_route = 1; + zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + return CMD_SUCCESS; } DEFUN (no_ipv6_nht_default_route, @@ -1347,12 +1373,12 @@ DEFUN (no_ipv6_nht_default_route, "Filter Next Hop tracking route resolution\n" "Resolve via default route\n") { - if (!zebra_rnh_ipv6_default_route) - return CMD_SUCCESS; + if (!zebra_rnh_ipv6_default_route) + return CMD_SUCCESS; - zebra_rnh_ipv6_default_route = 0; - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + zebra_rnh_ipv6_default_route = 0; + zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + return CMD_SUCCESS; } DEFUN (show_ip_route, @@ -1373,99 +1399,96 @@ DEFUN (show_ip_route, "Instance ID\n" JSON_STR) { - bool uf = use_fib(argv[2]); - struct route_table *table; - int vrf_all = 0; - route_tag_t tag = 0; - vrf_id_t vrf_id = VRF_DEFAULT; - struct vrf *vrf; - struct zebra_vrf *zvrf; - int uj = use_json(argc, argv); - int idx = 0; - struct prefix p; - bool longer_prefixes = false; - bool supernets_only = false; - int type = 0; - u_short ospf_instance_id = 0; - - if (argv_find (argv, argc, "vrf", &idx)) - { - if (strmatch(argv[idx+1]->arg, "all")) - vrf_all = 1; - else - VRF_GET_ID (vrf_id, argv[idx+1]->arg); - } - - if (argv_find (argv, argc, "tag", &idx)) - tag = strtoul(argv[idx + 1]->arg, NULL, 10); - - else if (argv_find (argv, argc, "A.B.C.D/M", &idx)) - { - str2prefix (argv[idx]->arg, &p); - longer_prefixes = true; - } - - else if (argv_find (argv, argc, "supernets_only", &idx)) - supernets_only = true; - - else - { - if (argv_find (argv, argc, "kernel", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "babel", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "connected", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "static", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "rip", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "ospf", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "isis", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "bgp", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "pim", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "eigrp", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "nhrp", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "table", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "vnc", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - - if (argv_find (argv, argc, "(1-65535)", &idx)) - ospf_instance_id = strtoul(argv[idx]->arg, NULL, 10); - - if (type < 0) - { - vty_out (vty, "Unknown route type\n"); - return CMD_WARNING; - } - } - - if (vrf_all) - { - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) - continue; - - do_show_ip_route (vty, zvrf_name (zvrf), AFI_IP, SAFI_UNICAST, uf, uj, tag, - longer_prefixes ? &p : NULL, supernets_only, type, ospf_instance_id); - } - } - else - { - vrf = vrf_lookup_by_id (vrf_id); - do_show_ip_route (vty, vrf->name, AFI_IP, SAFI_UNICAST, uf, uj, tag, - longer_prefixes ? &p : NULL, supernets_only, type, ospf_instance_id); - } - return CMD_SUCCESS; + bool uf = use_fib(argv[2]); + struct route_table *table; + int vrf_all = 0; + route_tag_t tag = 0; + vrf_id_t vrf_id = VRF_DEFAULT; + struct vrf *vrf; + struct zebra_vrf *zvrf; + int uj = use_json(argc, argv); + int idx = 0; + struct prefix p; + bool longer_prefixes = false; + bool supernets_only = false; + int type = 0; + u_short ospf_instance_id = 0; + + if (argv_find(argv, argc, "vrf", &idx)) { + if (strmatch(argv[idx + 1]->arg, "all")) + vrf_all = 1; + else + VRF_GET_ID(vrf_id, argv[idx + 1]->arg); + } + + if (argv_find(argv, argc, "tag", &idx)) + tag = strtoul(argv[idx + 1]->arg, NULL, 10); + + else if (argv_find(argv, argc, "A.B.C.D/M", &idx)) { + str2prefix(argv[idx]->arg, &p); + longer_prefixes = true; + } + + else if (argv_find(argv, argc, "supernets_only", &idx)) + supernets_only = true; + + else { + if (argv_find(argv, argc, "kernel", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "babel", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "connected", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "static", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "rip", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "ospf", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "isis", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "bgp", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "pim", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "eigrp", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "nhrp", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "table", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "vnc", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + + if (argv_find(argv, argc, "(1-65535)", &idx)) + ospf_instance_id = strtoul(argv[idx]->arg, NULL, 10); + + if (type < 0) { + vty_out(vty, "Unknown route type\n"); + return CMD_WARNING; + } + } + + if (vrf_all) { + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) + == NULL) + continue; + + do_show_ip_route( + vty, zvrf_name(zvrf), AFI_IP, SAFI_UNICAST, uf, + uj, tag, longer_prefixes ? &p : NULL, + supernets_only, type, ospf_instance_id); + } + } else { + vrf = vrf_lookup_by_id(vrf_id); + do_show_ip_route(vty, vrf->name, AFI_IP, SAFI_UNICAST, uf, uj, + tag, longer_prefixes ? &p : NULL, + supernets_only, type, ospf_instance_id); + } + return CMD_SUCCESS; } DEFUN (show_ip_route_addr, @@ -1477,44 +1500,39 @@ DEFUN (show_ip_route_addr, VRF_CMD_HELP_STR "Network in the IP routing table to display\n") { - int ret; - struct prefix_ipv4 p; - struct route_table *table; - struct route_node *rn; - vrf_id_t vrf_id = VRF_DEFAULT; - - if (strmatch(argv[3]->text, "vrf")) - { - VRF_GET_ID (vrf_id, argv[4]->arg); - ret = str2prefix_ipv4 (argv[5]->arg, &p); - } - else - { - ret = str2prefix_ipv4 (argv[3]->arg, &p); - } + int ret; + struct prefix_ipv4 p; + struct route_table *table; + struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (strmatch(argv[3]->text, "vrf")) { + VRF_GET_ID(vrf_id, argv[4]->arg); + ret = str2prefix_ipv4(argv[5]->arg, &p); + } else { + ret = str2prefix_ipv4(argv[3]->arg, &p); + } - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv4 address\n"); - return CMD_WARNING; - } + if (ret <= 0) { + vty_out(vty, "%% Malformed IPv4 address\n"); + return CMD_WARNING; + } - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - { - vty_out (vty, "%% Network not in table\n"); - return CMD_WARNING; - } + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) { + vty_out(vty, "%% Network not in table\n"); + return CMD_WARNING; + } - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); + route_unlock_node(rn); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_route_prefix, @@ -1526,110 +1544,102 @@ DEFUN (show_ip_route_prefix, VRF_CMD_HELP_STR "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { - int ret; - struct prefix_ipv4 p; - struct route_table *table; - struct route_node *rn; - vrf_id_t vrf_id = VRF_DEFAULT; - - if (strmatch(argv[3]->text, "vrf")) - { - VRF_GET_ID (vrf_id, argv[4]->arg); - ret = str2prefix_ipv4 (argv[5]->arg, &p); - } - else - { - ret = str2prefix_ipv4 (argv[3]->arg, &p); - } + int ret; + struct prefix_ipv4 p; + struct route_table *table; + struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (strmatch(argv[3]->text, "vrf")) { + VRF_GET_ID(vrf_id, argv[4]->arg); + ret = str2prefix_ipv4(argv[5]->arg, &p); + } else { + ret = str2prefix_ipv4(argv[3]->arg, &p); + } - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv4 address\n"); - return CMD_WARNING; - } + if (ret <= 0) { + vty_out(vty, "%% Malformed IPv4 address\n"); + return CMD_WARNING; + } - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn || rn->p.prefixlen != p.prefixlen) - { - vty_out (vty, "%% Network not in table\n"); - return CMD_WARNING; - } + rn = route_node_match(table, (struct prefix *)&p); + if (!rn || rn->p.prefixlen != p.prefixlen) { + vty_out(vty, "%% Network not in table\n"); + return CMD_WARNING; + } - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); + route_unlock_node(rn); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -vty_show_ip_route_summary (struct vty *vty, struct route_table *table) +static void vty_show_ip_route_summary(struct vty *vty, + struct route_table *table) { - struct route_node *rn; - struct route_entry *re; + struct route_node *rn; + struct route_entry *re; #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1) - u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1]; - u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1]; - u_int32_t i; - u_int32_t is_ibgp; - - memset (&rib_cnt, 0, sizeof(rib_cnt)); - memset (&fib_cnt, 0, sizeof(fib_cnt)); - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE (rn, re) - { - is_ibgp = (re->type == ZEBRA_ROUTE_BGP && - CHECK_FLAG (re->flags, ZEBRA_FLAG_IBGP)); - - rib_cnt[ZEBRA_ROUTE_TOTAL]++; - if (is_ibgp) - rib_cnt[ZEBRA_ROUTE_IBGP]++; - else - rib_cnt[re->type]++; - - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED)) - { - fib_cnt[ZEBRA_ROUTE_TOTAL]++; - - if (is_ibgp) - fib_cnt[ZEBRA_ROUTE_IBGP]++; - else - fib_cnt[re->type]++; - } - } - - vty_out (vty, "%-20s %-20s %s (vrf %s)\n", - "Route Source", "Routes", "FIB", - zvrf_name(((rib_table_info_t *)table->info)->zvrf)); - - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if ((rib_cnt[i] > 0) || - (i == ZEBRA_ROUTE_BGP && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) - { - if (i == ZEBRA_ROUTE_BGP) - { - vty_out (vty, "%-20s %-20d %-20d \n", "ebgp", - rib_cnt[ZEBRA_ROUTE_BGP],fib_cnt[ZEBRA_ROUTE_BGP]); - vty_out (vty, "%-20s %-20d %-20d \n", "ibgp", - rib_cnt[ZEBRA_ROUTE_IBGP],fib_cnt[ZEBRA_ROUTE_IBGP]); - } - else - vty_out (vty, "%-20s %-20d %-20d \n", zebra_route_string(i), - rib_cnt[i], fib_cnt[i]); - } - } - - vty_out (vty, "------\n"); - vty_out (vty, "%-20s %-20d %-20d \n", "Totals", rib_cnt[ZEBRA_ROUTE_TOTAL], - fib_cnt[ZEBRA_ROUTE_TOTAL]); - vty_out (vty, "\n"); + u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1]; + u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1]; + u_int32_t i; + u_int32_t is_ibgp; + + memset(&rib_cnt, 0, sizeof(rib_cnt)); + memset(&fib_cnt, 0, sizeof(fib_cnt)); + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE(rn, re) + { + is_ibgp = (re->type == ZEBRA_ROUTE_BGP + && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)); + + rib_cnt[ZEBRA_ROUTE_TOTAL]++; + if (is_ibgp) + rib_cnt[ZEBRA_ROUTE_IBGP]++; + else + rib_cnt[re->type]++; + + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) { + fib_cnt[ZEBRA_ROUTE_TOTAL]++; + + if (is_ibgp) + fib_cnt[ZEBRA_ROUTE_IBGP]++; + else + fib_cnt[re->type]++; + } + } + + vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source", "Routes", + "FIB", zvrf_name(((rib_table_info_t *)table->info)->zvrf)); + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP + && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) { + if (i == ZEBRA_ROUTE_BGP) { + vty_out(vty, "%-20s %-20d %-20d \n", "ebgp", + rib_cnt[ZEBRA_ROUTE_BGP], + fib_cnt[ZEBRA_ROUTE_BGP]); + vty_out(vty, "%-20s %-20d %-20d \n", "ibgp", + rib_cnt[ZEBRA_ROUTE_IBGP], + fib_cnt[ZEBRA_ROUTE_IBGP]); + } else + vty_out(vty, "%-20s %-20d %-20d \n", + zebra_route_string(i), rib_cnt[i], + fib_cnt[i]); + } + } + + vty_out(vty, "------\n"); + vty_out(vty, "%-20s %-20d %-20d \n", "Totals", + rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]); + vty_out(vty, "\n"); } /* @@ -1639,75 +1649,75 @@ vty_show_ip_route_summary (struct vty *vty, struct route_table *table) * protocols on the box. * */ -static void -vty_show_ip_route_summary_prefix (struct vty *vty, struct route_table *table) +static void vty_show_ip_route_summary_prefix(struct vty *vty, + struct route_table *table) { - struct route_node *rn; - struct route_entry *re; - struct nexthop *nexthop; + struct route_node *rn; + struct route_entry *re; + struct nexthop *nexthop; #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1) - u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1]; - u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1]; - u_int32_t i; - int cnt; - - memset (&rib_cnt, 0, sizeof(rib_cnt)); - memset (&fib_cnt, 0, sizeof(fib_cnt)); - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE (rn, re) - { - - /* - * In case of ECMP, count only once. - */ - cnt = 0; - for (nexthop = re->nexthop; (!cnt && nexthop); nexthop = nexthop->next) - { - cnt++; - rib_cnt[ZEBRA_ROUTE_TOTAL]++; - rib_cnt[re->type]++; - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - fib_cnt[ZEBRA_ROUTE_TOTAL]++; - fib_cnt[re->type]++; - } - if (re->type == ZEBRA_ROUTE_BGP && - CHECK_FLAG (re->flags, ZEBRA_FLAG_IBGP)) - { - rib_cnt[ZEBRA_ROUTE_IBGP]++; - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - fib_cnt[ZEBRA_ROUTE_IBGP]++; - } - } - } - - vty_out (vty, "%-20s %-20s %s (vrf %s)\n", - "Route Source", "Prefix Routes", "FIB", - zvrf_name(((rib_table_info_t *)table->info)->zvrf)); - - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (rib_cnt[i] > 0) - { - if (i == ZEBRA_ROUTE_BGP) - { - vty_out (vty, "%-20s %-20d %-20d \n", "ebgp", - rib_cnt[ZEBRA_ROUTE_BGP] - rib_cnt[ZEBRA_ROUTE_IBGP], - fib_cnt[ZEBRA_ROUTE_BGP] - fib_cnt[ZEBRA_ROUTE_IBGP]); - vty_out (vty, "%-20s %-20d %-20d \n", "ibgp", - rib_cnt[ZEBRA_ROUTE_IBGP],fib_cnt[ZEBRA_ROUTE_IBGP]); - } - else - vty_out (vty, "%-20s %-20d %-20d \n", zebra_route_string(i), - rib_cnt[i], fib_cnt[i]); - } - } - - vty_out (vty, "------\n"); - vty_out (vty, "%-20s %-20d %-20d \n", "Totals", rib_cnt[ZEBRA_ROUTE_TOTAL], - fib_cnt[ZEBRA_ROUTE_TOTAL]); - vty_out (vty, "\n"); + u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1]; + u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1]; + u_int32_t i; + int cnt; + + memset(&rib_cnt, 0, sizeof(rib_cnt)); + memset(&fib_cnt, 0, sizeof(fib_cnt)); + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE(rn, re) + { + + /* + * In case of ECMP, count only once. + */ + cnt = 0; + for (nexthop = re->nexthop; (!cnt && nexthop); + nexthop = nexthop->next) { + cnt++; + rib_cnt[ZEBRA_ROUTE_TOTAL]++; + rib_cnt[re->type]++; + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB)) { + fib_cnt[ZEBRA_ROUTE_TOTAL]++; + fib_cnt[re->type]++; + } + if (re->type == ZEBRA_ROUTE_BGP + && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) { + rib_cnt[ZEBRA_ROUTE_IBGP]++; + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB)) + fib_cnt[ZEBRA_ROUTE_IBGP]++; + } + } + } + + vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source", + "Prefix Routes", "FIB", + zvrf_name(((rib_table_info_t *)table->info)->zvrf)); + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (rib_cnt[i] > 0) { + if (i == ZEBRA_ROUTE_BGP) { + vty_out(vty, "%-20s %-20d %-20d \n", "ebgp", + rib_cnt[ZEBRA_ROUTE_BGP] + - rib_cnt[ZEBRA_ROUTE_IBGP], + fib_cnt[ZEBRA_ROUTE_BGP] + - fib_cnt[ZEBRA_ROUTE_IBGP]); + vty_out(vty, "%-20s %-20d %-20d \n", "ibgp", + rib_cnt[ZEBRA_ROUTE_IBGP], + fib_cnt[ZEBRA_ROUTE_IBGP]); + } else + vty_out(vty, "%-20s %-20d %-20d \n", + zebra_route_string(i), rib_cnt[i], + fib_cnt[i]); + } + } + + vty_out(vty, "------\n"); + vty_out(vty, "%-20s %-20d %-20d \n", "Totals", + rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]); + vty_out(vty, "\n"); } /* Show route summary. */ @@ -1720,19 +1730,19 @@ DEFUN (show_ip_route_summary, VRF_CMD_HELP_STR "Summary of all routes\n") { - struct route_table *table; - vrf_id_t vrf_id = VRF_DEFAULT; + struct route_table *table; + vrf_id_t vrf_id = VRF_DEFAULT; - if (strmatch(argv[3]->text, "vrf")) - VRF_GET_ID (vrf_id, argv[4]->arg); + if (strmatch(argv[3]->text, "vrf")) + VRF_GET_ID(vrf_id, argv[4]->arg); - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - vty_show_ip_route_summary (vty, table); + vty_show_ip_route_summary(vty, table); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Show route summary prefix. */ @@ -1746,19 +1756,19 @@ DEFUN (show_ip_route_summary_prefix, "Summary of all routes\n" "Prefix routes\n") { - struct route_table *table; - vrf_id_t vrf_id = VRF_DEFAULT; + struct route_table *table; + vrf_id_t vrf_id = VRF_DEFAULT; - if (strmatch(argv[3]->text, "vrf")) - VRF_GET_ID (vrf_id, argv[4]->arg); + if (strmatch(argv[3]->text, "vrf")) + VRF_GET_ID(vrf_id, argv[4]->arg); - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - vty_show_ip_route_summary_prefix (vty, table); + vty_show_ip_route_summary_prefix(vty, table); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1771,37 +1781,36 @@ DEFUN (show_ip_route_vrf_all_addr, VRF_ALL_CMD_HELP_STR "Network in the IP routing table to display\n") { - int idx_ipv4 = 5; - int ret; - struct prefix_ipv4 p; - struct route_table *table; - struct route_node *rn; - struct vrf *vrf; - struct zebra_vrf *zvrf; - - ret = str2prefix_ipv4 (argv[idx_ipv4]->arg, &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv4 address\n"); - return CMD_WARNING; - } + int idx_ipv4 = 5; + int ret; + struct prefix_ipv4 p; + struct route_table *table; + struct route_node *rn; + struct vrf *vrf; + struct zebra_vrf *zvrf; + + ret = str2prefix_ipv4(argv[idx_ipv4]->arg, &p); + if (ret <= 0) { + vty_out(vty, "%% Malformed IPv4 address\n"); + return CMD_WARNING; + } - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) - continue; + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - continue; + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + continue; - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); - } + route_unlock_node(rn); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_route_vrf_all_prefix, @@ -1813,42 +1822,40 @@ DEFUN (show_ip_route_vrf_all_prefix, VRF_ALL_CMD_HELP_STR "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { - int idx_ipv4_prefixlen = 5; - int ret; - struct prefix_ipv4 p; - struct route_table *table; - struct route_node *rn; - struct vrf *vrf; - struct zebra_vrf *zvrf; - - ret = str2prefix_ipv4 (argv[idx_ipv4_prefixlen]->arg, &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv4 address\n"); - return CMD_WARNING; - } + int idx_ipv4_prefixlen = 5; + int ret; + struct prefix_ipv4 p; + struct route_table *table; + struct route_node *rn; + struct vrf *vrf; + struct zebra_vrf *zvrf; + + ret = str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + if (ret <= 0) { + vty_out(vty, "%% Malformed IPv4 address\n"); + return CMD_WARNING; + } - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) - continue; + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - continue; - if (rn->p.prefixlen != p.prefixlen) - { - route_unlock_node (rn); - continue; - } + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + continue; + if (rn->p.prefixlen != p.prefixlen) { + route_unlock_node(rn); + continue; + } - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); - } + route_unlock_node(rn); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_route_vrf_all_summary, @@ -1860,14 +1867,15 @@ DEFUN (show_ip_route_vrf_all_summary, VRF_ALL_CMD_HELP_STR "Summary of all routes\n") { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - vty_show_ip_route_summary (vty, zvrf->table[AFI_IP][SAFI_UNICAST]); + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) + vty_show_ip_route_summary(vty, + zvrf->table[AFI_IP][SAFI_UNICAST]); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_route_vrf_all_summary_prefix, @@ -1880,275 +1888,282 @@ DEFUN (show_ip_route_vrf_all_summary_prefix, "Summary of all routes\n" "Prefix routes\n") { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - vty_show_ip_route_summary_prefix (vty, zvrf->table[AFI_IP][SAFI_UNICAST]); + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) + vty_show_ip_route_summary_prefix( + vty, zvrf->table[AFI_IP][SAFI_UNICAST]); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Write static route configuration. */ -static int -static_config (struct vty *vty, afi_t afi, safi_t safi, const char *cmd) -{ - struct route_node *rn; - struct static_route *si; - struct route_table *stable; - struct vrf *vrf; - struct zebra_vrf *zvrf; - char buf[SRCDEST2STR_BUFFER]; - int write =0; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if (!(zvrf = vrf->info)) - continue; - if ((stable = zvrf->stable[afi][safi]) == NULL) - continue; - - for (rn = route_top (stable); rn; rn = srcdest_route_next (rn)) - for (si = rn->info; si; si = si->next) - { - vty_out (vty, "%s %s", cmd, srcdest_rnode2str (rn, buf, sizeof buf)); - - switch (si->type) - { - case STATIC_IPV4_GATEWAY: - vty_out (vty, " %s", inet_ntoa (si->addr.ipv4)); - break; - case STATIC_IPV6_GATEWAY: - vty_out (vty, " %s", inet_ntop (AF_INET6, &si->addr.ipv6, buf, sizeof buf)); - break; - case STATIC_IFINDEX: - vty_out (vty, " %s", si->ifname); - break; - case STATIC_BLACKHOLE: - vty_out (vty, " Null0"); - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - vty_out (vty, " %s %s", - inet_ntop (AF_INET6, &si->addr.ipv6, buf, sizeof buf), - ifindex2ifname (si->ifindex, si->vrf_id)); - break; - } - - /* flags are incompatible with STATIC_BLACKHOLE */ - if (si->type != STATIC_BLACKHOLE) - { - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, " %s", "reject"); - - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, " %s", "blackhole"); - } - - if (si->tag) - vty_out (vty, " tag %"ROUTE_TAG_PRI, si->tag); - - if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) - vty_out (vty, " %d", si->distance); - - if (si->vrf_id != VRF_DEFAULT) - vty_out (vty, " vrf %s", zvrf_name (zvrf)); - - /* Label information */ - if (si->snh_label.num_labels) - vty_out (vty, " label %s", - mpls_label2str (si->snh_label.num_labels, - si->snh_label.label, buf, sizeof buf, 0)); - - vty_out (vty, "\n"); - - write = 1; - } - } - return write; +static int static_config(struct vty *vty, afi_t afi, safi_t safi, + const char *cmd) +{ + struct route_node *rn; + struct static_route *si; + struct route_table *stable; + struct vrf *vrf; + struct zebra_vrf *zvrf; + char buf[SRCDEST2STR_BUFFER]; + int write = 0; + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if (!(zvrf = vrf->info)) + continue; + if ((stable = zvrf->stable[afi][safi]) == NULL) + continue; + + for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) + for (si = rn->info; si; si = si->next) { + vty_out(vty, "%s %s", cmd, + srcdest_rnode2str(rn, buf, sizeof buf)); + + switch (si->type) { + case STATIC_IPV4_GATEWAY: + vty_out(vty, " %s", + inet_ntoa(si->addr.ipv4)); + break; + case STATIC_IPV6_GATEWAY: + vty_out(vty, " %s", + inet_ntop(AF_INET6, + &si->addr.ipv6, buf, + sizeof buf)); + break; + case STATIC_IFINDEX: + vty_out(vty, " %s", si->ifname); + break; + case STATIC_BLACKHOLE: + vty_out(vty, " Null0"); + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + vty_out(vty, " %s %s", + inet_ntop(AF_INET6, + &si->addr.ipv6, buf, + sizeof buf), + ifindex2ifname(si->ifindex, + si->vrf_id)); + break; + } + + /* flags are incompatible with STATIC_BLACKHOLE + */ + if (si->type != STATIC_BLACKHOLE) { + if (CHECK_FLAG(si->flags, + ZEBRA_FLAG_REJECT)) + vty_out(vty, " %s", "reject"); + + if (CHECK_FLAG(si->flags, + ZEBRA_FLAG_BLACKHOLE)) + vty_out(vty, " %s", + "blackhole"); + } + + if (si->tag) + vty_out(vty, " tag %" ROUTE_TAG_PRI, + si->tag); + + if (si->distance + != ZEBRA_STATIC_DISTANCE_DEFAULT) + vty_out(vty, " %d", si->distance); + + if (si->vrf_id != VRF_DEFAULT) + vty_out(vty, " vrf %s", + zvrf_name(zvrf)); + + /* Label information */ + if (si->snh_label.num_labels) + vty_out(vty, " label %s", + mpls_label2str( + si->snh_label + .num_labels, + si->snh_label.label, + buf, sizeof buf, 0)); + + vty_out(vty, "\n"); + + write = 1; + } + } + return write; } /* General fucntion for IPv6 static route. */ -int -static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, - const char *src_str, - const char *gate_str, const char *ifname, - const char *flag_str, const char *tag_str, - const char *distance_str, const char *vrf_id_str, - const char *label_str) -{ - int ret; - u_char distance; - struct prefix p, src; - struct prefix_ipv6 *src_p = NULL; - struct in6_addr *gate = NULL; - struct in6_addr gate_addr; - u_char type = STATIC_BLACKHOLE; - u_char flag = 0; - route_tag_t tag = 0; - unsigned int ifindex = 0; - struct interface *ifp = NULL; - struct zebra_vrf *zvrf; - struct static_nh_label snh_label; - - ret = str2prefix (dest_str, &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (src_str) - { - ret = str2prefix (src_str, &src); - if (ret <= 0 || src.family != AF_INET6) - { - vty_out (vty, "%% Malformed source address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - src_p = (struct prefix_ipv6*)&src; - } - - /* Apply mask for given prefix. */ - apply_mask (&p); - - /* Administrative distance. */ - if (distance_str) - distance = atoi (distance_str); - else - distance = ZEBRA_STATIC_DISTANCE_DEFAULT; - - /* tag */ - if (tag_str) - tag = strtoul(tag_str, NULL, 10); - - /* When gateway is valid IPv6 addrees, then gate is treated as - nexthop address other case gate is treated as interface name. */ - ret = inet_pton (AF_INET6, gate_str, &gate_addr); - - /* VRF id */ - zvrf = zebra_vrf_lookup_by_name (vrf_id_str); - - if (!zvrf) - { - vty_out (vty, "%% vrf %s is not defined\n", vrf_id_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Labels */ - memset (&snh_label, 0, sizeof (struct static_nh_label)); - if (label_str) - { - if (!mpls_enabled) - { - vty_out (vty, - "%% MPLS not turned on in kernel, ignoring command\n"); - return CMD_WARNING_CONFIG_FAILED; - } - int rc = mpls_str2label (label_str, &snh_label.num_labels, - snh_label.label); - if (rc < 0) - { - switch (rc) { - case -1: - vty_out (vty, "%% Malformed label(s)\n"); - break; - case -2: - vty_out (vty, "%% Cannot use reserved label(s) (%d-%d)\n", - MPLS_MIN_RESERVED_LABEL,MPLS_MAX_RESERVED_LABEL); - break; - case -3: - vty_out (vty, "%% Too many labels. Enter %d or fewer\n", - MPLS_MAX_LABELS); - break; - } - return CMD_WARNING_CONFIG_FAILED; - } - } - - /* Null0 static route. */ - if ((gate_str != NULL) && (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)) - { - if (flag_str) - { - vty_out (vty, "%% can not have flag %s with Null0\n", flag_str); - return CMD_WARNING_CONFIG_FAILED; - } - if (add_cmd) - static_add_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, NULL, ifindex, ifname, - ZEBRA_FLAG_BLACKHOLE, tag, distance, zvrf, &snh_label); - else - static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, NULL, ifindex, tag, - distance, zvrf, &snh_label); - return CMD_SUCCESS; - } - - /* Route flags */ - if (flag_str) { - switch(flag_str[0]) { - case 'r': - case 'R': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_REJECT); - break; - case 'b': - case 'B': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE); - break; - default: - vty_out (vty, "%% Malformed flag %s \n", flag_str); - return CMD_WARNING_CONFIG_FAILED; - } - } - - if (ifname) - { - /* When ifname is specified. It must be come with gateway - address. */ - if (ret != 1) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - type = STATIC_IPV6_GATEWAY_IFINDEX; - gate = &gate_addr; - ifp = if_lookup_by_name (ifname, zvrf_id (zvrf)); - if (!ifp) - { - vty_out (vty, "%% Malformed Interface name %s\n", ifname); - return CMD_WARNING_CONFIG_FAILED; - } - ifindex = ifp->ifindex; - } - else - { - if (ret == 1) - { - type = STATIC_IPV6_GATEWAY; - gate = &gate_addr; - } - else - { - type = STATIC_IFINDEX; - ifp = if_lookup_by_name (gate_str, zvrf_id (zvrf)); - if (!ifp) - { - vty_out (vty, "%% Malformed Interface name %s\n", gate_str); - ifindex = IFINDEX_DELETED; - } - else - ifindex = ifp->ifindex; - ifname = gate_str; - } - } - - if (add_cmd) - static_add_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, (union g_addr *)gate, - ifindex, ifname, flag, tag, distance, zvrf, &snh_label); - else - static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, (union g_addr *)gate, - ifindex, tag, distance, zvrf, &snh_label); - - return CMD_SUCCESS; +int static_ipv6_func(struct vty *vty, int add_cmd, const char *dest_str, + const char *src_str, const char *gate_str, + const char *ifname, const char *flag_str, + const char *tag_str, const char *distance_str, + const char *vrf_id_str, const char *label_str) +{ + int ret; + u_char distance; + struct prefix p, src; + struct prefix_ipv6 *src_p = NULL; + struct in6_addr *gate = NULL; + struct in6_addr gate_addr; + u_char type = STATIC_BLACKHOLE; + u_char flag = 0; + route_tag_t tag = 0; + unsigned int ifindex = 0; + struct interface *ifp = NULL; + struct zebra_vrf *zvrf; + struct static_nh_label snh_label; + + ret = str2prefix(dest_str, &p); + if (ret <= 0) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (src_str) { + ret = str2prefix(src_str, &src); + if (ret <= 0 || src.family != AF_INET6) { + vty_out(vty, "%% Malformed source address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + src_p = (struct prefix_ipv6 *)&src; + } + + /* Apply mask for given prefix. */ + apply_mask(&p); + + /* Administrative distance. */ + if (distance_str) + distance = atoi(distance_str); + else + distance = ZEBRA_STATIC_DISTANCE_DEFAULT; + + /* tag */ + if (tag_str) + tag = strtoul(tag_str, NULL, 10); + + /* When gateway is valid IPv6 addrees, then gate is treated as + nexthop address other case gate is treated as interface name. */ + ret = inet_pton(AF_INET6, gate_str, &gate_addr); + + /* VRF id */ + zvrf = zebra_vrf_lookup_by_name(vrf_id_str); + + if (!zvrf) { + vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Labels */ + memset(&snh_label, 0, sizeof(struct static_nh_label)); + if (label_str) { + if (!mpls_enabled) { + vty_out(vty, + "%% MPLS not turned on in kernel, ignoring command\n"); + return CMD_WARNING_CONFIG_FAILED; + } + int rc = mpls_str2label(label_str, &snh_label.num_labels, + snh_label.label); + if (rc < 0) { + switch (rc) { + case -1: + vty_out(vty, "%% Malformed label(s)\n"); + break; + case -2: + vty_out(vty, + "%% Cannot use reserved label(s) (%d-%d)\n", + MPLS_MIN_RESERVED_LABEL, + MPLS_MAX_RESERVED_LABEL); + break; + case -3: + vty_out(vty, + "%% Too many labels. Enter %d or fewer\n", + MPLS_MAX_LABELS); + break; + } + return CMD_WARNING_CONFIG_FAILED; + } + } + + /* Null0 static route. */ + if ((gate_str != NULL) + && (strncasecmp(gate_str, "Null0", strlen(gate_str)) == 0)) { + if (flag_str) { + vty_out(vty, "%% can not have flag %s with Null0\n", + flag_str); + return CMD_WARNING_CONFIG_FAILED; + } + if (add_cmd) + static_add_route(AFI_IP6, SAFI_UNICAST, type, &p, src_p, + NULL, ifindex, ifname, + ZEBRA_FLAG_BLACKHOLE, tag, distance, + zvrf, &snh_label); + else + static_delete_route(AFI_IP6, SAFI_UNICAST, type, &p, + src_p, NULL, ifindex, tag, distance, + zvrf, &snh_label); + return CMD_SUCCESS; + } + + /* Route flags */ + if (flag_str) { + switch (flag_str[0]) { + case 'r': + case 'R': /* XXX */ + SET_FLAG(flag, ZEBRA_FLAG_REJECT); + break; + case 'b': + case 'B': /* XXX */ + SET_FLAG(flag, ZEBRA_FLAG_BLACKHOLE); + break; + default: + vty_out(vty, "%% Malformed flag %s \n", flag_str); + return CMD_WARNING_CONFIG_FAILED; + } + } + + if (ifname) { + /* When ifname is specified. It must be come with gateway + address. */ + if (ret != 1) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + type = STATIC_IPV6_GATEWAY_IFINDEX; + gate = &gate_addr; + ifp = if_lookup_by_name(ifname, zvrf_id(zvrf)); + if (!ifp) { + vty_out(vty, "%% Malformed Interface name %s\n", + ifname); + return CMD_WARNING_CONFIG_FAILED; + } + ifindex = ifp->ifindex; + } else { + if (ret == 1) { + type = STATIC_IPV6_GATEWAY; + gate = &gate_addr; + } else { + type = STATIC_IFINDEX; + ifp = if_lookup_by_name(gate_str, zvrf_id(zvrf)); + if (!ifp) { + vty_out(vty, "%% Malformed Interface name %s\n", + gate_str); + ifindex = IFINDEX_DELETED; + } else + ifindex = ifp->ifindex; + ifname = gate_str; + } + } + + if (add_cmd) + static_add_route(AFI_IP6, SAFI_UNICAST, type, &p, src_p, + (union g_addr *)gate, ifindex, ifname, flag, + tag, distance, zvrf, &snh_label); + else + static_delete_route(AFI_IP6, SAFI_UNICAST, type, &p, src_p, + (union g_addr *)gate, ifindex, tag, + distance, zvrf, &snh_label); + + return CMD_SUCCESS; } DEFUN (ipv6_route, @@ -2167,33 +2182,28 @@ DEFUN (ipv6_route, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 2; - int idx_ipv6_ifname; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[3]->text, "from")) - { - src = argv[4]->arg; - idx_ipv6_ifname = 5; - idx_curr = 6; - } - else - { - src = NULL; - idx_ipv6_ifname = 3; - idx_curr = 4; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 1, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6_ifname]->arg, - NULL, NULL, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 2; + int idx_ipv6_ifname; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[3]->text, "from")) { + src = argv[4]->arg; + idx_ipv6_ifname = 5; + idx_curr = 6; + } else { + src = NULL; + idx_ipv6_ifname = 3; + idx_curr = 4; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 1, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6_ifname]->arg, NULL, NULL, tag, + distance, vrf, NULL); } DEFUN (ipv6_route_flags, @@ -2213,37 +2223,32 @@ DEFUN (ipv6_route_flags, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 2; - int idx_ipv6_ifname; - int idx_reject_blackhole; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[3]->text, "from")) - { - src = argv[4]->arg; - idx_ipv6_ifname = 5; - idx_reject_blackhole = 6; - idx_curr = 7; - } - else - { - src = NULL; - idx_ipv6_ifname = 3; - idx_reject_blackhole = 4; - idx_curr = 5; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 1, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6_ifname]->arg, - NULL, - argv[idx_reject_blackhole]->arg, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 2; + int idx_ipv6_ifname; + int idx_reject_blackhole; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[3]->text, "from")) { + src = argv[4]->arg; + idx_ipv6_ifname = 5; + idx_reject_blackhole = 6; + idx_curr = 7; + } else { + src = NULL; + idx_ipv6_ifname = 3; + idx_reject_blackhole = 4; + idx_curr = 5; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 1, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6_ifname]->arg, NULL, + argv[idx_reject_blackhole]->arg, tag, distance, + vrf, NULL); } DEFUN (ipv6_route_ifname, @@ -2261,37 +2266,31 @@ DEFUN (ipv6_route_ifname, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 2; - int idx_ipv6 = 3; - int idx_interface = 4; - int idx_curr = 5; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[3]->text, "from")) - { - src = argv[4]->arg; - idx_ipv6 = 5; - idx_interface = 6; - idx_curr = 7; - } - else - { - src = NULL; - idx_ipv6 = 3; - idx_interface = 4; - idx_curr = 5; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 1, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6]->arg, - argv[idx_interface]->arg, - NULL, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 2; + int idx_ipv6 = 3; + int idx_interface = 4; + int idx_curr = 5; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[3]->text, "from")) { + src = argv[4]->arg; + idx_ipv6 = 5; + idx_interface = 6; + idx_curr = 7; + } else { + src = NULL; + idx_ipv6 = 3; + idx_interface = 4; + idx_curr = 5; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 1, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6]->arg, argv[idx_interface]->arg, + NULL, tag, distance, vrf, NULL); } DEFUN (ipv6_route_ifname_flags, @@ -2311,40 +2310,35 @@ DEFUN (ipv6_route_ifname_flags, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 2; - int idx_ipv6; - int idx_interface; - int idx_reject_blackhole; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[3]->text, "from")) - { - src = argv[4]->arg; - idx_ipv6 = 5; - idx_interface = 6; - idx_reject_blackhole = 7; - idx_curr = 8; - } - else - { - src = NULL; - idx_ipv6 = 3; - idx_interface = 4; - idx_reject_blackhole = 5; - idx_curr = 6; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 1, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6]->arg, - argv[idx_interface]->arg, - argv[idx_reject_blackhole]->arg, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 2; + int idx_ipv6; + int idx_interface; + int idx_reject_blackhole; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[3]->text, "from")) { + src = argv[4]->arg; + idx_ipv6 = 5; + idx_interface = 6; + idx_reject_blackhole = 7; + idx_curr = 8; + } else { + src = NULL; + idx_ipv6 = 3; + idx_interface = 4; + idx_reject_blackhole = 5; + idx_curr = 6; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 1, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6]->arg, argv[idx_interface]->arg, + argv[idx_reject_blackhole]->arg, tag, distance, + vrf, NULL); } DEFUN (no_ipv6_route, @@ -2364,33 +2358,28 @@ DEFUN (no_ipv6_route, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 3; - int idx_ipv6_ifname; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[4]->text, "from")) - { - src = argv[5]->arg; - idx_ipv6_ifname = 6; - idx_curr = 7; - } - else - { - src = NULL; - idx_ipv6_ifname = 4; - idx_curr = 5; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 0, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6_ifname]->arg, - NULL, NULL, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 3; + int idx_ipv6_ifname; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[4]->text, "from")) { + src = argv[5]->arg; + idx_ipv6_ifname = 6; + idx_curr = 7; + } else { + src = NULL; + idx_ipv6_ifname = 4; + idx_curr = 5; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 0, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6_ifname]->arg, NULL, NULL, tag, + distance, vrf, NULL); } DEFUN (no_ipv6_route_flags, @@ -2411,37 +2400,32 @@ DEFUN (no_ipv6_route_flags, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 3; - int idx_ipv6_ifname; - int idx_reject_blackhole; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[4]->text, "from")) - { - src = argv[5]->arg; - idx_ipv6_ifname = 6; - idx_reject_blackhole = 7; - idx_curr = 8; - } - else - { - src = NULL; - idx_ipv6_ifname = 4; - idx_reject_blackhole = 5; - idx_curr = 6; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 0, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6_ifname]->arg, - NULL, - argv[idx_reject_blackhole]->arg, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 3; + int idx_ipv6_ifname; + int idx_reject_blackhole; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[4]->text, "from")) { + src = argv[5]->arg; + idx_ipv6_ifname = 6; + idx_reject_blackhole = 7; + idx_curr = 8; + } else { + src = NULL; + idx_ipv6_ifname = 4; + idx_reject_blackhole = 5; + idx_curr = 6; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 0, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6_ifname]->arg, NULL, + argv[idx_reject_blackhole]->arg, tag, distance, + vrf, NULL); } DEFUN (no_ipv6_route_ifname, @@ -2460,37 +2444,31 @@ DEFUN (no_ipv6_route_ifname, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 3; - int idx_ipv6; - int idx_interface; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[4]->text, "from")) - { - src = argv[5]->arg; - idx_ipv6 = 6; - idx_interface = 7; - idx_curr = 8; - } - else - { - src = NULL; - idx_ipv6 = 4; - idx_interface = 5; - idx_curr = 6; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 0, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6]->arg, - argv[idx_interface]->arg, - NULL, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 3; + int idx_ipv6; + int idx_interface; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[4]->text, "from")) { + src = argv[5]->arg; + idx_ipv6 = 6; + idx_interface = 7; + idx_curr = 8; + } else { + src = NULL; + idx_ipv6 = 4; + idx_interface = 5; + idx_curr = 6; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 0, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6]->arg, argv[idx_interface]->arg, + NULL, tag, distance, vrf, NULL); } DEFUN (no_ipv6_route_ifname_flags, @@ -2511,40 +2489,35 @@ DEFUN (no_ipv6_route_ifname_flags, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 3; - int idx_ipv6; - int idx_interface; - int idx_reject_blackhole; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[4]->text, "from")) - { - src = argv[5]->arg; - idx_ipv6 = 6; - idx_interface = 7; - idx_reject_blackhole = 8; - idx_curr = 9; - } - else - { - src = NULL; - idx_ipv6 = 4; - idx_interface = 5; - idx_reject_blackhole = 6; - idx_curr = 7; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 0, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6]->arg, - argv[idx_interface]->arg, - argv[idx_reject_blackhole]->arg, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 3; + int idx_ipv6; + int idx_interface; + int idx_reject_blackhole; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[4]->text, "from")) { + src = argv[5]->arg; + idx_ipv6 = 6; + idx_interface = 7; + idx_reject_blackhole = 8; + idx_curr = 9; + } else { + src = NULL; + idx_ipv6 = 4; + idx_interface = 5; + idx_reject_blackhole = 6; + idx_curr = 7; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 0, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6]->arg, argv[idx_interface]->arg, + argv[idx_reject_blackhole]->arg, tag, distance, + vrf, NULL); } DEFUN (show_ipv6_route, @@ -2562,88 +2535,85 @@ DEFUN (show_ipv6_route, FRR_IP6_REDIST_HELP_STR_ZEBRA JSON_STR) { - bool uf = use_fib(argv[2]); - struct route_table *table; - int vrf_all = 0; - route_tag_t tag = 0; - vrf_id_t vrf_id = VRF_DEFAULT; - struct vrf *vrf; - struct zebra_vrf *zvrf; - int uj = use_json(argc, argv); - int idx = 0; - struct prefix p; - bool longer_prefixes = false; - bool supernets_only = false; - int type = 0; - - if (argv_find (argv, argc, "vrf", &idx)) - { - if (strmatch(argv[idx+1]->arg, "all")) - vrf_all = 1; - else - VRF_GET_ID (vrf_id, argv[idx+1]->arg); - } - - if (argv_find (argv, argc, "tag", &idx)) - tag = strtoul(argv[idx + 1]->arg, NULL, 10); - - else if (argv_find (argv, argc, "X:X::X:X/M", &idx)) - { - str2prefix (argv[idx]->arg, &p); - longer_prefixes = true; - } - - else - { - if (argv_find (argv, argc, "kernel", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "babel", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "connected", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "static", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "ripng", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "ospf6", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "isis", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "bgp", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "nhrp", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "table", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "vnc", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - - if (type < 0) - { - vty_out (vty, "Unknown route type\n"); - return CMD_WARNING; - } - } - - if (vrf_all) - { - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) - continue; - - do_show_ip_route (vty, zvrf_name (zvrf), AFI_IP6, SAFI_UNICAST, uf, uj, tag, - longer_prefixes ? &p : NULL, supernets_only, type, 0); - } - } - else - { - vrf = vrf_lookup_by_id (vrf_id); - do_show_ip_route (vty, vrf->name, AFI_IP6, SAFI_UNICAST, uf, uj, tag, - longer_prefixes ? &p : NULL, supernets_only, type, 0); - } - return CMD_SUCCESS; + bool uf = use_fib(argv[2]); + struct route_table *table; + int vrf_all = 0; + route_tag_t tag = 0; + vrf_id_t vrf_id = VRF_DEFAULT; + struct vrf *vrf; + struct zebra_vrf *zvrf; + int uj = use_json(argc, argv); + int idx = 0; + struct prefix p; + bool longer_prefixes = false; + bool supernets_only = false; + int type = 0; + + if (argv_find(argv, argc, "vrf", &idx)) { + if (strmatch(argv[idx + 1]->arg, "all")) + vrf_all = 1; + else + VRF_GET_ID(vrf_id, argv[idx + 1]->arg); + } + + if (argv_find(argv, argc, "tag", &idx)) + tag = strtoul(argv[idx + 1]->arg, NULL, 10); + + else if (argv_find(argv, argc, "X:X::X:X/M", &idx)) { + str2prefix(argv[idx]->arg, &p); + longer_prefixes = true; + } + + else { + if (argv_find(argv, argc, "kernel", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "babel", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "connected", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "static", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "ripng", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "ospf6", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "isis", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "bgp", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "nhrp", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "table", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "vnc", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + + if (type < 0) { + vty_out(vty, "Unknown route type\n"); + return CMD_WARNING; + } + } + + if (vrf_all) { + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) + == NULL) + continue; + + do_show_ip_route(vty, zvrf_name(zvrf), AFI_IP6, + SAFI_UNICAST, uf, uj, tag, + longer_prefixes ? &p : NULL, + supernets_only, type, 0); + } + } else { + vrf = vrf_lookup_by_id(vrf_id); + do_show_ip_route(vty, vrf->name, AFI_IP6, SAFI_UNICAST, uf, uj, + tag, longer_prefixes ? &p : NULL, + supernets_only, type, 0); + } + return CMD_SUCCESS; } DEFUN (show_ipv6_route_addr, @@ -2655,44 +2625,39 @@ DEFUN (show_ipv6_route_addr, VRF_CMD_HELP_STR "IPv6 Address\n") { - int ret; - struct prefix_ipv6 p; - struct route_table *table; - struct route_node *rn; - vrf_id_t vrf_id = VRF_DEFAULT; - - if (strmatch(argv[3]->text, "vrf")) - { - VRF_GET_ID (vrf_id, argv[4]->arg); - ret = str2prefix_ipv6 (argv[5]->arg, &p); - } - else - { - ret = str2prefix_ipv6 (argv[3]->arg, &p); - } + int ret; + struct prefix_ipv6 p; + struct route_table *table; + struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (strmatch(argv[3]->text, "vrf")) { + VRF_GET_ID(vrf_id, argv[4]->arg); + ret = str2prefix_ipv6(argv[5]->arg, &p); + } else { + ret = str2prefix_ipv6(argv[3]->arg, &p); + } - if (ret <= 0) - { - vty_out (vty, "Malformed IPv6 address\n"); - return CMD_WARNING; - } + if (ret <= 0) { + vty_out(vty, "Malformed IPv6 address\n"); + return CMD_WARNING; + } - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - { - vty_out (vty, "%% Network not in table\n"); - return CMD_WARNING; - } + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) { + vty_out(vty, "%% Network not in table\n"); + return CMD_WARNING; + } - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); + route_unlock_node(rn); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_route_prefix, @@ -2704,42 +2669,38 @@ DEFUN (show_ipv6_route_prefix, VRF_CMD_HELP_STR "IPv6 prefix\n") { - int ret; - struct prefix_ipv6 p; - struct route_table *table; - struct route_node *rn; - vrf_id_t vrf_id = VRF_DEFAULT; - - if (strmatch(argv[3]->text, "vrf")) - { - VRF_GET_ID (vrf_id, argv[4]->arg); - ret = str2prefix_ipv6 (argv[5]->arg, &p); - } - else - ret = str2prefix_ipv6 (argv[3]->arg, &p); - - if (ret <= 0) - { - vty_out (vty, "Malformed IPv6 prefix\n"); - return CMD_WARNING; - } + int ret; + struct prefix_ipv6 p; + struct route_table *table; + struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (strmatch(argv[3]->text, "vrf")) { + VRF_GET_ID(vrf_id, argv[4]->arg); + ret = str2prefix_ipv6(argv[5]->arg, &p); + } else + ret = str2prefix_ipv6(argv[3]->arg, &p); + + if (ret <= 0) { + vty_out(vty, "Malformed IPv6 prefix\n"); + return CMD_WARNING; + } - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn || rn->p.prefixlen != p.prefixlen) - { - vty_out (vty, "%% Network not in table\n"); - return CMD_WARNING; - } + rn = route_node_match(table, (struct prefix *)&p); + if (!rn || rn->p.prefixlen != p.prefixlen) { + vty_out(vty, "%% Network not in table\n"); + return CMD_WARNING; + } - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); + route_unlock_node(rn); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -2753,19 +2714,19 @@ DEFUN (show_ipv6_route_summary, VRF_CMD_HELP_STR "Summary of all IPv6 routes\n") { - struct route_table *table; - vrf_id_t vrf_id = VRF_DEFAULT; + struct route_table *table; + vrf_id_t vrf_id = VRF_DEFAULT; - if (strmatch(argv[3]->text, "vrf")) - VRF_GET_ID (vrf_id, argv[4]->arg); + if (strmatch(argv[3]->text, "vrf")) + VRF_GET_ID(vrf_id, argv[4]->arg); - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - vty_show_ip_route_summary (vty, table); + vty_show_ip_route_summary(vty, table); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -2780,19 +2741,19 @@ DEFUN (show_ipv6_route_summary_prefix, "Summary of all IPv6 routes\n" "Prefix routes\n") { - struct route_table *table; - vrf_id_t vrf_id = VRF_DEFAULT; + struct route_table *table; + vrf_id_t vrf_id = VRF_DEFAULT; - if (strmatch(argv[3]->text, "vrf")) - VRF_GET_ID (vrf_id, argv[4]->arg); + if (strmatch(argv[3]->text, "vrf")) + VRF_GET_ID(vrf_id, argv[4]->arg); - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - vty_show_ip_route_summary_prefix (vty, table); + vty_show_ip_route_summary_prefix(vty, table); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -2808,31 +2769,30 @@ DEFUN (show_ipv6_mroute, "IPv6 Multicast routing table\n" VRF_CMD_HELP_STR) { - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - int first = 1; - vrf_id_t vrf_id = VRF_DEFAULT; - - if (argc == 5) - VRF_GET_ID (vrf_id, argv[4]->arg); - - table = zebra_vrf_table (AFI_IP6, SAFI_MULTICAST, vrf_id); - if (! table) - return CMD_SUCCESS; - - /* Show all IPv6 route. */ - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE (rn, re) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V6_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, re, NULL); - } - return CMD_SUCCESS; + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (argc == 5) + VRF_GET_ID(vrf_id, argv[4]->arg); + + table = zebra_vrf_table(AFI_IP6, SAFI_MULTICAST, vrf_id); + if (!table) + return CMD_SUCCESS; + + /* Show all IPv6 route. */ + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE(rn, re) + { + if (first) { + vty_out(vty, SHOW_ROUTE_V6_HEADER); + first = 0; + } + vty_show_ip_route(vty, rn, re, NULL); + } + return CMD_SUCCESS; } DEFUN (show_ipv6_route_vrf_all_addr, @@ -2844,37 +2804,36 @@ DEFUN (show_ipv6_route_vrf_all_addr, VRF_ALL_CMD_HELP_STR "IPv6 Address\n") { - int idx_ipv6 = 5; - int ret; - struct prefix_ipv6 p; - struct route_table *table; - struct route_node *rn; - struct vrf *vrf; - struct zebra_vrf *zvrf; - - ret = str2prefix_ipv6 (argv[idx_ipv6]->arg, &p); - if (ret <= 0) - { - vty_out (vty, "Malformed IPv6 address\n"); - return CMD_WARNING; - } + int idx_ipv6 = 5; + int ret; + struct prefix_ipv6 p; + struct route_table *table; + struct route_node *rn; + struct vrf *vrf; + struct zebra_vrf *zvrf; + + ret = str2prefix_ipv6(argv[idx_ipv6]->arg, &p); + if (ret <= 0) { + vty_out(vty, "Malformed IPv6 address\n"); + return CMD_WARNING; + } - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) - continue; + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) + continue; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - continue; + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + continue; - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); - } + route_unlock_node(rn); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_route_vrf_all_prefix, @@ -2886,42 +2845,40 @@ DEFUN (show_ipv6_route_vrf_all_prefix, VRF_ALL_CMD_HELP_STR "IPv6 prefix\n") { - int idx_ipv6_prefixlen = 5; - int ret; - struct prefix_ipv6 p; - struct route_table *table; - struct route_node *rn; - struct vrf *vrf; - struct zebra_vrf *zvrf; - - ret = str2prefix_ipv6 (argv[idx_ipv6_prefixlen]->arg, &p); - if (ret <= 0) - { - vty_out (vty, "Malformed IPv6 prefix\n"); - return CMD_WARNING; - } + int idx_ipv6_prefixlen = 5; + int ret; + struct prefix_ipv6 p; + struct route_table *table; + struct route_node *rn; + struct vrf *vrf; + struct zebra_vrf *zvrf; + + ret = str2prefix_ipv6(argv[idx_ipv6_prefixlen]->arg, &p); + if (ret <= 0) { + vty_out(vty, "Malformed IPv6 prefix\n"); + return CMD_WARNING; + } - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) - continue; + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) + continue; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - continue; - if (rn->p.prefixlen != p.prefixlen) - { - route_unlock_node (rn); - continue; - } + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + continue; + if (rn->p.prefixlen != p.prefixlen) { + route_unlock_node(rn); + continue; + } - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); - } + route_unlock_node(rn); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_route_vrf_all_summary, @@ -2933,14 +2890,15 @@ DEFUN (show_ipv6_route_vrf_all_summary, VRF_ALL_CMD_HELP_STR "Summary of all IPv6 routes\n") { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - vty_show_ip_route_summary (vty, zvrf->table[AFI_IP6][SAFI_UNICAST]); + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) + vty_show_ip_route_summary(vty, + zvrf->table[AFI_IP6][SAFI_UNICAST]); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_mroute_vrf_all, @@ -2951,32 +2909,31 @@ DEFUN (show_ipv6_mroute_vrf_all, "IPv6 Multicast routing table\n" VRF_ALL_CMD_HELP_STR) { - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - struct vrf *vrf; - struct zebra_vrf *zvrf; - int first = 1; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP6][SAFI_MULTICAST]) == NULL) - continue; - - /* Show all IPv6 route. */ - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE (rn, re) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V6_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, re, NULL); - } - } - return CMD_SUCCESS; + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + struct vrf *vrf; + struct zebra_vrf *zvrf; + int first = 1; + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP6][SAFI_MULTICAST]) == NULL) + continue; + + /* Show all IPv6 route. */ + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE(rn, re) + { + if (first) { + vty_out(vty, SHOW_ROUTE_V6_HEADER); + first = 0; + } + vty_show_ip_route(vty, rn, re, NULL); + } + } + return CMD_SUCCESS; } DEFUN (show_ipv6_route_vrf_all_summary_prefix, @@ -2989,14 +2946,15 @@ DEFUN (show_ipv6_route_vrf_all_summary_prefix, "Summary of all IPv6 routes\n" "Prefix routes\n") { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - vty_show_ip_route_summary_prefix (vty, zvrf->table[AFI_IP6][SAFI_UNICAST]); + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) + vty_show_ip_route_summary_prefix( + vty, zvrf->table[AFI_IP6][SAFI_UNICAST]); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (allow_external_route_update, @@ -3004,9 +2962,9 @@ DEFUN (allow_external_route_update, "allow-external-route-update", "Allow FRR routes to be overwritten by external processes\n") { - allow_delete = 1; + allow_delete = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_allow_external_route_update, @@ -3015,9 +2973,9 @@ DEFUN (no_allow_external_route_update, NO_STR "Allow FRR routes to be overwritten by external processes\n") { - allow_delete = 0; + allow_delete = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } /* show vrf */ @@ -3027,26 +2985,26 @@ DEFUN (show_vrf, SHOW_STR "VRF\n") { - struct vrf *vrf; - struct zebra_vrf *zvrf; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if (!(zvrf = vrf->info)) - continue; - if (!zvrf_id (zvrf)) - continue; + struct vrf *vrf; + struct zebra_vrf *zvrf; - vty_out (vty, "vrf %s ", zvrf_name (zvrf)); - if (zvrf_id (zvrf) == VRF_UNKNOWN) - vty_out (vty, "inactive"); - else - vty_out (vty, "id %u table %u", zvrf_id (zvrf), zvrf->table_id); - vty_out (vty, "\n"); - - } + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if (!(zvrf = vrf->info)) + continue; + if (!zvrf_id(zvrf)) + continue; + + vty_out(vty, "vrf %s ", zvrf_name(zvrf)); + if (zvrf_id(zvrf) == VRF_UNKNOWN) + vty_out(vty, "inactive"); + else + vty_out(vty, "id %u table %u", zvrf_id(zvrf), + zvrf->table_id); + vty_out(vty, "\n"); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_evpn_vni, @@ -3056,11 +3014,11 @@ DEFUN (show_evpn_vni, "EVPN\n" "VxLAN information\n") { - struct zebra_vrf *zvrf; + struct zebra_vrf *zvrf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_vnis(vty, zvrf); - return CMD_SUCCESS; + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_vnis(vty, zvrf); + return CMD_SUCCESS; } DEFUN (show_evpn_vni_vni, @@ -3071,13 +3029,13 @@ DEFUN (show_evpn_vni_vni, "VxLAN Network Identifier\n" "VNI number\n") { - struct zebra_vrf *zvrf; - vni_t vni; + struct zebra_vrf *zvrf; + vni_t vni; - vni = strtoul(argv[3]->arg, NULL, 10); - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_vni(vty, zvrf, vni); - return CMD_SUCCESS; + vni = strtoul(argv[3]->arg, NULL, 10); + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_vni(vty, zvrf, vni); + return CMD_SUCCESS; } DEFUN (show_evpn_mac_vni, @@ -3089,13 +3047,13 @@ DEFUN (show_evpn_mac_vni, "VxLAN Network Identifier\n" "VNI number\n") { - struct zebra_vrf *zvrf; - vni_t vni; + struct zebra_vrf *zvrf; + vni_t vni; - vni = strtoul(argv[4]->arg, NULL, 10); - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_macs_vni(vty, zvrf, vni); - return CMD_SUCCESS; + vni = strtoul(argv[4]->arg, NULL, 10); + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_macs_vni(vty, zvrf, vni); + return CMD_SUCCESS; } DEFUN (show_evpn_mac_vni_all, @@ -3107,11 +3065,11 @@ DEFUN (show_evpn_mac_vni_all, "VxLAN Network Identifier\n" "All VNIs\n") { - struct zebra_vrf *zvrf; + struct zebra_vrf *zvrf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_macs_all_vni(vty, zvrf); - return CMD_SUCCESS; + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_macs_all_vni(vty, zvrf); + return CMD_SUCCESS; } DEFUN (show_evpn_mac_vni_all_vtep, @@ -3125,18 +3083,17 @@ DEFUN (show_evpn_mac_vni_all_vtep, "Remote VTEP\n" "Remote VTEP IP address\n") { - struct zebra_vrf *zvrf; - struct in_addr vtep_ip; + struct zebra_vrf *zvrf; + struct in_addr vtep_ip; - if (!inet_aton (argv[6]->arg, &vtep_ip)) - { - vty_out (vty, "%% Malformed VTEP IP address\n"); - return CMD_WARNING; - } - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip); + if (!inet_aton(argv[6]->arg, &vtep_ip)) { + vty_out(vty, "%% Malformed VTEP IP address\n"); + return CMD_WARNING; + } + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -3151,19 +3108,18 @@ DEFUN (show_evpn_mac_vni_mac, "MAC\n" "MAC address (e.g., 00:e0:ec:20:12:62)\n") { - struct zebra_vrf *zvrf; - vni_t vni; - struct ethaddr mac; + struct zebra_vrf *zvrf; + vni_t vni; + struct ethaddr mac; - vni = strtoul(argv[4]->arg, NULL, 10); - if (!prefix_str2mac (argv[6]->arg, &mac)) - { - vty_out (vty, "%% Malformed MAC address"); - return CMD_WARNING; - } - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac); - return CMD_SUCCESS; + vni = strtoul(argv[4]->arg, NULL, 10); + if (!prefix_str2mac(argv[6]->arg, &mac)) { + vty_out(vty, "%% Malformed MAC address"); + return CMD_WARNING; + } + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac); + return CMD_SUCCESS; } DEFUN (show_evpn_mac_vni_vtep, @@ -3177,20 +3133,19 @@ DEFUN (show_evpn_mac_vni_vtep, "Remote VTEP\n" "Remote VTEP IP address\n") { - struct zebra_vrf *zvrf; - vni_t vni; - struct in_addr vtep_ip; + struct zebra_vrf *zvrf; + vni_t vni; + struct in_addr vtep_ip; - vni = strtoul(argv[4]->arg, NULL, 10); - if (!inet_aton (argv[6]->arg, &vtep_ip)) - { - vty_out (vty, "%% Malformed VTEP IP address\n"); - return CMD_WARNING; - } + vni = strtoul(argv[4]->arg, NULL, 10); + if (!inet_aton(argv[6]->arg, &vtep_ip)) { + vty_out(vty, "%% Malformed VTEP IP address\n"); + return CMD_WARNING; + } - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip); - return CMD_SUCCESS; + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip); + return CMD_SUCCESS; } DEFUN (show_evpn_neigh_vni, @@ -3202,13 +3157,13 @@ DEFUN (show_evpn_neigh_vni, "VxLAN Network Identifier\n" "VNI number\n") { - struct zebra_vrf *zvrf; - vni_t vni; + struct zebra_vrf *zvrf; + vni_t vni; - vni = strtoul(argv[4]->arg, NULL, 10); - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_neigh_vni(vty, zvrf, vni); - return CMD_SUCCESS; + vni = strtoul(argv[4]->arg, NULL, 10); + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_neigh_vni(vty, zvrf, vni); + return CMD_SUCCESS; } DEFUN (show_evpn_neigh_vni_all, @@ -3220,11 +3175,11 @@ DEFUN (show_evpn_neigh_vni_all, "VxLAN Network Identifier\n" "All VNIs\n") { - struct zebra_vrf *zvrf; + struct zebra_vrf *zvrf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_neigh_all_vni(vty, zvrf); - return CMD_SUCCESS; + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_neigh_all_vni(vty, zvrf); + return CMD_SUCCESS; } DEFUN (show_evpn_neigh_vni_neigh, @@ -3238,19 +3193,18 @@ DEFUN (show_evpn_neigh_vni_neigh, "Neighbor\n" "Neighbor address (IPv4 or IPv6 address)\n") { - struct zebra_vrf *zvrf; - vni_t vni; - struct ipaddr ip; + struct zebra_vrf *zvrf; + vni_t vni; + struct ipaddr ip; - vni = strtoul(argv[4]->arg, NULL, 10); - if (str2ipaddr (argv[6]->arg, &ip) != 0) - { - vty_out (vty, "%% Malformed Neighbor address\n"); - return CMD_WARNING; - } - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip); - return CMD_SUCCESS; + vni = strtoul(argv[4]->arg, NULL, 10); + if (str2ipaddr(argv[6]->arg, &ip) != 0) { + vty_out(vty, "%% Malformed Neighbor address\n"); + return CMD_WARNING; + } + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip); + return CMD_SUCCESS; } DEFUN (show_evpn_neigh_vni_vtep, @@ -3264,34 +3218,32 @@ DEFUN (show_evpn_neigh_vni_vtep, "Remote VTEP\n" "Remote VTEP IP address\n") { - struct zebra_vrf *zvrf; - vni_t vni; - struct in_addr vtep_ip; + struct zebra_vrf *zvrf; + vni_t vni; + struct in_addr vtep_ip; - vni = strtoul(argv[4]->arg, NULL, 10); - if (!inet_aton (argv[6]->arg, &vtep_ip)) - { - vty_out (vty, "%% Malformed VTEP IP address\n"); - return CMD_WARNING; - } + vni = strtoul(argv[4]->arg, NULL, 10); + if (!inet_aton(argv[6]->arg, &vtep_ip)) { + vty_out(vty, "%% Malformed VTEP IP address\n"); + return CMD_WARNING; + } - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip); - return CMD_SUCCESS; + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip); + return CMD_SUCCESS; } /* Static ip route configuration write function. */ -static int -zebra_ip_config (struct vty *vty) +static int zebra_ip_config(struct vty *vty) { - int write = 0; + int write = 0; - write += static_config (vty, AFI_IP, SAFI_UNICAST, "ip route"); - write += static_config (vty, AFI_IP, SAFI_MULTICAST, "ip mroute"); - write += static_config (vty, AFI_IP6, SAFI_UNICAST, "ipv6 route"); + write += static_config(vty, AFI_IP, SAFI_UNICAST, "ip route"); + write += static_config(vty, AFI_IP, SAFI_MULTICAST, "ip mroute"); + write += static_config(vty, AFI_IP6, SAFI_UNICAST, "ipv6 route"); - write += zebra_import_table_config (vty); - return write; + write += zebra_import_table_config(vty); + return write; } DEFUN (ip_zebra_import_table_distance, @@ -3305,36 +3257,38 @@ DEFUN (ip_zebra_import_table_distance, "route-map for filtering\n" "route-map name\n") { - u_int32_t table_id = 0; + u_int32_t table_id = 0; - table_id = strtoul(argv[2]->arg, NULL, 10); - int distance = ZEBRA_TABLE_DISTANCE_DEFAULT; - char *rmap = strmatch (argv[argc - 2]->text, "route-map") ? - XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg) : NULL; - int ret; + table_id = strtoul(argv[2]->arg, NULL, 10); + int distance = ZEBRA_TABLE_DISTANCE_DEFAULT; + char *rmap = + strmatch(argv[argc - 2]->text, "route-map") + ? XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg) + : NULL; + int ret; - if (argc == 7 || (argc == 5 && !rmap)) - distance = strtoul(argv[4]->arg, NULL, 10); + if (argc == 7 || (argc == 5 && !rmap)) + distance = strtoul(argv[4]->arg, NULL, 10); - if (!is_zebra_valid_kernel_table(table_id)) - { - vty_out (vty, "Invalid routing table ID, %d. Must be in range 1-252\n", - table_id); - return CMD_WARNING; - } + if (!is_zebra_valid_kernel_table(table_id)) { + vty_out(vty, + "Invalid routing table ID, %d. Must be in range 1-252\n", + table_id); + return CMD_WARNING; + } - if (is_zebra_main_routing_table(table_id)) - { - vty_out (vty, "Invalid routing table ID, %d. Must be non-default table\n", - table_id); - return CMD_WARNING; - } + if (is_zebra_main_routing_table(table_id)) { + vty_out(vty, + "Invalid routing table ID, %d. Must be non-default table\n", + table_id); + return CMD_WARNING; + } - ret = zebra_import_table(AFI_IP, table_id, distance, rmap, 1); - if (rmap) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap); + ret = zebra_import_table(AFI_IP, table_id, distance, rmap, 1); + if (rmap) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap); - return ret; + return ret; } DEFUN (no_ip_zebra_import_table, @@ -3349,137 +3303,145 @@ DEFUN (no_ip_zebra_import_table, "route-map for filtering\n" "route-map name\n") { - u_int32_t table_id = 0; - table_id = strtoul(argv[3]->arg, NULL, 10); + u_int32_t table_id = 0; + table_id = strtoul(argv[3]->arg, NULL, 10); - if (!is_zebra_valid_kernel_table(table_id)) - { - vty_out (vty,"Invalid routing table ID. Must be in range 1-252\n"); - return CMD_WARNING; - } + if (!is_zebra_valid_kernel_table(table_id)) { + vty_out(vty, + "Invalid routing table ID. Must be in range 1-252\n"); + return CMD_WARNING; + } - if (is_zebra_main_routing_table(table_id)) - { - vty_out (vty, "Invalid routing table ID, %d. Must be non-default table\n", - table_id); - return CMD_WARNING; - } + if (is_zebra_main_routing_table(table_id)) { + vty_out(vty, + "Invalid routing table ID, %d. Must be non-default table\n", + table_id); + return CMD_WARNING; + } - if (!is_zebra_import_table_enabled(AFI_IP, table_id)) - return CMD_SUCCESS; + if (!is_zebra_import_table_enabled(AFI_IP, table_id)) + return CMD_SUCCESS; - return (zebra_import_table(AFI_IP, table_id, 0, NULL, 0)); + return (zebra_import_table(AFI_IP, table_id, 0, NULL, 0)); } -static int -config_write_protocol (struct vty *vty) +static int config_write_protocol(struct vty *vty) { - if (allow_delete) - vty_out (vty, "allow-external-route-update\n"); + if (allow_delete) + vty_out(vty, "allow-external-route-update\n"); - if (zebra_rnh_ip_default_route) - vty_out (vty, "ip nht resolve-via-default\n"); + if (zebra_rnh_ip_default_route) + vty_out(vty, "ip nht resolve-via-default\n"); - if (zebra_rnh_ipv6_default_route) - vty_out (vty, "ipv6 nht resolve-via-default\n"); + if (zebra_rnh_ipv6_default_route) + vty_out(vty, "ipv6 nht resolve-via-default\n"); - enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get (); + enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get(); - if (ipv4_multicast_mode != MCAST_NO_CONFIG) - vty_out (vty, "ip multicast rpf-lookup-mode %s\n", - ipv4_multicast_mode == MCAST_URIB_ONLY ? "urib-only" : ipv4_multicast_mode == MCAST_MRIB_ONLY ? "mrib-only" : ipv4_multicast_mode == MCAST_MIX_MRIB_FIRST ? "mrib-then-urib" : ipv4_multicast_mode == MCAST_MIX_DISTANCE ? "lower-distance" : "longer-prefix"); + if (ipv4_multicast_mode != MCAST_NO_CONFIG) + vty_out(vty, "ip multicast rpf-lookup-mode %s\n", + ipv4_multicast_mode == MCAST_URIB_ONLY + ? "urib-only" + : ipv4_multicast_mode == MCAST_MRIB_ONLY + ? "mrib-only" + : ipv4_multicast_mode + == MCAST_MIX_MRIB_FIRST + ? "mrib-then-urib" + : ipv4_multicast_mode + == MCAST_MIX_DISTANCE + ? "lower-distance" + : "longer-prefix"); - zebra_routemap_config_write_protocol(vty); + zebra_routemap_config_write_protocol(vty); - return 1; + return 1; } /* IP node for static routes. */ -static struct cmd_node ip_node = { IP_NODE, "", 1 }; -static struct cmd_node protocol_node = { PROTOCOL_NODE, "", 1 }; +static struct cmd_node ip_node = {IP_NODE, "", 1}; +static struct cmd_node protocol_node = {PROTOCOL_NODE, "", 1}; /* Route VTY. */ -void -zebra_vty_init (void) -{ - install_node (&ip_node, zebra_ip_config); - install_node (&protocol_node, config_write_protocol); - - install_element (CONFIG_NODE, &allow_external_route_update_cmd); - install_element (CONFIG_NODE, &no_allow_external_route_update_cmd); - install_element (CONFIG_NODE, &ip_mroute_dist_cmd); - install_element (CONFIG_NODE, &no_ip_mroute_dist_cmd); - install_element (CONFIG_NODE, &ip_multicast_mode_cmd); - install_element (CONFIG_NODE, &no_ip_multicast_mode_cmd); - install_element (CONFIG_NODE, &ip_route_cmd); - install_element (CONFIG_NODE, &ip_route_flags_cmd); - install_element (CONFIG_NODE, &ip_route_mask_cmd); - install_element (CONFIG_NODE, &ip_route_mask_flags_cmd); - install_element (CONFIG_NODE, &no_ip_route_cmd); - install_element (CONFIG_NODE, &no_ip_route_mask_cmd); - install_element (CONFIG_NODE, &ip_zebra_import_table_distance_cmd); - install_element (CONFIG_NODE, &no_ip_zebra_import_table_cmd); - - install_element (VIEW_NODE, &show_vrf_cmd); - install_element (VIEW_NODE, &show_ip_route_cmd); - install_element (VIEW_NODE, &show_ip_nht_cmd); - install_element (VIEW_NODE, &show_ip_nht_vrf_all_cmd); - install_element (VIEW_NODE, &show_ipv6_nht_cmd); - install_element (VIEW_NODE, &show_ipv6_nht_vrf_all_cmd); - install_element (VIEW_NODE, &show_ip_route_addr_cmd); - install_element (VIEW_NODE, &show_ip_route_prefix_cmd); - install_element (VIEW_NODE, &show_ip_route_summary_cmd); - install_element (VIEW_NODE, &show_ip_route_summary_prefix_cmd); - - install_element (VIEW_NODE, &show_ip_rpf_cmd); - install_element (VIEW_NODE, &show_ip_rpf_addr_cmd); - - /* Commands for VRF */ - - install_element (CONFIG_NODE, &no_ip_route_flags_cmd); - install_element (CONFIG_NODE, &no_ip_route_mask_flags_cmd); - - install_element (VIEW_NODE, &show_ip_route_vrf_all_addr_cmd); - install_element (VIEW_NODE, &show_ip_route_vrf_all_prefix_cmd); - install_element (VIEW_NODE, &show_ip_route_vrf_all_summary_cmd); - install_element (VIEW_NODE, &show_ip_route_vrf_all_summary_prefix_cmd); - - install_element (CONFIG_NODE, &ipv6_route_cmd); - install_element (CONFIG_NODE, &ipv6_route_flags_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_flags_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_flags_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_cmd); - install_element (CONFIG_NODE, &ip_nht_default_route_cmd); - install_element (CONFIG_NODE, &no_ip_nht_default_route_cmd); - install_element (CONFIG_NODE, &ipv6_nht_default_route_cmd); - install_element (CONFIG_NODE, &no_ipv6_nht_default_route_cmd); - install_element (VIEW_NODE, &show_ipv6_route_cmd); - install_element (VIEW_NODE, &show_ipv6_route_summary_cmd); - install_element (VIEW_NODE, &show_ipv6_route_summary_prefix_cmd); - install_element (VIEW_NODE, &show_ipv6_route_addr_cmd); - install_element (VIEW_NODE, &show_ipv6_route_prefix_cmd); - install_element (VIEW_NODE, &show_ipv6_mroute_cmd); - - /* Commands for VRF */ - install_element (VIEW_NODE, &show_ipv6_route_vrf_all_summary_cmd); - install_element (VIEW_NODE, &show_ipv6_route_vrf_all_summary_prefix_cmd); - install_element (VIEW_NODE, &show_ipv6_route_vrf_all_addr_cmd); - install_element (VIEW_NODE, &show_ipv6_route_vrf_all_prefix_cmd); - - install_element (VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd); - - install_element (VIEW_NODE, &show_evpn_vni_cmd); - install_element (VIEW_NODE, &show_evpn_vni_vni_cmd); - install_element (VIEW_NODE, &show_evpn_mac_vni_cmd); - install_element (VIEW_NODE, &show_evpn_mac_vni_all_cmd); - install_element (VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd); - install_element (VIEW_NODE, &show_evpn_mac_vni_mac_cmd); - install_element (VIEW_NODE, &show_evpn_mac_vni_vtep_cmd); - install_element (VIEW_NODE, &show_evpn_neigh_vni_cmd); - install_element (VIEW_NODE, &show_evpn_neigh_vni_all_cmd); - install_element (VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd); - install_element (VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd); +void zebra_vty_init(void) +{ + install_node(&ip_node, zebra_ip_config); + install_node(&protocol_node, config_write_protocol); + + install_element(CONFIG_NODE, &allow_external_route_update_cmd); + install_element(CONFIG_NODE, &no_allow_external_route_update_cmd); + install_element(CONFIG_NODE, &ip_mroute_dist_cmd); + install_element(CONFIG_NODE, &no_ip_mroute_dist_cmd); + install_element(CONFIG_NODE, &ip_multicast_mode_cmd); + install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd); + install_element(CONFIG_NODE, &ip_route_cmd); + install_element(CONFIG_NODE, &ip_route_flags_cmd); + install_element(CONFIG_NODE, &ip_route_mask_cmd); + install_element(CONFIG_NODE, &ip_route_mask_flags_cmd); + install_element(CONFIG_NODE, &no_ip_route_cmd); + install_element(CONFIG_NODE, &no_ip_route_mask_cmd); + install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd); + install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd); + + install_element(VIEW_NODE, &show_vrf_cmd); + install_element(VIEW_NODE, &show_ip_route_cmd); + install_element(VIEW_NODE, &show_ip_nht_cmd); + install_element(VIEW_NODE, &show_ip_nht_vrf_all_cmd); + install_element(VIEW_NODE, &show_ipv6_nht_cmd); + install_element(VIEW_NODE, &show_ipv6_nht_vrf_all_cmd); + install_element(VIEW_NODE, &show_ip_route_addr_cmd); + install_element(VIEW_NODE, &show_ip_route_prefix_cmd); + install_element(VIEW_NODE, &show_ip_route_summary_cmd); + install_element(VIEW_NODE, &show_ip_route_summary_prefix_cmd); + + install_element(VIEW_NODE, &show_ip_rpf_cmd); + install_element(VIEW_NODE, &show_ip_rpf_addr_cmd); + + /* Commands for VRF */ + + install_element(CONFIG_NODE, &no_ip_route_flags_cmd); + install_element(CONFIG_NODE, &no_ip_route_mask_flags_cmd); + + install_element(VIEW_NODE, &show_ip_route_vrf_all_addr_cmd); + install_element(VIEW_NODE, &show_ip_route_vrf_all_prefix_cmd); + install_element(VIEW_NODE, &show_ip_route_vrf_all_summary_cmd); + install_element(VIEW_NODE, &show_ip_route_vrf_all_summary_prefix_cmd); + + install_element(CONFIG_NODE, &ipv6_route_cmd); + install_element(CONFIG_NODE, &ipv6_route_flags_cmd); + install_element(CONFIG_NODE, &ipv6_route_ifname_cmd); + install_element(CONFIG_NODE, &ipv6_route_ifname_flags_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_flags_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_ifname_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_ifname_flags_cmd); + install_element(CONFIG_NODE, &ip_nht_default_route_cmd); + install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd); + install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd); + install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd); + install_element(VIEW_NODE, &show_ipv6_route_cmd); + install_element(VIEW_NODE, &show_ipv6_route_summary_cmd); + install_element(VIEW_NODE, &show_ipv6_route_summary_prefix_cmd); + install_element(VIEW_NODE, &show_ipv6_route_addr_cmd); + install_element(VIEW_NODE, &show_ipv6_route_prefix_cmd); + install_element(VIEW_NODE, &show_ipv6_mroute_cmd); + + /* Commands for VRF */ + install_element(VIEW_NODE, &show_ipv6_route_vrf_all_summary_cmd); + install_element(VIEW_NODE, &show_ipv6_route_vrf_all_summary_prefix_cmd); + install_element(VIEW_NODE, &show_ipv6_route_vrf_all_addr_cmd); + install_element(VIEW_NODE, &show_ipv6_route_vrf_all_prefix_cmd); + + install_element(VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd); + + install_element(VIEW_NODE, &show_evpn_vni_cmd); + install_element(VIEW_NODE, &show_evpn_vni_vni_cmd); + install_element(VIEW_NODE, &show_evpn_mac_vni_cmd); + install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd); + install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd); + install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd); + install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd); + install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd); + install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd); + install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd); + install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd); } diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 7df31cb93..c96f07306 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -47,140 +47,90 @@ #include "zebra/zebra_memory.h" #include "zebra/zebra_l2.h" -DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash"); +DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash"); DEFINE_MTYPE_STATIC(ZEBRA, ZVNI_VTEP, "VNI remote VTEP"); -DEFINE_MTYPE_STATIC(ZEBRA, MAC, "VNI MAC"); -DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "VNI Neighbor"); +DEFINE_MTYPE_STATIC(ZEBRA, MAC, "VNI MAC"); +DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "VNI Neighbor"); /* definitions */ /* static function declarations */ -static void -zvni_print_neigh (zebra_neigh_t *n, void *ctxt); -static void -zvni_print_neigh_hash (struct hash_backet *backet, void *ctxt); -static void -zvni_print_neigh_hash_all_vni (struct hash_backet *backet, void *ctxt); -static void -zvni_print_mac (zebra_mac_t *mac, void *ctxt); -static void -zvni_print_mac_hash (struct hash_backet *backet, void *ctxt); -static void -zvni_print_mac_hash_all_vni (struct hash_backet *backet, void *ctxt); -static void -zvni_print (zebra_vni_t *zvni, void *ctxt); -static void -zvni_print_hash (struct hash_backet *backet, void *ctxt); - -static int -zvni_macip_send_msg_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ethaddr *macaddr, - struct ipaddr *ip, u_char sticky, - u_int16_t cmd); -static unsigned int -neigh_hash_keymake (void *p); -static int -neigh_cmp (const void *p1, const void *p2); -static void * -zvni_neigh_alloc (void *p); -static zebra_neigh_t * -zvni_neigh_add (zebra_vni_t *zvni, struct ipaddr *ip); -static int -zvni_neigh_del (zebra_vni_t *zvni, zebra_neigh_t *n); -static int -zvni_neigh_del_hash_entry (struct hash_backet *backet, void *arg); -static void -zvni_neigh_del_from_vtep (zebra_vni_t *zvni, int uninstall, - struct in_addr *r_vtep_ip); -static void -zvni_neigh_del_all (struct zebra_vrf *zvrf, zebra_vni_t *zvni, - int uninstall, int upd_client, u_int32_t flags); -static zebra_neigh_t * -zvni_neigh_lookup (zebra_vni_t *zvni, struct ipaddr *ip); -static int -zvni_neigh_send_add_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ipaddr *ip, struct ethaddr *macaddr); -static int -zvni_neigh_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ipaddr *ip, struct ethaddr *macaddr); -static int -zvni_neigh_install (zebra_vni_t *zvni, zebra_neigh_t *n); -static int -zvni_neigh_uninstall (zebra_vni_t *zvni, zebra_neigh_t *n); -static zebra_vni_t * -zvni_map_svi (struct interface *ifp, struct interface *br_if); -static struct interface * -zvni_map_to_svi (struct zebra_vrf *zvrf, vlanid_t vid, - struct interface *br_if); - -static unsigned int -mac_hash_keymake (void *p); -static int -mac_cmp (const void *p1, const void *p2); -static void * -zvni_mac_alloc (void *p); -static zebra_mac_t * -zvni_mac_add (zebra_vni_t *zvni, struct ethaddr *macaddr); -static int -zvni_mac_del (zebra_vni_t *zvni, zebra_mac_t *mac); -static int -zvni_mac_del_hash_entry (struct hash_backet *backet, void *arg); -static void -zvni_mac_del_from_vtep (zebra_vni_t *zvni, int uninstall, - struct in_addr *r_vtep_ip); -static void -zvni_mac_del_all (struct zebra_vrf *zvrf, zebra_vni_t *zvni, - int uninstall, int upd_client, u_int32_t flags); -static zebra_mac_t * -zvni_mac_lookup (zebra_vni_t *zvni, struct ethaddr *macaddr); -static int -zvni_mac_send_add_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ethaddr *macaddr, u_char sticky); -static int -zvni_mac_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ethaddr *macaddr, u_char sticky); -static zebra_vni_t * -zvni_map_vlan (struct interface *ifp, struct interface *br_if, vlanid_t vid); -static int -zvni_mac_install (zebra_vni_t *zvni, zebra_mac_t *mac); -static int -zvni_mac_uninstall (zebra_vni_t *zvni, zebra_mac_t *mac, int local); -static void -zvni_install_mac_hash (struct hash_backet *backet, void *ctxt); - -static unsigned int -vni_hash_keymake (void *p); -static int -vni_hash_cmp (const void *p1, const void *p2); -static void * -zvni_alloc (void *p); -static zebra_vni_t * -zvni_lookup (struct zebra_vrf *zvrf, vni_t vni); -static zebra_vni_t * -zvni_add (struct zebra_vrf *zvrf, vni_t vni); -static int -zvni_del (struct zebra_vrf *zvrf, zebra_vni_t *zvni); -static int -zvni_send_add_to_client (struct zebra_vrf *zvrf, zebra_vni_t *zvni); -static int -zvni_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni); -static void -zvni_build_hash_table (struct zebra_vrf *zvrf); -static int -zvni_vtep_match (struct in_addr *vtep_ip, zebra_vtep_t *zvtep); -static zebra_vtep_t * -zvni_vtep_find (zebra_vni_t *zvni, struct in_addr *vtep_ip); -static zebra_vtep_t * -zvni_vtep_add (zebra_vni_t *zvni, struct in_addr *vtep_ip); -static int -zvni_vtep_del (zebra_vni_t *zvni, zebra_vtep_t *zvtep); -static int -zvni_vtep_del_all (zebra_vni_t *zvni, int uninstall); -static int -zvni_vtep_install (zebra_vni_t *zvni, struct in_addr *vtep_ip); -static int -zvni_vtep_uninstall (zebra_vni_t *zvni, struct in_addr *vtep_ip); +static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt); +static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt); +static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet, + void *ctxt); +static void zvni_print_mac(zebra_mac_t *mac, void *ctxt); +static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt); +static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt); +static void zvni_print(zebra_vni_t *zvni, void *ctxt); +static void zvni_print_hash(struct hash_backet *backet, void *ctxt); + +static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ethaddr *macaddr, + struct ipaddr *ip, u_char sticky, + u_int16_t cmd); +static unsigned int neigh_hash_keymake(void *p); +static int neigh_cmp(const void *p1, const void *p2); +static void *zvni_neigh_alloc(void *p); +static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip); +static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n); +static int zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg); +static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall, + struct in_addr *r_vtep_ip); +static void zvni_neigh_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni, + int uninstall, int upd_client, u_int32_t flags); +static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip); +static int zvni_neigh_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ipaddr *ip, + struct ethaddr *macaddr); +static int zvni_neigh_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ipaddr *ip, + struct ethaddr *macaddr); +static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n); +static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n); +static zebra_vni_t *zvni_map_svi(struct interface *ifp, + struct interface *br_if); +static struct interface *zvni_map_to_svi(struct zebra_vrf *zvrf, vlanid_t vid, + struct interface *br_if); + +static unsigned int mac_hash_keymake(void *p); +static int mac_cmp(const void *p1, const void *p2); +static void *zvni_mac_alloc(void *p); +static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr); +static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac); +static int zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg); +static void zvni_mac_del_from_vtep(zebra_vni_t *zvni, int uninstall, + struct in_addr *r_vtep_ip); +static void zvni_mac_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni, + int uninstall, int upd_client, u_int32_t flags); +static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *macaddr); +static int zvni_mac_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ethaddr *macaddr, u_char sticky); +static int zvni_mac_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ethaddr *macaddr, u_char sticky); +static zebra_vni_t *zvni_map_vlan(struct interface *ifp, + struct interface *br_if, vlanid_t vid); +static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac); +static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac, int local); +static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt); + +static unsigned int vni_hash_keymake(void *p); +static int vni_hash_cmp(const void *p1, const void *p2); +static void *zvni_alloc(void *p); +static zebra_vni_t *zvni_lookup(struct zebra_vrf *zvrf, vni_t vni); +static zebra_vni_t *zvni_add(struct zebra_vrf *zvrf, vni_t vni); +static int zvni_del(struct zebra_vrf *zvrf, zebra_vni_t *zvni); +static int zvni_send_add_to_client(struct zebra_vrf *zvrf, zebra_vni_t *zvni); +static int zvni_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni); +static void zvni_build_hash_table(struct zebra_vrf *zvrf); +static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep); +static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip); +static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip); +static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep); +static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall); +static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip); +static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip); /* Private functions */ @@ -190,893 +140,830 @@ zvni_vtep_uninstall (zebra_vni_t *zvni, struct in_addr *vtep_ip); * display - just because we're dealing with IPv6 addresses that can * widely vary. */ -static void -zvni_find_neigh_addr_width (struct hash_backet *backet, void *ctxt) +static void zvni_find_neigh_addr_width(struct hash_backet *backet, void *ctxt) { - zebra_neigh_t *n; - char buf[INET6_ADDRSTRLEN]; - struct neigh_walk_ctx *wctx = ctxt; - int width; + zebra_neigh_t *n; + char buf[INET6_ADDRSTRLEN]; + struct neigh_walk_ctx *wctx = ctxt; + int width; - n = (zebra_neigh_t *) backet->data; - if (!n) - return; + n = (zebra_neigh_t *)backet->data; + if (!n) + return; - ipaddr2str (&n->ip, buf, sizeof(buf)), - width = strlen (buf); - if (width > wctx->addr_width) - wctx->addr_width = width; + ipaddr2str(&n->ip, buf, sizeof(buf)), width = strlen(buf); + if (width > wctx->addr_width) + wctx->addr_width = width; } /* * Print a specific neighbor entry. */ -static void -zvni_print_neigh (zebra_neigh_t *n, void *ctxt) +static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt) { - struct vty *vty; - char buf1[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; + struct vty *vty; + char buf1[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; - ipaddr2str (&n->ip, buf2, sizeof(buf2)), - vty = (struct vty *) ctxt; - vty_out(vty, "IP: %s\n", - ipaddr2str (&n->ip, buf2, sizeof(buf2))); - vty_out(vty, " MAC: %s", prefix_mac2str (&n->emac, buf1, sizeof (buf1))); - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) - vty_out(vty, " Remote VTEP: %s", inet_ntoa (n->r_vtep_ip)); - vty_out(vty, "\n"); + ipaddr2str(&n->ip, buf2, sizeof(buf2)), vty = (struct vty *)ctxt; + vty_out(vty, "IP: %s\n", ipaddr2str(&n->ip, buf2, sizeof(buf2))); + vty_out(vty, " MAC: %s", prefix_mac2str(&n->emac, buf1, sizeof(buf1))); + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) + vty_out(vty, " Remote VTEP: %s", inet_ntoa(n->r_vtep_ip)); + vty_out(vty, "\n"); } /* * Print neighbor hash entry - called for display of all neighbors. */ -static void -zvni_print_neigh_hash (struct hash_backet *backet, void *ctxt) -{ - struct vty *vty; - zebra_neigh_t *n; - char buf1[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - struct neigh_walk_ctx *wctx = ctxt; - - vty = wctx->vty; - n = (zebra_neigh_t *) backet->data; - if (!n) - return; - - prefix_mac2str (&n->emac, buf1, sizeof (buf1)); - ipaddr2str (&n->ip, buf2, sizeof(buf2)); - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) && - !(wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)) - { - vty_out(vty, "%*s %-6s %-17s\n", - -wctx->addr_width, buf2, "local", buf1); - wctx->count++; - } - else - { - if (wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) - { - if (IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip)) - { - if (wctx->count == 0) - vty_out(vty, "%*s %-6s %-17s %-21s\n", - -wctx->addr_width, "Neighbor", "Type", "MAC", - "Remote VTEP"); - vty_out(vty, "%*s %-6s %-17s %-21s\n", - -wctx->addr_width, buf2, "remote", buf1, - inet_ntoa (n->r_vtep_ip)); - wctx->count++; - } - } - else - { - vty_out(vty, "%*s %-6s %-17s %-21s\n", - -wctx->addr_width, buf2, "remote", buf1, - inet_ntoa (n->r_vtep_ip)); - wctx->count++; - } - } +static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt) +{ + struct vty *vty; + zebra_neigh_t *n; + char buf1[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + struct neigh_walk_ctx *wctx = ctxt; + + vty = wctx->vty; + n = (zebra_neigh_t *)backet->data; + if (!n) + return; + + prefix_mac2str(&n->emac, buf1, sizeof(buf1)); + ipaddr2str(&n->ip, buf2, sizeof(buf2)); + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) + && !(wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)) { + vty_out(vty, "%*s %-6s %-17s\n", -wctx->addr_width, buf2, + "local", buf1); + wctx->count++; + } else { + if (wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) { + if (IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip)) { + if (wctx->count == 0) + vty_out(vty, "%*s %-6s %-17s %-21s\n", + -wctx->addr_width, "Neighbor", + "Type", "MAC", "Remote VTEP"); + vty_out(vty, "%*s %-6s %-17s %-21s\n", + -wctx->addr_width, buf2, "remote", buf1, + inet_ntoa(n->r_vtep_ip)); + wctx->count++; + } + } else { + vty_out(vty, "%*s %-6s %-17s %-21s\n", + -wctx->addr_width, buf2, "remote", buf1, + inet_ntoa(n->r_vtep_ip)); + wctx->count++; + } + } } /* * Print neighbors for all VNI. */ -static void -zvni_print_neigh_hash_all_vni (struct hash_backet *backet, void *ctxt) +static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet, + void *ctxt) { - struct vty *vty; - zebra_vni_t *zvni; - u_int32_t num_neigh; - struct neigh_walk_ctx wctx; + struct vty *vty; + zebra_vni_t *zvni; + u_int32_t num_neigh; + struct neigh_walk_ctx wctx; - vty = (struct vty *) ctxt; - zvni = (zebra_vni_t *) backet->data; - if (!zvni) - return; + vty = (struct vty *)ctxt; + zvni = (zebra_vni_t *)backet->data; + if (!zvni) + return; - num_neigh = hashcount(zvni->neigh_table); - vty_out(vty, "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n", - zvni->vni, num_neigh); - if (!num_neigh) - return; + num_neigh = hashcount(zvni->neigh_table); + vty_out(vty, "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n", + zvni->vni, num_neigh); + if (!num_neigh) + return; - /* Since we have IPv6 addresses to deal with which can vary widely in - * size, we try to be a bit more elegant in display by first computing - * the maximum width. - */ - memset (&wctx, 0, sizeof (struct neigh_walk_ctx)); - wctx.zvni = zvni; - wctx.vty = vty; - wctx.addr_width = 15; - hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); + /* Since we have IPv6 addresses to deal with which can vary widely in + * size, we try to be a bit more elegant in display by first computing + * the maximum width. + */ + memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); + wctx.zvni = zvni; + wctx.vty = vty; + wctx.addr_width = 15; + hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); - vty_out(vty, "%*s %-6s %-17s %-21s\n", - -wctx.addr_width, "IP", "Type", "MAC", - "Remote VTEP"); - hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); + vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP", "Type", + "MAC", "Remote VTEP"); + hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); } /* * Print a specific MAC entry. */ -static void -zvni_print_mac (zebra_mac_t *mac, void *ctxt) -{ - struct vty *vty; - char buf1[20]; - - vty = (struct vty *) ctxt; - vty_out(vty, "MAC: %s", - prefix_mac2str (&mac->macaddr, buf1, sizeof (buf1))); - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) - { - struct zebra_ns *zns; - struct interface *ifp; - ifindex_t ifindex; - - ifindex = mac->fwd_info.local.ifindex; - zns = zebra_ns_lookup (NS_DEFAULT); - ifp = if_lookup_by_index_per_ns (zns, ifindex); - if (!ifp) // unexpected - return; - vty_out(vty, " Intf: %s(%u)", ifp->name, ifindex); - if (mac->fwd_info.local.vid) - vty_out(vty, " VLAN: %u", mac->fwd_info.local.vid); - } - else - { - vty_out(vty, " Remote VTEP: %s", - inet_ntoa (mac->fwd_info.r_vtep_ip)); - } - vty_out(vty, " ARP ref: %u", mac->neigh_refcnt); - vty_out(vty, "\n"); +static void zvni_print_mac(zebra_mac_t *mac, void *ctxt) +{ + struct vty *vty; + char buf1[20]; + + vty = (struct vty *)ctxt; + vty_out(vty, "MAC: %s", + prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1))); + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { + struct zebra_ns *zns; + struct interface *ifp; + ifindex_t ifindex; + + ifindex = mac->fwd_info.local.ifindex; + zns = zebra_ns_lookup(NS_DEFAULT); + ifp = if_lookup_by_index_per_ns(zns, ifindex); + if (!ifp) // unexpected + return; + vty_out(vty, " Intf: %s(%u)", ifp->name, ifindex); + if (mac->fwd_info.local.vid) + vty_out(vty, " VLAN: %u", mac->fwd_info.local.vid); + } else { + vty_out(vty, " Remote VTEP: %s", + inet_ntoa(mac->fwd_info.r_vtep_ip)); + } + vty_out(vty, " ARP ref: %u", mac->neigh_refcnt); + vty_out(vty, "\n"); } /* * Print MAC hash entry - called for display of all MACs. */ -static void -zvni_print_mac_hash (struct hash_backet *backet, void *ctxt) -{ - struct vty *vty; - zebra_mac_t *mac; - char buf1[20]; - struct mac_walk_ctx *wctx = ctxt; - - vty = wctx->vty; - mac = (zebra_mac_t *) backet->data; - if (!mac) - return; - - prefix_mac2str (&mac->macaddr, buf1, sizeof (buf1)); - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) && - !(wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)) - { - struct zebra_ns *zns; - ifindex_t ifindex; - struct interface *ifp; - vlanid_t vid; - - zns = zebra_ns_lookup (NS_DEFAULT); - ifindex = mac->fwd_info.local.ifindex; - ifp = if_lookup_by_index_per_ns (zns, ifindex); - if (!ifp) // unexpected - return; - vid = mac->fwd_info.local.vid; - vty_out(vty, "%-17s %-6s %-21s", - buf1, "local", ifp->name); - if (vid) - vty_out(vty, " %-5u", vid); - vty_out(vty, "\n"); - wctx->count++; - } - else - { - if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) - { - if (IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, - &wctx->r_vtep_ip)) - { - if (wctx->count == 0) - { - vty_out(vty, "\nVNI %u", - wctx->zvni->vni); - vty_out(vty, "%-17s %-6s %-21s %-5s", - "MAC", "Type", "Intf/Remote VTEP", - "VLAN"); - } - vty_out(vty, "%-17s %-6s %-21s", - buf1, "remote", - inet_ntoa (mac->fwd_info.r_vtep_ip)); - wctx->count++; - } - } - else - { - vty_out(vty, "%-17s %-6s %-21s", - buf1, "remote", - inet_ntoa (mac->fwd_info.r_vtep_ip)); - wctx->count++; - } - } - +static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt) +{ + struct vty *vty; + zebra_mac_t *mac; + char buf1[20]; + struct mac_walk_ctx *wctx = ctxt; + + vty = wctx->vty; + mac = (zebra_mac_t *)backet->data; + if (!mac) + return; + + prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)); + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) + && !(wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)) { + struct zebra_ns *zns; + ifindex_t ifindex; + struct interface *ifp; + vlanid_t vid; + + zns = zebra_ns_lookup(NS_DEFAULT); + ifindex = mac->fwd_info.local.ifindex; + ifp = if_lookup_by_index_per_ns(zns, ifindex); + if (!ifp) // unexpected + return; + vid = mac->fwd_info.local.vid; + vty_out(vty, "%-17s %-6s %-21s", buf1, "local", ifp->name); + if (vid) + vty_out(vty, " %-5u", vid); + vty_out(vty, "\n"); + wctx->count++; + } else { + if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) { + if (IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, + &wctx->r_vtep_ip)) { + if (wctx->count == 0) { + vty_out(vty, "\nVNI %u", + wctx->zvni->vni); + vty_out(vty, "%-17s %-6s %-21s %-5s", + "MAC", "Type", + "Intf/Remote VTEP", "VLAN"); + } + vty_out(vty, "%-17s %-6s %-21s", buf1, "remote", + inet_ntoa(mac->fwd_info.r_vtep_ip)); + wctx->count++; + } + } else { + vty_out(vty, "%-17s %-6s %-21s", buf1, "remote", + inet_ntoa(mac->fwd_info.r_vtep_ip)); + wctx->count++; + } + } } /* * Print MACs for all VNI. */ -static void -zvni_print_mac_hash_all_vni (struct hash_backet *backet, void *ctxt) +static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt) { - struct vty *vty; - zebra_vni_t *zvni; - u_int32_t num_macs; - struct mac_walk_ctx *wctx = ctxt; + struct vty *vty; + zebra_vni_t *zvni; + u_int32_t num_macs; + struct mac_walk_ctx *wctx = ctxt; - vty = (struct vty *) wctx->vty; + vty = (struct vty *)wctx->vty; - zvni = (zebra_vni_t *) backet->data; - if (!zvni) - return; - wctx->zvni = zvni; + zvni = (zebra_vni_t *)backet->data; + if (!zvni) + return; + wctx->zvni = zvni; - /*We are iterating over a new VNI, set the count to 0*/ - wctx->count = 0; + /*We are iterating over a new VNI, set the count to 0*/ + wctx->count = 0; - num_macs = hashcount(zvni->mac_table); - if (!num_macs) - return; - if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) - { - vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n", - zvni->vni, num_macs); - vty_out(vty, "%-17s %-6s %-21s %-5s\n", - "MAC", "Type", "Intf/Remote VTEP", "VLAN"); - } + num_macs = hashcount(zvni->mac_table); + if (!num_macs) + return; + if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) { + vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n", + zvni->vni, num_macs); + vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type", + "Intf/Remote VTEP", "VLAN"); + } - hash_iterate(zvni->mac_table, zvni_print_mac_hash, wctx); + hash_iterate(zvni->mac_table, zvni_print_mac_hash, wctx); } /* * Print a specific VNI entry. */ -static void -zvni_print (zebra_vni_t *zvni, void *ctxt) -{ - struct vty *vty; - zebra_vtep_t *zvtep; - u_int32_t num_macs; - u_int32_t num_neigh; - - vty = (struct vty *) ctxt; - - vty_out(vty, "VNI: %u\n", zvni->vni); - if (!zvni->vxlan_if) - { // unexpected - vty_out(vty, " VxLAN interface: unknown\n"); - return; - } - vty_out(vty, " VxLAN interface: %s ifIndex: %u VTEP IP: %s\n", - zvni->vxlan_if->name, zvni->vxlan_if->ifindex, - inet_ntoa(zvni->local_vtep_ip)); - - if (!zvni->vteps) - { - vty_out(vty, " No remote VTEPs known for this VNI\n"); - } - else - { - vty_out(vty, " Remote VTEPs for this VNI:\n"); - for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) - vty_out(vty, " %s\n", - inet_ntoa (zvtep->vtep_ip)); - } - num_macs = hashcount(zvni->mac_table); - vty_out(vty, " Number of MACs (local and remote) known for this VNI: %u\n", - num_macs); - num_neigh = hashcount(zvni->neigh_table); - vty_out(vty, " Number of ARPs (IPv4 and IPv6, local and remote) " - "known for this VNI: %u", num_neigh); +static void zvni_print(zebra_vni_t *zvni, void *ctxt) +{ + struct vty *vty; + zebra_vtep_t *zvtep; + u_int32_t num_macs; + u_int32_t num_neigh; + + vty = (struct vty *)ctxt; + + vty_out(vty, "VNI: %u\n", zvni->vni); + if (!zvni->vxlan_if) { // unexpected + vty_out(vty, " VxLAN interface: unknown\n"); + return; + } + vty_out(vty, " VxLAN interface: %s ifIndex: %u VTEP IP: %s\n", + zvni->vxlan_if->name, zvni->vxlan_if->ifindex, + inet_ntoa(zvni->local_vtep_ip)); + + if (!zvni->vteps) { + vty_out(vty, " No remote VTEPs known for this VNI\n"); + } else { + vty_out(vty, " Remote VTEPs for this VNI:\n"); + for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) + vty_out(vty, " %s\n", inet_ntoa(zvtep->vtep_ip)); + } + num_macs = hashcount(zvni->mac_table); + vty_out(vty, + " Number of MACs (local and remote) known for this VNI: %u\n", + num_macs); + num_neigh = hashcount(zvni->neigh_table); + vty_out(vty, + " Number of ARPs (IPv4 and IPv6, local and remote) " + "known for this VNI: %u", + num_neigh); } /* * Print a VNI hash entry - called for display of all VNIs. */ -static void -zvni_print_hash (struct hash_backet *backet, void *ctxt) +static void zvni_print_hash(struct hash_backet *backet, void *ctxt) { - struct vty *vty; - zebra_vni_t *zvni; - zebra_vtep_t *zvtep; - u_int32_t num_vteps = 0; - u_int32_t num_macs = 0; - u_int32_t num_neigh = 0; + struct vty *vty; + zebra_vni_t *zvni; + zebra_vtep_t *zvtep; + u_int32_t num_vteps = 0; + u_int32_t num_macs = 0; + u_int32_t num_neigh = 0; - vty = (struct vty *) ctxt; - zvni = (zebra_vni_t *) backet->data; - if (!zvni) - return; + vty = (struct vty *)ctxt; + zvni = (zebra_vni_t *)backet->data; + if (!zvni) + return; - zvtep = zvni->vteps; - while (zvtep) - { - num_vteps++; - zvtep = zvtep->next; - } + zvtep = zvni->vteps; + while (zvtep) { + num_vteps++; + zvtep = zvtep->next; + } - num_macs = hashcount(zvni->mac_table); - num_neigh = hashcount(zvni->neigh_table); - vty_out(vty, "%-10u %-21s %-15s %-8u %-8u %-15u\n", - zvni->vni, - zvni->vxlan_if ? zvni->vxlan_if->name : "unknown", - inet_ntoa(zvni->local_vtep_ip), - num_macs, num_neigh, num_vteps); + num_macs = hashcount(zvni->mac_table); + num_neigh = hashcount(zvni->neigh_table); + vty_out(vty, "%-10u %-21s %-15s %-8u %-8u %-15u\n", zvni->vni, + zvni->vxlan_if ? zvni->vxlan_if->name : "unknown", + inet_ntoa(zvni->local_vtep_ip), num_macs, num_neigh, num_vteps); } /* * Inform BGP about local MACIP. */ -static int -zvni_macip_send_msg_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ethaddr *macaddr, - struct ipaddr *ip, u_char sticky, - u_int16_t cmd) -{ - struct zserv *client; - struct stream *s; - int ipa_len; - char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - - client = zebra_find_client (ZEBRA_ROUTE_BGP); - /* BGP may not be running. */ - if (!client) - return 0; - - s = client->obuf; - stream_reset (s); - - zserv_create_header (s, cmd, zvrf_id (zvrf)); - stream_putl (s, vni); - stream_put (s, macaddr->octet, ETHER_ADDR_LEN); - if (ip) - { - ipa_len = 0; - if (IS_IPADDR_V4(ip)) - ipa_len = IPV4_MAX_BYTELEN; - else if (IS_IPADDR_V6(ip)) - ipa_len = IPV6_MAX_BYTELEN; - - stream_putl (s, ipa_len); /* IP address length */ - if (ipa_len) - stream_put (s, &ip->ip.addr, ipa_len); /* IP address */ - } - else - stream_putl (s, 0); /* Just MAC. */ - - stream_putc (s, sticky); /* Sticky MAC? */ - - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Send MACIP %s %sMAC %s IP %s VNI %u to %s", - zvrf_id (zvrf), (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", - sticky ? "sticky " : "", - prefix_mac2str (macaddr, buf, sizeof (buf)), - ipaddr2str (ip, buf2, sizeof(buf2)), vni, - zebra_route_string (client->proto)); - - if (cmd == ZEBRA_MACIP_ADD) - client->macipadd_cnt++; - else - client->macipdel_cnt++; - - return zebra_server_send_message(client); +static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ethaddr *macaddr, + struct ipaddr *ip, u_char sticky, + u_int16_t cmd) +{ + struct zserv *client; + struct stream *s; + int ipa_len; + char buf[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + + client = zebra_find_client(ZEBRA_ROUTE_BGP); + /* BGP may not be running. */ + if (!client) + return 0; + + s = client->obuf; + stream_reset(s); + + zserv_create_header(s, cmd, zvrf_id(zvrf)); + stream_putl(s, vni); + stream_put(s, macaddr->octet, ETHER_ADDR_LEN); + if (ip) { + ipa_len = 0; + if (IS_IPADDR_V4(ip)) + ipa_len = IPV4_MAX_BYTELEN; + else if (IS_IPADDR_V6(ip)) + ipa_len = IPV6_MAX_BYTELEN; + + stream_putl(s, ipa_len); /* IP address length */ + if (ipa_len) + stream_put(s, &ip->ip.addr, ipa_len); /* IP address */ + } else + stream_putl(s, 0); /* Just MAC. */ + + stream_putc(s, sticky); /* Sticky MAC? */ + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Send MACIP %s %sMAC %s IP %s VNI %u to %s", + zvrf_id(zvrf), + (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", + sticky ? "sticky " : "", + prefix_mac2str(macaddr, buf, sizeof(buf)), + ipaddr2str(ip, buf2, sizeof(buf2)), vni, + zebra_route_string(client->proto)); + + if (cmd == ZEBRA_MACIP_ADD) + client->macipadd_cnt++; + else + client->macipdel_cnt++; + + return zebra_server_send_message(client); } /* * Make hash key for neighbors. */ -static unsigned int -neigh_hash_keymake (void *p) +static unsigned int neigh_hash_keymake(void *p) { - zebra_neigh_t *n = p; - struct ipaddr *ip = &n->ip; + zebra_neigh_t *n = p; + struct ipaddr *ip = &n->ip; - if (IS_IPADDR_V4(ip)) - return jhash_1word (ip->ipaddr_v4.s_addr, 0); + if (IS_IPADDR_V4(ip)) + return jhash_1word(ip->ipaddr_v4.s_addr, 0); - return jhash2 (ip->ipaddr_v6.s6_addr32, - ZEBRA_NUM_OF(ip->ipaddr_v6.s6_addr32), 0); + return jhash2(ip->ipaddr_v6.s6_addr32, + ZEBRA_NUM_OF(ip->ipaddr_v6.s6_addr32), 0); } /* * Compare two neighbor hash structures. */ -static int -neigh_cmp (const void *p1, const void *p2) +static int neigh_cmp(const void *p1, const void *p2) { - const zebra_neigh_t *n1 = p1; - const zebra_neigh_t *n2 = p2; + const zebra_neigh_t *n1 = p1; + const zebra_neigh_t *n2 = p2; - if (n1 == NULL && n2 == NULL) - return 1; + if (n1 == NULL && n2 == NULL) + return 1; - if (n1 == NULL || n2 == NULL) - return 0; + if (n1 == NULL || n2 == NULL) + return 0; - return (memcmp(&n1->ip, &n2->ip, sizeof (struct ipaddr)) == 0); + return (memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr)) == 0); } /* * Callback to allocate neighbor hash entry. */ -static void * -zvni_neigh_alloc (void *p) +static void *zvni_neigh_alloc(void *p) { - const zebra_neigh_t *tmp_n = p; - zebra_neigh_t *n; + const zebra_neigh_t *tmp_n = p; + zebra_neigh_t *n; - n = XCALLOC (MTYPE_NEIGH, sizeof(zebra_neigh_t)); - *n = *tmp_n; + n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t)); + *n = *tmp_n; - return ((void *)n); + return ((void *)n); } /* * Add neighbor entry. */ -static zebra_neigh_t * -zvni_neigh_add (zebra_vni_t *zvni, struct ipaddr *ip) +static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip) { - zebra_neigh_t tmp_n; - zebra_neigh_t *n = NULL; + zebra_neigh_t tmp_n; + zebra_neigh_t *n = NULL; - memset (&tmp_n, 0, sizeof (zebra_neigh_t)); - memcpy (&tmp_n.ip, ip, sizeof (struct ipaddr)); - n = hash_get (zvni->neigh_table, &tmp_n, zvni_neigh_alloc); - assert (n); + memset(&tmp_n, 0, sizeof(zebra_neigh_t)); + memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr)); + n = hash_get(zvni->neigh_table, &tmp_n, zvni_neigh_alloc); + assert(n); - return n; + return n; } /* * Delete neighbor entry. */ -static int -zvni_neigh_del (zebra_vni_t *zvni, zebra_neigh_t *n) +static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n) { - zebra_neigh_t *tmp_n; + zebra_neigh_t *tmp_n; - /* Free the VNI hash entry and allocated memory. */ - tmp_n = hash_release (zvni->neigh_table, n); - if (tmp_n) - XFREE(MTYPE_NEIGH, tmp_n); + /* Free the VNI hash entry and allocated memory. */ + tmp_n = hash_release(zvni->neigh_table, n); + if (tmp_n) + XFREE(MTYPE_NEIGH, tmp_n); - return 0; + return 0; } /* * Free neighbor hash entry (callback) */ -static int -zvni_neigh_del_hash_entry (struct hash_backet *backet, void *arg) +static int zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg) { - struct neigh_walk_ctx *wctx = arg; - zebra_neigh_t *n = backet->data; + struct neigh_walk_ctx *wctx = arg; + zebra_neigh_t *n = backet->data; - if (((wctx->flags & DEL_LOCAL_NEIGH) && (n->flags & ZEBRA_NEIGH_LOCAL)) || - ((wctx->flags & DEL_REMOTE_NEIGH) && (n->flags & ZEBRA_NEIGH_REMOTE)) || - ((wctx->flags & DEL_REMOTE_NEIGH_FROM_VTEP) && - (n->flags & ZEBRA_NEIGH_REMOTE) && - IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip) - )) - { - if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL)) - zvni_neigh_send_del_to_client (wctx->zvrf, wctx->zvni->vni, &n->ip, - &n->emac); + if (((wctx->flags & DEL_LOCAL_NEIGH) && (n->flags & ZEBRA_NEIGH_LOCAL)) + || ((wctx->flags & DEL_REMOTE_NEIGH) + && (n->flags & ZEBRA_NEIGH_REMOTE)) + || ((wctx->flags & DEL_REMOTE_NEIGH_FROM_VTEP) + && (n->flags & ZEBRA_NEIGH_REMOTE) + && IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) { + if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL)) + zvni_neigh_send_del_to_client( + wctx->zvrf, wctx->zvni->vni, &n->ip, &n->emac); - if (wctx->uninstall) - zvni_neigh_uninstall (wctx->zvni, n); + if (wctx->uninstall) + zvni_neigh_uninstall(wctx->zvni, n); - return zvni_neigh_del (wctx->zvni, n); - } + return zvni_neigh_del(wctx->zvni, n); + } - return 0; + return 0; } /* * Delete all neighbor entries from specific VTEP for a particular VNI. */ -static void -zvni_neigh_del_from_vtep (zebra_vni_t *zvni, int uninstall, - struct in_addr *r_vtep_ip) +static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall, + struct in_addr *r_vtep_ip) { - struct neigh_walk_ctx wctx; + struct neigh_walk_ctx wctx; - if (!zvni->neigh_table) - return; + if (!zvni->neigh_table) + return; - memset (&wctx, 0, sizeof (struct neigh_walk_ctx)); - wctx.zvni = zvni; - wctx.uninstall = uninstall; - wctx.flags = DEL_REMOTE_NEIGH_FROM_VTEP; - wctx.r_vtep_ip = *r_vtep_ip; + memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); + wctx.zvni = zvni; + wctx.uninstall = uninstall; + wctx.flags = DEL_REMOTE_NEIGH_FROM_VTEP; + wctx.r_vtep_ip = *r_vtep_ip; - hash_iterate (zvni->neigh_table, - (void (*) (struct hash_backet *, void *)) - zvni_neigh_del_hash_entry, &wctx); + hash_iterate(zvni->neigh_table, + (void (*)(struct hash_backet *, + void *))zvni_neigh_del_hash_entry, + &wctx); } /* * Delete all neighbor entries for this VNI. */ -static void -zvni_neigh_del_all (struct zebra_vrf *zvrf, zebra_vni_t *zvni, - int uninstall, int upd_client, u_int32_t flags) +static void zvni_neigh_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni, + int uninstall, int upd_client, u_int32_t flags) { - struct neigh_walk_ctx wctx; + struct neigh_walk_ctx wctx; - if (!zvni->neigh_table) - return; + if (!zvni->neigh_table) + return; - memset (&wctx, 0, sizeof (struct neigh_walk_ctx)); - wctx.zvni = zvni; - wctx.zvrf = zvrf; - wctx.uninstall = uninstall; - wctx.upd_client = upd_client; - wctx.flags = flags; + memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); + wctx.zvni = zvni; + wctx.zvrf = zvrf; + wctx.uninstall = uninstall; + wctx.upd_client = upd_client; + wctx.flags = flags; - hash_iterate (zvni->neigh_table, - (void (*) (struct hash_backet *, void *)) - zvni_neigh_del_hash_entry, &wctx); + hash_iterate(zvni->neigh_table, + (void (*)(struct hash_backet *, + void *))zvni_neigh_del_hash_entry, + &wctx); } /* * Look up neighbor hash entry. */ -static zebra_neigh_t * -zvni_neigh_lookup (zebra_vni_t *zvni, struct ipaddr *ip) +static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip) { - zebra_neigh_t tmp; - zebra_neigh_t *n; + zebra_neigh_t tmp; + zebra_neigh_t *n; - memset (&tmp, 0, sizeof(tmp)); - memcpy (&tmp.ip, ip, sizeof (struct ipaddr)); - n = hash_lookup (zvni->neigh_table, &tmp); + memset(&tmp, 0, sizeof(tmp)); + memcpy(&tmp.ip, ip, sizeof(struct ipaddr)); + n = hash_lookup(zvni->neigh_table, &tmp); - return n; + return n; } /* * Inform BGP about local neighbor addition. */ -static int -zvni_neigh_send_add_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ipaddr *ip, struct ethaddr *macaddr) +static int zvni_neigh_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ipaddr *ip, + struct ethaddr *macaddr) { - return zvni_macip_send_msg_to_client (zvrf, vni, macaddr, ip, 0, - ZEBRA_MACIP_ADD); + return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, ip, 0, + ZEBRA_MACIP_ADD); } /* * Inform BGP about local neighbor deletion. */ -static int -zvni_neigh_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ipaddr *ip, struct ethaddr *macaddr) +static int zvni_neigh_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ipaddr *ip, + struct ethaddr *macaddr) { - return zvni_macip_send_msg_to_client (zvrf, vni, macaddr, ip, 0, - ZEBRA_MACIP_DEL); + return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, ip, 0, + ZEBRA_MACIP_DEL); } /* * Install remote neighbor into the kernel. */ -static int -zvni_neigh_install (zebra_vni_t *zvni, zebra_neigh_t *n) +static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n) { - struct zebra_vrf *zvrf; - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - struct interface *vlan_if; + struct zebra_vrf *zvrf; + struct zebra_if *zif; + struct zebra_l2info_vxlan *vxl; + struct interface *vlan_if; - if (!(n->flags & ZEBRA_NEIGH_REMOTE)) - return 0; + if (!(n->flags & ZEBRA_NEIGH_REMOTE)) + return 0; - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - assert(zvrf); - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - vxl = &zif->l2info.vxl; + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + assert(zvrf); + zif = zvni->vxlan_if->info; + if (!zif) + return -1; + vxl = &zif->l2info.vxl; - vlan_if = zvni_map_to_svi (zvrf, vxl->access_vlan, - zif->brslave_info.br_if); - if (!vlan_if) - return -1; + vlan_if = zvni_map_to_svi(zvrf, vxl->access_vlan, + zif->brslave_info.br_if); + if (!vlan_if) + return -1; - return kernel_add_neigh (vlan_if, &n->ip, &n->emac); + return kernel_add_neigh(vlan_if, &n->ip, &n->emac); } /* * Uninstall remote neighbor from the kernel. */ -static int -zvni_neigh_uninstall (zebra_vni_t *zvni, zebra_neigh_t *n) +static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n) { - struct zebra_vrf *zvrf; - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - struct interface *vlan_if; + struct zebra_vrf *zvrf; + struct zebra_if *zif; + struct zebra_l2info_vxlan *vxl; + struct interface *vlan_if; - if (!(n->flags & ZEBRA_NEIGH_REMOTE)) - return 0; + if (!(n->flags & ZEBRA_NEIGH_REMOTE)) + return 0; - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - assert(zvrf); - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p couldn't be uninstalled - no intf", - zvni->vni, zvni); - return -1; - } + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + assert(zvrf); + if (!zvni->vxlan_if) { + zlog_err("VNI %u hash %p couldn't be uninstalled - no intf", + zvni->vni, zvni); + return -1; + } - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - vxl = &zif->l2info.vxl; - vlan_if = zvni_map_to_svi (zvrf, vxl->access_vlan, - zif->brslave_info.br_if); - if (!vlan_if) - return -1; + zif = zvni->vxlan_if->info; + if (!zif) + return -1; + vxl = &zif->l2info.vxl; + vlan_if = zvni_map_to_svi(zvrf, vxl->access_vlan, + zif->brslave_info.br_if); + if (!vlan_if) + return -1; - return kernel_del_neigh (vlan_if, &n->ip); + return kernel_del_neigh(vlan_if, &n->ip); } /* * Install neighbor hash entry - called upon access VLAN change. */ -static void -zvni_install_neigh_hash (struct hash_backet *backet, void *ctxt) +static void zvni_install_neigh_hash(struct hash_backet *backet, void *ctxt) { - zebra_neigh_t *n; - struct neigh_walk_ctx *wctx = ctxt; + zebra_neigh_t *n; + struct neigh_walk_ctx *wctx = ctxt; - n = (zebra_neigh_t *) backet->data; - if (!n) - return; + n = (zebra_neigh_t *)backet->data; + if (!n) + return; - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) - zvni_neigh_install (wctx->zvni, n); + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) + zvni_neigh_install(wctx->zvni, n); } /* * Make hash key for MAC. */ -static unsigned int -mac_hash_keymake (void *p) +static unsigned int mac_hash_keymake(void *p) { - zebra_mac_t *pmac = p; - char *pnt = (char *) pmac->macaddr.octet; - unsigned int key = 0; - int c = 0; + zebra_mac_t *pmac = p; + char *pnt = (char *)pmac->macaddr.octet; + unsigned int key = 0; + int c = 0; - key += pnt[c]; - key += pnt[c + 1]; - key += pnt[c + 2]; - key += pnt[c + 3]; - key += pnt[c + 4]; - key += pnt[c + 5]; + key += pnt[c]; + key += pnt[c + 1]; + key += pnt[c + 2]; + key += pnt[c + 3]; + key += pnt[c + 4]; + key += pnt[c + 5]; - return (key); + return (key); } /* * Compare two MAC addresses. */ -static int -mac_cmp (const void *p1, const void *p2) +static int mac_cmp(const void *p1, const void *p2) { - const zebra_mac_t *pmac1 = p1; - const zebra_mac_t *pmac2 = p2; + const zebra_mac_t *pmac1 = p1; + const zebra_mac_t *pmac2 = p2; - if (pmac1 == NULL && pmac2 == NULL) - return 1; + if (pmac1 == NULL && pmac2 == NULL) + return 1; - if (pmac1 == NULL || pmac2 == NULL) - return 0; + if (pmac1 == NULL || pmac2 == NULL) + return 0; - return(memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETHER_ADDR_LEN) == 0); + return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, + ETHER_ADDR_LEN) + == 0); } /* * Callback to allocate MAC hash entry. */ -static void * -zvni_mac_alloc (void *p) +static void *zvni_mac_alloc(void *p) { - const zebra_mac_t *tmp_mac = p; - zebra_mac_t *mac; + const zebra_mac_t *tmp_mac = p; + zebra_mac_t *mac; - mac = XCALLOC (MTYPE_MAC, sizeof(zebra_mac_t)); - *mac = *tmp_mac; + mac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t)); + *mac = *tmp_mac; - return ((void *)mac); + return ((void *)mac); } /* * Add MAC entry. */ -static zebra_mac_t * -zvni_mac_add (zebra_vni_t *zvni, struct ethaddr *macaddr) +static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr) { - zebra_mac_t tmp_mac; - zebra_mac_t *mac = NULL; + zebra_mac_t tmp_mac; + zebra_mac_t *mac = NULL; - memset (&tmp_mac, 0, sizeof (zebra_mac_t)); - memcpy(&tmp_mac.macaddr, macaddr, ETHER_ADDR_LEN); - mac = hash_get (zvni->mac_table, &tmp_mac, zvni_mac_alloc); - assert (mac); + memset(&tmp_mac, 0, sizeof(zebra_mac_t)); + memcpy(&tmp_mac.macaddr, macaddr, ETHER_ADDR_LEN); + mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc); + assert(mac); - return mac; + return mac; } /* * Delete MAC entry. */ -static int -zvni_mac_del (zebra_vni_t *zvni, zebra_mac_t *mac) +static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac) { - zebra_mac_t *tmp_mac; + zebra_mac_t *tmp_mac; - /* Free the VNI hash entry and allocated memory. */ - tmp_mac = hash_release (zvni->mac_table, mac); - if (tmp_mac) - XFREE(MTYPE_MAC, tmp_mac); + /* Free the VNI hash entry and allocated memory. */ + tmp_mac = hash_release(zvni->mac_table, mac); + if (tmp_mac) + XFREE(MTYPE_MAC, tmp_mac); - return 0; + return 0; } /* * Free MAC hash entry (callback) */ -static int -zvni_mac_del_hash_entry (struct hash_backet *backet, void *arg) +static int zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg) { - struct mac_walk_ctx *wctx = arg; - zebra_mac_t *mac = backet->data; - u_char sticky = 0; + struct mac_walk_ctx *wctx = arg; + zebra_mac_t *mac = backet->data; + u_char sticky = 0; - if (((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL)) || - ((wctx->flags & DEL_REMOTE_MAC) && (mac->flags & ZEBRA_MAC_REMOTE)) || - ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP) && - (mac->flags & ZEBRA_MAC_REMOTE) && - IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip) - )) - { - if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) - { - sticky = CHECK_FLAG (mac->flags, ZEBRA_MAC_STICKY) ? 1: 0; - zvni_mac_send_del_to_client (wctx->zvrf, wctx->zvni->vni, - &mac->macaddr, sticky); - } + if (((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL)) + || ((wctx->flags & DEL_REMOTE_MAC) + && (mac->flags & ZEBRA_MAC_REMOTE)) + || ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP) + && (mac->flags & ZEBRA_MAC_REMOTE) + && IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, + &wctx->r_vtep_ip))) { + if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) { + sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 + : 0; + zvni_mac_send_del_to_client(wctx->zvrf, wctx->zvni->vni, + &mac->macaddr, sticky); + } - if (wctx->uninstall) - zvni_mac_uninstall (wctx->zvni, mac, 0); + if (wctx->uninstall) + zvni_mac_uninstall(wctx->zvni, mac, 0); - return zvni_mac_del (wctx->zvni, mac); - } + return zvni_mac_del(wctx->zvni, mac); + } - return 0; + return 0; } /* * Delete all MAC entries from specific VTEP for a particular VNI. */ -static void -zvni_mac_del_from_vtep (zebra_vni_t *zvni, int uninstall, - struct in_addr *r_vtep_ip) +static void zvni_mac_del_from_vtep(zebra_vni_t *zvni, int uninstall, + struct in_addr *r_vtep_ip) { - struct mac_walk_ctx wctx; + struct mac_walk_ctx wctx; - if (!zvni->mac_table) - return; + if (!zvni->mac_table) + return; - memset (&wctx, 0, sizeof (struct mac_walk_ctx)); - wctx.zvni = zvni; - wctx.uninstall = uninstall; - wctx.flags = DEL_REMOTE_MAC_FROM_VTEP; - wctx.r_vtep_ip = *r_vtep_ip; + memset(&wctx, 0, sizeof(struct mac_walk_ctx)); + wctx.zvni = zvni; + wctx.uninstall = uninstall; + wctx.flags = DEL_REMOTE_MAC_FROM_VTEP; + wctx.r_vtep_ip = *r_vtep_ip; - hash_iterate (zvni->mac_table, - (void (*) (struct hash_backet *, void *)) - zvni_mac_del_hash_entry, &wctx); + hash_iterate(zvni->mac_table, (void (*)(struct hash_backet *, + void *))zvni_mac_del_hash_entry, + &wctx); } /* * Delete all MAC entries for this VNI. */ -static void -zvni_mac_del_all (struct zebra_vrf *zvrf, zebra_vni_t *zvni, - int uninstall, int upd_client, u_int32_t flags) +static void zvni_mac_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni, + int uninstall, int upd_client, u_int32_t flags) { - struct mac_walk_ctx wctx; + struct mac_walk_ctx wctx; - if (!zvni->mac_table) - return; + if (!zvni->mac_table) + return; - memset (&wctx, 0, sizeof (struct mac_walk_ctx)); - wctx.zvni = zvni; - wctx.zvrf = zvrf; - wctx.uninstall = uninstall; - wctx.upd_client = upd_client; - wctx.flags = flags; + memset(&wctx, 0, sizeof(struct mac_walk_ctx)); + wctx.zvni = zvni; + wctx.zvrf = zvrf; + wctx.uninstall = uninstall; + wctx.upd_client = upd_client; + wctx.flags = flags; - hash_iterate (zvni->mac_table, - (void (*) (struct hash_backet *, void *)) - zvni_mac_del_hash_entry, &wctx); + hash_iterate(zvni->mac_table, (void (*)(struct hash_backet *, + void *))zvni_mac_del_hash_entry, + &wctx); } /* * Look up MAC hash entry. */ -static zebra_mac_t * -zvni_mac_lookup (zebra_vni_t *zvni, struct ethaddr *mac) +static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *mac) { - zebra_mac_t tmp; - zebra_mac_t *pmac; + zebra_mac_t tmp; + zebra_mac_t *pmac; - memset(&tmp, 0, sizeof(tmp)); - memcpy(&tmp.macaddr, mac, ETHER_ADDR_LEN); - pmac = hash_lookup (zvni->mac_table, &tmp); + memset(&tmp, 0, sizeof(tmp)); + memcpy(&tmp.macaddr, mac, ETHER_ADDR_LEN); + pmac = hash_lookup(zvni->mac_table, &tmp); - return pmac; + return pmac; } /* * Inform BGP about local MAC addition. */ -static int -zvni_mac_send_add_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ethaddr *macaddr, u_char sticky) +static int zvni_mac_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ethaddr *macaddr, u_char sticky) { - return zvni_macip_send_msg_to_client (zvrf, vni, macaddr, NULL, - sticky, ZEBRA_MACIP_ADD); + return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, NULL, sticky, + ZEBRA_MACIP_ADD); } /* * Inform BGP about local MAC deletion. */ -static int -zvni_mac_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ethaddr *macaddr, u_char sticky) +static int zvni_mac_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ethaddr *macaddr, u_char sticky) { - return zvni_macip_send_msg_to_client (zvrf, vni, macaddr, NULL, - sticky, ZEBRA_MACIP_DEL); + return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, NULL, sticky, + ZEBRA_MACIP_DEL); } /* @@ -1084,54 +971,53 @@ zvni_mac_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni, * notifications, to see if there are of interest. * TODO: Need to make this as a hash table. */ -static zebra_vni_t * -zvni_map_vlan (struct interface *ifp, struct interface *br_if, vlanid_t vid) +static zebra_vni_t *zvni_map_vlan(struct interface *ifp, + struct interface *br_if, vlanid_t vid) { - struct zebra_vrf *zvrf; - struct listnode *node; - struct interface *tmp_if; - struct zebra_if *zif; - struct zebra_l2info_bridge *br; - struct zebra_l2info_vxlan *vxl; - u_char bridge_vlan_aware; - zebra_vni_t *zvni; + struct zebra_vrf *zvrf; + struct listnode *node; + struct interface *tmp_if; + struct zebra_if *zif; + struct zebra_l2info_bridge *br; + struct zebra_l2info_vxlan *vxl; + u_char bridge_vlan_aware; + zebra_vni_t *zvni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* Determine if bridge is VLAN-aware or not */ - zif = br_if->info; - assert (zif); - br = &zif->l2info.br; - bridge_vlan_aware = br->vlan_aware; + /* Determine if bridge is VLAN-aware or not */ + zif = br_if->info; + assert(zif); + br = &zif->l2info.br; + bridge_vlan_aware = br->vlan_aware; - /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ - /* TODO: Optimize with a hash. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (zvrf_id (zvrf)), node, tmp_if)) - { - zif = tmp_if->info; - if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) - continue; - if (!if_is_operative (tmp_if)) - continue; - vxl = &zif->l2info.vxl; + /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ + /* TODO: Optimize with a hash. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, tmp_if)) { + zif = tmp_if->info; + if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) + continue; + if (!if_is_operative(tmp_if)) + continue; + vxl = &zif->l2info.vxl; - if (zif->brslave_info.br_if != br_if) - continue; + if (zif->brslave_info.br_if != br_if) + continue; - if (!bridge_vlan_aware) - break; + if (!bridge_vlan_aware) + break; - if (vxl->access_vlan == vid) - break; - } + if (vxl->access_vlan == vid) + break; + } - if (!tmp_if) - return NULL; + if (!tmp_if) + return NULL; - zvni = zvni_lookup (zvrf, vxl->vni); - return zvni; + zvni = zvni_lookup(zvrf, vxl->vni); + return zvni; } /* @@ -1139,71 +1025,68 @@ zvni_map_vlan (struct interface *ifp, struct interface *br_if, vlanid_t vid) * neighbor notifications, to see if they are of interest. * TODO: Need to make this as a hash table. */ -static zebra_vni_t * -zvni_map_svi (struct interface *ifp, struct interface *br_if) -{ - struct zebra_vrf *zvrf; - struct listnode *node; - struct interface *tmp_if; - struct zebra_if *zif; - struct zebra_l2info_bridge *br; - struct zebra_l2info_vxlan *vxl; - u_char bridge_vlan_aware; - vlanid_t vid = 0; - zebra_vni_t *zvni; - - /* Make sure the linked interface is a bridge. */ - if (!IS_ZEBRA_IF_BRIDGE (br_if)) - return NULL; - - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); - - /* Determine if bridge is VLAN-aware or not */ - zif = br_if->info; - assert (zif); - br = &zif->l2info.br; - bridge_vlan_aware = br->vlan_aware; - if (bridge_vlan_aware) - { - struct zebra_l2info_vlan *vl; - - if (!IS_ZEBRA_IF_VLAN(ifp)) - return NULL; - - zif = ifp->info; - assert (zif); - vl = &zif->l2info.vl; - vid = vl->vid; - } - - /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ - /* TODO: Optimize with a hash. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (zvrf_id (zvrf)), node, tmp_if)) - { - zif = tmp_if->info; - if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) - continue; - if (!if_is_operative (tmp_if)) - continue; - vxl = &zif->l2info.vxl; - - if (zif->brslave_info.br_if != br_if) - continue; - - if (!bridge_vlan_aware) - break; - - if (vxl->access_vlan == vid) - break; - } - - if (!tmp_if) - return NULL; - - zvni = zvni_lookup (zvrf, vxl->vni); - return zvni; +static zebra_vni_t *zvni_map_svi(struct interface *ifp, struct interface *br_if) +{ + struct zebra_vrf *zvrf; + struct listnode *node; + struct interface *tmp_if; + struct zebra_if *zif; + struct zebra_l2info_bridge *br; + struct zebra_l2info_vxlan *vxl; + u_char bridge_vlan_aware; + vlanid_t vid = 0; + zebra_vni_t *zvni; + + /* Make sure the linked interface is a bridge. */ + if (!IS_ZEBRA_IF_BRIDGE(br_if)) + return NULL; + + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); + + /* Determine if bridge is VLAN-aware or not */ + zif = br_if->info; + assert(zif); + br = &zif->l2info.br; + bridge_vlan_aware = br->vlan_aware; + if (bridge_vlan_aware) { + struct zebra_l2info_vlan *vl; + + if (!IS_ZEBRA_IF_VLAN(ifp)) + return NULL; + + zif = ifp->info; + assert(zif); + vl = &zif->l2info.vl; + vid = vl->vid; + } + + /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ + /* TODO: Optimize with a hash. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, tmp_if)) { + zif = tmp_if->info; + if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) + continue; + if (!if_is_operative(tmp_if)) + continue; + vxl = &zif->l2info.vxl; + + if (zif->brslave_info.br_if != br_if) + continue; + + if (!bridge_vlan_aware) + break; + + if (vxl->access_vlan == vid) + break; + } + + if (!tmp_if) + return NULL; + + zvni = zvni_lookup(zvrf, vxl->vni); + return zvni; } /* Map to SVI on bridge corresponding to specified VLAN. This can be one @@ -1213,551 +1096,515 @@ zvni_map_svi (struct interface *ifp, struct interface *br_if) * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface * itself */ -static struct interface * -zvni_map_to_svi (struct zebra_vrf *zvrf, vlanid_t vid, - struct interface *br_if) -{ - struct listnode *node; - struct interface *tmp_if; - struct zebra_if *zif; - struct zebra_l2info_bridge *br; - struct zebra_l2info_vlan *vl; - u_char bridge_vlan_aware; - - /* Determine if bridge is VLAN-aware or not */ - zif = br_if->info; - assert (zif); - br = &zif->l2info.br; - bridge_vlan_aware = br->vlan_aware; - - /* Check oper status of the SVI. */ - if (!bridge_vlan_aware) - return if_is_operative (br_if) ? br_if : NULL; - - /* Identify corresponding VLAN interface. */ - /* TODO: Optimize with a hash. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (zvrf_id (zvrf)), node, tmp_if)) - { - /* Check oper status of the SVI. */ - if (!if_is_operative (tmp_if)) - continue; - zif = tmp_if->info; - if (!zif || - zif->zif_type != ZEBRA_IF_VLAN || - zif->link != br_if) - continue; - vl = (struct zebra_l2info_vlan *)&zif->l2info.vl; - - if (vl->vid == vid) - break; - } - - return tmp_if; +static struct interface *zvni_map_to_svi(struct zebra_vrf *zvrf, vlanid_t vid, + struct interface *br_if) +{ + struct listnode *node; + struct interface *tmp_if; + struct zebra_if *zif; + struct zebra_l2info_bridge *br; + struct zebra_l2info_vlan *vl; + u_char bridge_vlan_aware; + + /* Determine if bridge is VLAN-aware or not */ + zif = br_if->info; + assert(zif); + br = &zif->l2info.br; + bridge_vlan_aware = br->vlan_aware; + + /* Check oper status of the SVI. */ + if (!bridge_vlan_aware) + return if_is_operative(br_if) ? br_if : NULL; + + /* Identify corresponding VLAN interface. */ + /* TODO: Optimize with a hash. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, tmp_if)) { + /* Check oper status of the SVI. */ + if (!if_is_operative(tmp_if)) + continue; + zif = tmp_if->info; + if (!zif || zif->zif_type != ZEBRA_IF_VLAN + || zif->link != br_if) + continue; + vl = (struct zebra_l2info_vlan *)&zif->l2info.vl; + + if (vl->vid == vid) + break; + } + + return tmp_if; } /* * Install remote MAC into the kernel. */ -static int -zvni_mac_install (zebra_vni_t *zvni, zebra_mac_t *mac) +static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac) { - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - u_char sticky; + struct zebra_if *zif; + struct zebra_l2info_vxlan *vxl; + u_char sticky; - if (!(mac->flags & ZEBRA_MAC_REMOTE)) - return 0; + if (!(mac->flags & ZEBRA_MAC_REMOTE)) + return 0; - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - vxl = &zif->l2info.vxl; + zif = zvni->vxlan_if->info; + if (!zif) + return -1; + vxl = &zif->l2info.vxl; - sticky = CHECK_FLAG (mac->flags, ZEBRA_MAC_STICKY) ? 1: 0; + sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0; - return kernel_add_mac (zvni->vxlan_if, vxl->access_vlan, - &mac->macaddr, mac->fwd_info.r_vtep_ip, sticky); + return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr, + mac->fwd_info.r_vtep_ip, sticky); } /* * Uninstall remote MAC from the kernel. In the scenario where the MAC * moves to remote, we have to uninstall any existing local entry first. */ -static int -zvni_mac_uninstall (zebra_vni_t *zvni, zebra_mac_t *mac, int local) +static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac, int local) { - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - struct in_addr vtep_ip = { .s_addr = 0 }; - struct zebra_ns *zns; - struct interface *ifp; + struct zebra_if *zif; + struct zebra_l2info_vxlan *vxl; + struct in_addr vtep_ip = {.s_addr = 0}; + struct zebra_ns *zns; + struct interface *ifp; - if (!local && !(mac->flags & ZEBRA_MAC_REMOTE)) - return 0; + if (!local && !(mac->flags & ZEBRA_MAC_REMOTE)) + return 0; - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p couldn't be uninstalled - no intf", - zvni->vni, zvni); - return -1; - } + if (!zvni->vxlan_if) { + zlog_err("VNI %u hash %p couldn't be uninstalled - no intf", + zvni->vni, zvni); + return -1; + } - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - vxl = &zif->l2info.vxl; + zif = zvni->vxlan_if->info; + if (!zif) + return -1; + vxl = &zif->l2info.vxl; - if (local) - { - zns = zebra_ns_lookup (NS_DEFAULT); - ifp = if_lookup_by_index_per_ns (zns, mac->fwd_info.local.ifindex); - if (!ifp) // unexpected - return -1; - } - else - { - ifp = zvni->vxlan_if; - vtep_ip = mac->fwd_info.r_vtep_ip; - } + if (local) { + zns = zebra_ns_lookup(NS_DEFAULT); + ifp = if_lookup_by_index_per_ns(zns, + mac->fwd_info.local.ifindex); + if (!ifp) // unexpected + return -1; + } else { + ifp = zvni->vxlan_if; + vtep_ip = mac->fwd_info.r_vtep_ip; + } - return kernel_del_mac (ifp, vxl->access_vlan, - &mac->macaddr, vtep_ip, local); + return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip, + local); } /* * Install MAC hash entry - called upon access VLAN change. */ -static void -zvni_install_mac_hash (struct hash_backet *backet, void *ctxt) +static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt) { - zebra_mac_t *mac; - struct mac_walk_ctx *wctx = ctxt; + zebra_mac_t *mac; + struct mac_walk_ctx *wctx = ctxt; - mac = (zebra_mac_t *) backet->data; - if (!mac) - return; + mac = (zebra_mac_t *)backet->data; + if (!mac) + return; - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) - zvni_mac_install (wctx->zvni, mac); + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) + zvni_mac_install(wctx->zvni, mac); } /* * Decrement neighbor refcount of MAC; uninstall and free it if * appropriate. */ -static void -zvni_deref_ip2mac (zebra_vni_t *zvni, zebra_mac_t *mac, int uninstall) +static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac, + int uninstall) { - if (mac->neigh_refcnt) - mac->neigh_refcnt--; + if (mac->neigh_refcnt) + mac->neigh_refcnt--; - if (!CHECK_FLAG (mac->flags, ZEBRA_MAC_AUTO) || - mac->neigh_refcnt > 0) - return; + if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) || mac->neigh_refcnt > 0) + return; - if (uninstall) - zvni_mac_uninstall (zvni, mac, 0); + if (uninstall) + zvni_mac_uninstall(zvni, mac, 0); - zvni_mac_del (zvni, mac); + zvni_mac_del(zvni, mac); } /* * Read and populate local MACs and neighbors corresponding to this VNI. */ -static void -zvni_read_mac_neigh (struct zebra_vrf *zvrf, zebra_vni_t *zvni, - struct interface *ifp) +static void zvni_read_mac_neigh(struct zebra_vrf *zvrf, zebra_vni_t *zvni, + struct interface *ifp) { - struct zebra_if *zif; - struct interface *vlan_if; - struct zebra_l2info_vxlan *vxl; + struct zebra_if *zif; + struct interface *vlan_if; + struct zebra_l2info_vxlan *vxl; - zif = ifp->info; - vxl = &zif->l2info.vxl; + zif = ifp->info; + vxl = &zif->l2info.vxl; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u", - ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni, - zif->brslave_info.bridge_ifindex); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u", + ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni, + zif->brslave_info.bridge_ifindex); - macfdb_read_for_bridge (zvrf->zns, ifp, zif->brslave_info.br_if); - vlan_if = zvni_map_to_svi (zvrf, vxl->access_vlan, - zif->brslave_info.br_if); - if (vlan_if) - neigh_read_for_vlan (zvrf->zns, vlan_if); + macfdb_read_for_bridge(zvrf->zns, ifp, zif->brslave_info.br_if); + vlan_if = zvni_map_to_svi(zvrf, vxl->access_vlan, + zif->brslave_info.br_if); + if (vlan_if) + neigh_read_for_vlan(zvrf->zns, vlan_if); } /* * Hash function for VNI. */ -static unsigned int -vni_hash_keymake (void *p) +static unsigned int vni_hash_keymake(void *p) { - const zebra_vni_t *zvni = p; + const zebra_vni_t *zvni = p; - return (jhash_1word(zvni->vni, 0)); + return (jhash_1word(zvni->vni, 0)); } /* * Compare 2 VNI hash entries. */ -static int -vni_hash_cmp (const void *p1, const void *p2) +static int vni_hash_cmp(const void *p1, const void *p2) { - const zebra_vni_t *zvni1 = p1; - const zebra_vni_t *zvni2 = p2; + const zebra_vni_t *zvni1 = p1; + const zebra_vni_t *zvni2 = p2; - return (zvni1->vni == zvni2->vni); + return (zvni1->vni == zvni2->vni); } /* * Callback to allocate VNI hash entry. */ -static void * -zvni_alloc (void *p) +static void *zvni_alloc(void *p) { - const zebra_vni_t *tmp_vni = p; - zebra_vni_t *zvni; + const zebra_vni_t *tmp_vni = p; + zebra_vni_t *zvni; - zvni = XCALLOC (MTYPE_ZVNI, sizeof(zebra_vni_t)); - zvni->vni = tmp_vni->vni; - return ((void *)zvni); + zvni = XCALLOC(MTYPE_ZVNI, sizeof(zebra_vni_t)); + zvni->vni = tmp_vni->vni; + return ((void *)zvni); } /* * Look up VNI hash entry. */ -static zebra_vni_t * -zvni_lookup (struct zebra_vrf *zvrf, vni_t vni) +static zebra_vni_t *zvni_lookup(struct zebra_vrf *zvrf, vni_t vni) { - zebra_vni_t tmp_vni; - zebra_vni_t *zvni = NULL; + zebra_vni_t tmp_vni; + zebra_vni_t *zvni = NULL; - memset (&tmp_vni, 0, sizeof (zebra_vni_t)); - tmp_vni.vni = vni; - zvni = hash_lookup (zvrf->vni_table, &tmp_vni); + memset(&tmp_vni, 0, sizeof(zebra_vni_t)); + tmp_vni.vni = vni; + zvni = hash_lookup(zvrf->vni_table, &tmp_vni); - return zvni; + return zvni; } /* * Add VNI hash entry. */ -static zebra_vni_t * -zvni_add (struct zebra_vrf *zvrf, vni_t vni) +static zebra_vni_t *zvni_add(struct zebra_vrf *zvrf, vni_t vni) { - zebra_vni_t tmp_zvni; - zebra_vni_t *zvni = NULL; + zebra_vni_t tmp_zvni; + zebra_vni_t *zvni = NULL; - memset (&tmp_zvni, 0, sizeof (zebra_vni_t)); - tmp_zvni.vni = vni; - zvni = hash_get (zvrf->vni_table, &tmp_zvni, zvni_alloc); - assert (zvni); + memset(&tmp_zvni, 0, sizeof(zebra_vni_t)); + tmp_zvni.vni = vni; + zvni = hash_get(zvrf->vni_table, &tmp_zvni, zvni_alloc); + assert(zvni); - /* Create hash table for MAC */ - zvni->mac_table = hash_create(mac_hash_keymake, - mac_cmp, - "Zebra VNI MAC Table"); + /* Create hash table for MAC */ + zvni->mac_table = + hash_create(mac_hash_keymake, mac_cmp, "Zebra VNI MAC Table"); - /* Create hash table for neighbors */ - zvni->neigh_table = hash_create(neigh_hash_keymake, - neigh_cmp, - "Zebra VNI Neighbor Table"); + /* Create hash table for neighbors */ + zvni->neigh_table = hash_create(neigh_hash_keymake, neigh_cmp, + "Zebra VNI Neighbor Table"); - return zvni; + return zvni; } /* * Delete VNI hash entry. */ -static int -zvni_del (struct zebra_vrf *zvrf, zebra_vni_t *zvni) +static int zvni_del(struct zebra_vrf *zvrf, zebra_vni_t *zvni) { - zebra_vni_t *tmp_zvni; + zebra_vni_t *tmp_zvni; - zvni->vxlan_if = NULL; + zvni->vxlan_if = NULL; - /* Free the neighbor hash table. */ - hash_free(zvni->neigh_table); - zvni->neigh_table = NULL; + /* Free the neighbor hash table. */ + hash_free(zvni->neigh_table); + zvni->neigh_table = NULL; - /* Free the MAC hash table. */ - hash_free(zvni->mac_table); - zvni->mac_table = NULL; + /* Free the MAC hash table. */ + hash_free(zvni->mac_table); + zvni->mac_table = NULL; - /* Free the VNI hash entry and allocated memory. */ - tmp_zvni = hash_release (zvrf->vni_table, zvni); - if (tmp_zvni) - XFREE(MTYPE_ZVNI, tmp_zvni); + /* Free the VNI hash entry and allocated memory. */ + tmp_zvni = hash_release(zvrf->vni_table, zvni); + if (tmp_zvni) + XFREE(MTYPE_ZVNI, tmp_zvni); - return 0; + return 0; } /* * Inform BGP about local VNI addition. */ -static int -zvni_send_add_to_client (struct zebra_vrf *zvrf, - zebra_vni_t *zvni) +static int zvni_send_add_to_client(struct zebra_vrf *zvrf, zebra_vni_t *zvni) { - struct zserv *client; - struct stream *s; + struct zserv *client; + struct stream *s; - client = zebra_find_client (ZEBRA_ROUTE_BGP); - /* BGP may not be running. */ - if (!client) - return 0; + client = zebra_find_client(ZEBRA_ROUTE_BGP); + /* BGP may not be running. */ + if (!client) + return 0; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_VNI_ADD, zvrf_id (zvrf)); - stream_putl (s, zvni->vni); - stream_put_in_addr (s, &zvni->local_vtep_ip); + zserv_create_header(s, ZEBRA_VNI_ADD, zvrf_id(zvrf)); + stream_putl(s, zvni->vni); + stream_put_in_addr(s, &zvni->local_vtep_ip); - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Send VNI_ADD %u %s to %s", - zvrf_id (zvrf), zvni->vni, - inet_ntoa(zvni->local_vtep_ip), - zebra_route_string (client->proto)); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Send VNI_ADD %u %s to %s", zvrf_id(zvrf), + zvni->vni, inet_ntoa(zvni->local_vtep_ip), + zebra_route_string(client->proto)); - client->vniadd_cnt++; - return zebra_server_send_message(client); + client->vniadd_cnt++; + return zebra_server_send_message(client); } /* * Inform BGP about local VNI deletion. */ -static int -zvni_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni) +static int zvni_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni) { - struct zserv *client; - struct stream *s; + struct zserv *client; + struct stream *s; - client = zebra_find_client (ZEBRA_ROUTE_BGP); - /* BGP may not be running. */ - if (!client) - return 0; + client = zebra_find_client(ZEBRA_ROUTE_BGP); + /* BGP may not be running. */ + if (!client) + return 0; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_VNI_DEL, zvrf_id (zvrf)); - stream_putl (s, vni); + zserv_create_header(s, ZEBRA_VNI_DEL, zvrf_id(zvrf)); + stream_putl(s, vni); - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Send VNI_DEL %u to %s", zvrf_id (zvrf), vni, - zebra_route_string (client->proto)); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Send VNI_DEL %u to %s", zvrf_id(zvrf), vni, + zebra_route_string(client->proto)); - client->vnidel_cnt++; - return zebra_server_send_message(client); + client->vnidel_cnt++; + return zebra_server_send_message(client); } /* * Build the VNI hash table by going over the VxLAN interfaces. This * is called when EVPN (advertise-all-vni) is enabled. */ -static void -zvni_build_hash_table (struct zebra_vrf *zvrf) +static void zvni_build_hash_table(struct zebra_vrf *zvrf) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - /* Walk VxLAN interfaces and create VNI hash. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (zvrf_id (zvrf)), node, ifp)) - { - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - zebra_vni_t *zvni; - vni_t vni; + /* Walk VxLAN interfaces and create VNI hash. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, ifp)) { + struct zebra_if *zif; + struct zebra_l2info_vxlan *vxl; + zebra_vni_t *zvni; + vni_t vni; - zif = ifp->info; - if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) - continue; - vxl = &zif->l2info.vxl; + zif = ifp->info; + if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) + continue; + vxl = &zif->l2info.vxl; - vni = vxl->vni; + vni = vxl->vni; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Create VNI hash for intf %s(%u) VNI %u local IP %s", - zvrf_id (zvrf), ifp->name, ifp->ifindex, vni, - inet_ntoa (vxl->vtep_ip)); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Create VNI hash for intf %s(%u) VNI %u local IP %s", + zvrf_id(zvrf), ifp->name, ifp->ifindex, vni, + inet_ntoa(vxl->vtep_ip)); - /* VNI hash entry is not expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (zvni) - { - zlog_err ("VNI hash already present for VRF %d IF %s(%u) VNI %u", - zvrf_id (zvrf), ifp->name, ifp->ifindex, vni); - continue; - } + /* VNI hash entry is not expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (zvni) { + zlog_err( + "VNI hash already present for VRF %d IF %s(%u) VNI %u", + zvrf_id(zvrf), ifp->name, ifp->ifindex, vni); + continue; + } - zvni = zvni_add (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to add VNI hash, VRF %d IF %s(%u) VNI %u", - zvrf_id (zvrf), ifp->name, ifp->ifindex, vni); - return; - } + zvni = zvni_add(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to add VNI hash, VRF %d IF %s(%u) VNI %u", + zvrf_id(zvrf), ifp->name, ifp->ifindex, vni); + return; + } - zvni->local_vtep_ip = vxl->vtep_ip; - zvni->vxlan_if = ifp; + zvni->local_vtep_ip = vxl->vtep_ip; + zvni->vxlan_if = ifp; - /* Inform BGP if interface is up and mapped to bridge. */ - if (if_is_operative (ifp) && - zif->brslave_info.br_if) - zvni_send_add_to_client (zvrf, zvni); - } + /* Inform BGP if interface is up and mapped to bridge. */ + if (if_is_operative(ifp) && zif->brslave_info.br_if) + zvni_send_add_to_client(zvrf, zvni); + } } /* * See if remote VTEP matches with prefix. */ -static int -zvni_vtep_match (struct in_addr *vtep_ip, zebra_vtep_t *zvtep) +static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep) { - return (IPV4_ADDR_SAME (vtep_ip, &zvtep->vtep_ip)); + return (IPV4_ADDR_SAME(vtep_ip, &zvtep->vtep_ip)); } /* * Locate remote VTEP in VNI hash table. */ -static zebra_vtep_t * -zvni_vtep_find (zebra_vni_t *zvni, struct in_addr *vtep_ip) +static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip) { - zebra_vtep_t *zvtep; + zebra_vtep_t *zvtep; - if (!zvni) - return NULL; + if (!zvni) + return NULL; - for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) - { - if (zvni_vtep_match (vtep_ip, zvtep)) - break; - } + for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) { + if (zvni_vtep_match(vtep_ip, zvtep)) + break; + } - return zvtep; + return zvtep; } /* * Add remote VTEP to VNI hash table. */ -static zebra_vtep_t * -zvni_vtep_add (zebra_vni_t *zvni, struct in_addr *vtep_ip) +static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip) { - zebra_vtep_t *zvtep; + zebra_vtep_t *zvtep; - zvtep = XCALLOC (MTYPE_ZVNI_VTEP, sizeof(zebra_vtep_t)); - if (!zvtep) - { - zlog_err ("Failed to alloc VTEP entry, VNI %u", zvni->vni); - return NULL; - } + zvtep = XCALLOC(MTYPE_ZVNI_VTEP, sizeof(zebra_vtep_t)); + if (!zvtep) { + zlog_err("Failed to alloc VTEP entry, VNI %u", zvni->vni); + return NULL; + } - zvtep->vtep_ip = *vtep_ip; + zvtep->vtep_ip = *vtep_ip; - if (zvni->vteps) - zvni->vteps->prev = zvtep; - zvtep->next = zvni->vteps; - zvni->vteps = zvtep; + if (zvni->vteps) + zvni->vteps->prev = zvtep; + zvtep->next = zvni->vteps; + zvni->vteps = zvtep; - return zvtep; + return zvtep; } /* * Remove remote VTEP from VNI hash table. */ -static int -zvni_vtep_del (zebra_vni_t *zvni, zebra_vtep_t *zvtep) +static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep) { - if (zvtep->next) - zvtep->next->prev = zvtep->prev; - if (zvtep->prev) - zvtep->prev->next = zvtep->next; - else - zvni->vteps = zvtep->next; + if (zvtep->next) + zvtep->next->prev = zvtep->prev; + if (zvtep->prev) + zvtep->prev->next = zvtep->next; + else + zvni->vteps = zvtep->next; - zvtep->prev = zvtep->next = NULL; - XFREE (MTYPE_ZVNI_VTEP, zvtep); + zvtep->prev = zvtep->next = NULL; + XFREE(MTYPE_ZVNI_VTEP, zvtep); - return 0; + return 0; } /* * Delete all remote VTEPs for this VNI (upon VNI delete). Also * uninstall from kernel if asked to. */ -static int -zvni_vtep_del_all (zebra_vni_t *zvni, int uninstall) +static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall) { - zebra_vtep_t *zvtep, *zvtep_next; + zebra_vtep_t *zvtep, *zvtep_next; - if (!zvni) - return -1; + if (!zvni) + return -1; - for (zvtep = zvni->vteps; zvtep; zvtep = zvtep_next) - { - zvtep_next = zvtep->next; - if (uninstall) - zvni_vtep_uninstall (zvni, &zvtep->vtep_ip); - zvni_vtep_del (zvni, zvtep); - } + for (zvtep = zvni->vteps; zvtep; zvtep = zvtep_next) { + zvtep_next = zvtep->next; + if (uninstall) + zvni_vtep_uninstall(zvni, &zvtep->vtep_ip); + zvni_vtep_del(zvni, zvtep); + } - return 0; + return 0; } /* * Install remote VTEP into the kernel. */ -static int -zvni_vtep_install (zebra_vni_t *zvni, struct in_addr *vtep_ip) +static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip) { - return kernel_add_vtep (zvni->vni, zvni->vxlan_if, vtep_ip); + return kernel_add_vtep(zvni->vni, zvni->vxlan_if, vtep_ip); } /* * Uninstall remote VTEP from the kernel. */ -static int -zvni_vtep_uninstall (zebra_vni_t *zvni, struct in_addr *vtep_ip) +static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip) { - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p couldn't be uninstalled - no intf", - zvni->vni, zvni); - return -1; - } + if (!zvni->vxlan_if) { + zlog_err("VNI %u hash %p couldn't be uninstalled - no intf", + zvni->vni, zvni); + return -1; + } - return kernel_del_vtep (zvni->vni, zvni->vxlan_if, vtep_ip); + return kernel_del_vtep(zvni->vni, zvni->vxlan_if, vtep_ip); } /* * Cleanup VNI/VTEP and update kernel */ -static void -zvni_cleanup_all (struct hash_backet *backet, void *zvrf) +static void zvni_cleanup_all(struct hash_backet *backet, void *zvrf) { - zebra_vni_t *zvni; + zebra_vni_t *zvni; - zvni = (zebra_vni_t *) backet->data; - if (!zvni) - return; + zvni = (zebra_vni_t *)backet->data; + if (!zvni) + return; - /* Free up all neighbors and MACs, if any. */ - zvni_neigh_del_all (zvrf, zvni, 1, 0, DEL_ALL_NEIGH); - zvni_mac_del_all (zvrf, zvni, 1, 0, DEL_ALL_MAC); + /* Free up all neighbors and MACs, if any. */ + zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH); + zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC); - /* Free up all remote VTEPs, if any. */ - zvni_vtep_del_all (zvni, 1); + /* Free up all remote VTEPs, if any. */ + zvni_vtep_del_all(zvni, 1); - /* Delete the hash entry. */ - zvni_del (zvrf, zvni); + /* Delete the hash entry. */ + zvni_del(zvrf, zvni); } @@ -1766,281 +1613,265 @@ zvni_cleanup_all (struct hash_backet *backet, void *zvrf) /* * Display Neighbors for a VNI (VTY command handler). */ -void -zebra_vxlan_print_neigh_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) -{ - zebra_vni_t *zvni; - u_int32_t num_neigh; - struct neigh_walk_ctx wctx; - - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist\n", vni); - return; - } - num_neigh = hashcount(zvni->neigh_table); - if (!num_neigh) - return; - - /* Since we have IPv6 addresses to deal with which can vary widely in - * size, we try to be a bit more elegant in display by first computing - * the maximum width. - */ - memset (&wctx, 0, sizeof (struct neigh_walk_ctx)); - wctx.zvni = zvni; - wctx.vty = vty; - wctx.addr_width = 15; - hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); - - vty_out(vty, "Number of ARPs (local and remote) known for this VNI: %u\n", - num_neigh); - vty_out(vty, "%*s %-6s %-17s %-21s\n", - -wctx.addr_width, "IP", "Type", "MAC", - "Remote VTEP"); - - hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); +void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni) +{ + zebra_vni_t *zvni; + u_int32_t num_neigh; + struct neigh_walk_ctx wctx; + + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist\n", vni); + return; + } + num_neigh = hashcount(zvni->neigh_table); + if (!num_neigh) + return; + + /* Since we have IPv6 addresses to deal with which can vary widely in + * size, we try to be a bit more elegant in display by first computing + * the maximum width. + */ + memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); + wctx.zvni = zvni; + wctx.vty = vty; + wctx.addr_width = 15; + hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); + + vty_out(vty, + "Number of ARPs (local and remote) known for this VNI: %u\n", + num_neigh); + vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP", "Type", + "MAC", "Remote VTEP"); + + hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); } /* * Display neighbors across all VNIs (VTY command handler). */ -void -zebra_vxlan_print_neigh_all_vni (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf) { - if (!EVPN_ENABLED(zvrf)) - return; - hash_iterate(zvrf->vni_table, zvni_print_neigh_hash_all_vni, vty); + if (!EVPN_ENABLED(zvrf)) + return; + hash_iterate(zvrf->vni_table, zvni_print_neigh_hash_all_vni, vty); } /* * Display specific neighbor for a VNI, if present (VTY command handler). */ -void -zebra_vxlan_print_specific_neigh_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct ipaddr *ip) +void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, + struct zebra_vrf *zvrf, vni_t vni, + struct ipaddr *ip) { - zebra_vni_t *zvni; - zebra_neigh_t *n; + zebra_vni_t *zvni; + zebra_neigh_t *n; - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist", vni); - return; - } - n = zvni_neigh_lookup (zvni, ip); - if (!n) - { - vty_out (vty, "%% Requested neighbor does not exist in VNI %u\n", - vni); - return; - } + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist", vni); + return; + } + n = zvni_neigh_lookup(zvni, ip); + if (!n) { + vty_out(vty, "%% Requested neighbor does not exist in VNI %u\n", + vni); + return; + } - zvni_print_neigh (n, vty); + zvni_print_neigh(n, vty); } /* * Display neighbors for a VNI from specific VTEP (VTY command handler). * By definition, these are remote neighbors. */ -void -zebra_vxlan_print_neigh_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct in_addr vtep_ip) +void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni, struct in_addr vtep_ip) { - zebra_vni_t *zvni; - u_int32_t num_neigh; - struct neigh_walk_ctx wctx; + zebra_vni_t *zvni; + u_int32_t num_neigh; + struct neigh_walk_ctx wctx; - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist\n", vni); - return; - } - num_neigh = hashcount(zvni->neigh_table); - if (!num_neigh) - return; + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist\n", vni); + return; + } + num_neigh = hashcount(zvni->neigh_table); + if (!num_neigh) + return; - memset (&wctx, 0, sizeof (struct neigh_walk_ctx)); - wctx.zvni = zvni; - wctx.vty = vty; - wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP; - wctx.r_vtep_ip = vtep_ip; + memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); + wctx.zvni = zvni; + wctx.vty = vty; + wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP; + wctx.r_vtep_ip = vtep_ip; - hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); + hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); } /* * Display MACs for a VNI (VTY command handler). */ -void -zebra_vxlan_print_macs_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) +void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni) { - zebra_vni_t *zvni; - u_int32_t num_macs; - struct mac_walk_ctx wctx; + zebra_vni_t *zvni; + u_int32_t num_macs; + struct mac_walk_ctx wctx; - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist\n", vni); - return; - } - num_macs = hashcount(zvni->mac_table); - if (!num_macs) - return; + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist\n", vni); + return; + } + num_macs = hashcount(zvni->mac_table); + if (!num_macs) + return; - memset (&wctx, 0, sizeof (struct mac_walk_ctx)); - wctx.zvni = zvni; - wctx.vty = vty; + memset(&wctx, 0, sizeof(struct mac_walk_ctx)); + wctx.zvni = zvni; + wctx.vty = vty; - vty_out(vty, "Number of MACs (local and remote) known for this VNI: %u\n", - num_macs); - vty_out(vty, "%-17s %-6s %-21s %-5s\n", - "MAC", "Type", "Intf/Remote VTEP", "VLAN"); + vty_out(vty, + "Number of MACs (local and remote) known for this VNI: %u\n", + num_macs); + vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type", + "Intf/Remote VTEP", "VLAN"); - hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx); + hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx); } /* * Display MACs for all VNIs (VTY command handler). */ -void -zebra_vxlan_print_macs_all_vni (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf) { - struct mac_walk_ctx wctx; + struct mac_walk_ctx wctx; - if (!EVPN_ENABLED(zvrf)) - return; - memset (&wctx, 0, sizeof (struct mac_walk_ctx)); - wctx.vty = vty; - hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx); + if (!EVPN_ENABLED(zvrf)) + return; + memset(&wctx, 0, sizeof(struct mac_walk_ctx)); + wctx.vty = vty; + hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx); } /* * Display MACs for all VNIs (VTY command handler). */ -void -zebra_vxlan_print_macs_all_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf, - struct in_addr vtep_ip) +void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, + struct zebra_vrf *zvrf, + struct in_addr vtep_ip) { - struct mac_walk_ctx wctx; + struct mac_walk_ctx wctx; - if (!EVPN_ENABLED(zvrf)) - return; - memset (&wctx, 0, sizeof (struct mac_walk_ctx)); - wctx.vty = vty; - wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP; - wctx.r_vtep_ip = vtep_ip; - hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx); + if (!EVPN_ENABLED(zvrf)) + return; + memset(&wctx, 0, sizeof(struct mac_walk_ctx)); + wctx.vty = vty; + wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP; + wctx.r_vtep_ip = vtep_ip; + hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx); } /* * Display specific MAC for a VNI, if present (VTY command handler). */ -void -zebra_vxlan_print_specific_mac_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct ethaddr *macaddr) +void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni, struct ethaddr *macaddr) { - zebra_vni_t *zvni; - zebra_mac_t *mac; + zebra_vni_t *zvni; + zebra_mac_t *mac; - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist\n", vni); - return; - } - mac = zvni_mac_lookup (zvni, macaddr); - if (!mac) - { - vty_out (vty, "%% Requested MAC does not exist in VNI %u\n", - vni); - return; - } + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist\n", vni); + return; + } + mac = zvni_mac_lookup(zvni, macaddr); + if (!mac) { + vty_out(vty, "%% Requested MAC does not exist in VNI %u\n", + vni); + return; + } - zvni_print_mac (mac, vty); + zvni_print_mac(mac, vty); } /* * Display MACs for a VNI from specific VTEP (VTY command handler). */ -void -zebra_vxlan_print_macs_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct in_addr vtep_ip) +void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni, struct in_addr vtep_ip) { - zebra_vni_t *zvni; - u_int32_t num_macs; - struct mac_walk_ctx wctx; + zebra_vni_t *zvni; + u_int32_t num_macs; + struct mac_walk_ctx wctx; - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist\n", vni); - return; - } - num_macs = hashcount(zvni->mac_table); - if (!num_macs) - return; - memset (&wctx, 0, sizeof (struct mac_walk_ctx)); - wctx.zvni = zvni; - wctx.vty = vty; - wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP; - wctx.r_vtep_ip = vtep_ip; - hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx); + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist\n", vni); + return; + } + num_macs = hashcount(zvni->mac_table); + if (!num_macs) + return; + memset(&wctx, 0, sizeof(struct mac_walk_ctx)); + wctx.zvni = zvni; + wctx.vty = vty; + wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP; + wctx.r_vtep_ip = vtep_ip; + hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx); } /* * Display VNI information (VTY command handler). */ -void -zebra_vxlan_print_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) +void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) { - zebra_vni_t *zvni; + zebra_vni_t *zvni; - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist\n", vni); - return; - } - zvni_print (zvni, (void *)vty); + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist\n", vni); + return; + } + zvni_print(zvni, (void *)vty); } /* * Display VNI hash table (VTY command handler). */ -void -zebra_vxlan_print_vnis (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf) { - u_int32_t num_vnis; + u_int32_t num_vnis; - if (!EVPN_ENABLED(zvrf)) - return; - num_vnis = hashcount(zvrf->vni_table); - if (!num_vnis) - return; - vty_out(vty, "Number of VNIs: %u\n", num_vnis); - vty_out(vty, "%-10s %-21s %-15s %-8s %-8s %-15s\n", - "VNI", "VxLAN IF", "VTEP IP", "# MACs", "# ARPs", - "# Remote VTEPs"); - hash_iterate(zvrf->vni_table, zvni_print_hash, vty); + if (!EVPN_ENABLED(zvrf)) + return; + num_vnis = hashcount(zvrf->vni_table); + if (!num_vnis) + return; + vty_out(vty, "Number of VNIs: %u\n", num_vnis); + vty_out(vty, "%-10s %-21s %-15s %-8s %-8s %-15s\n", "VNI", "VxLAN IF", + "VTEP IP", "# MACs", "# ARPs", "# Remote VTEPs"); + hash_iterate(zvrf->vni_table, zvni_print_hash, vty); } /* @@ -2049,293 +1880,292 @@ zebra_vxlan_print_vnis (struct vty *vty, struct zebra_vrf *zvrf) * our database or being re-added to the kernel (if it is a valid * remote neighbor). */ -int -zebra_vxlan_local_neigh_del (struct interface *ifp, - struct interface *link_if, - struct ipaddr *ip) -{ - zebra_vni_t *zvni; - zebra_neigh_t *n; - struct zebra_vrf *zvrf; - char buf[INET6_ADDRSTRLEN]; - - /* We are only interested in neighbors on an SVI that resides on top - * of a VxLAN bridge. - */ - zvni = zvni_map_svi (ifp, link_if); - if (!zvni) - return 0; - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon local neighbor DEL", - zvni->vni, zvni); - return -1; - } - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Del neighbor %s intf %s(%u) -> VNI %u", - ifp->vrf_id, ipaddr2str (ip, buf, sizeof(buf)), - ifp->name, ifp->ifindex, zvni->vni); - - /* If entry doesn't exist, nothing to do. */ - n = zvni_neigh_lookup (zvni, ip); - if (!n) - return 0; - - /* If it is a remote entry, the kernel has aged this out or someone has - * deleted it, it needs to be re-installed as Quagga is the owner. - */ - if (CHECK_FLAG (n->flags, ZEBRA_NEIGH_REMOTE)) - { - zvni_neigh_install (zvni, n); - return 0; - } - - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - assert(zvrf); - - /* Remove neighbor from BGP. */ - zvni_neigh_send_del_to_client (zvrf, zvni->vni, &n->ip, &n->emac); - - /* Delete this neighbor entry. */ - zvni_neigh_del (zvni, n); - - return 0; +int zebra_vxlan_local_neigh_del(struct interface *ifp, + struct interface *link_if, struct ipaddr *ip) +{ + zebra_vni_t *zvni; + zebra_neigh_t *n; + struct zebra_vrf *zvrf; + char buf[INET6_ADDRSTRLEN]; + + /* We are only interested in neighbors on an SVI that resides on top + * of a VxLAN bridge. + */ + zvni = zvni_map_svi(ifp, link_if); + if (!zvni) + return 0; + if (!zvni->vxlan_if) { + zlog_err( + "VNI %u hash %p doesn't have intf upon local neighbor DEL", + zvni->vni, zvni); + return -1; + } + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Del neighbor %s intf %s(%u) -> VNI %u", + ifp->vrf_id, ipaddr2str(ip, buf, sizeof(buf)), + ifp->name, ifp->ifindex, zvni->vni); + + /* If entry doesn't exist, nothing to do. */ + n = zvni_neigh_lookup(zvni, ip); + if (!n) + return 0; + + /* If it is a remote entry, the kernel has aged this out or someone has + * deleted it, it needs to be re-installed as Quagga is the owner. + */ + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { + zvni_neigh_install(zvni, n); + return 0; + } + + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + assert(zvrf); + + /* Remove neighbor from BGP. */ + zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac); + + /* Delete this neighbor entry. */ + zvni_neigh_del(zvni, n); + + return 0; } /* * Handle neighbor add or update (on a VLAN device / L3 interface) * from the kernel. */ -int -zebra_vxlan_local_neigh_add_update (struct interface *ifp, - struct interface *link_if, - struct ipaddr *ip, - struct ethaddr *macaddr, - u_int16_t state, - u_char ext_learned) -{ - zebra_vni_t *zvni; - zebra_neigh_t *n; - struct zebra_vrf *zvrf; - char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - int send_upd = 1, send_del = 0; - - /* We are only interested in neighbors on an SVI that resides on top - * of a VxLAN bridge. - */ - zvni = zvni_map_svi (ifp, link_if); - if (!zvni) - return 0; - - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - assert(zvrf); - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x " - "%s-> VNI %u", - ifp->vrf_id, ipaddr2str (ip, buf2, sizeof(buf2)), - prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, state, - ext_learned ? "ext-learned " : "", zvni->vni); - - /* If same entry already exists, it might be a change or it might be a - * move from remote to local. - */ - n = zvni_neigh_lookup (zvni, ip); - if (n) - { - if (CHECK_FLAG (n->flags, ZEBRA_NEIGH_LOCAL)) - { - if (memcmp (n->emac.octet, macaddr->octet, ETHER_ADDR_LEN) == 0) - { - if (n->ifindex == ifp->ifindex) - /* we're not interested in whatever has changed. */ - return 0; - /* client doesn't care about a purely local change. */ - send_upd = 0; - } - else - /* If the MAC has changed, issue a delete first as this means a - * different MACIP route. - */ - send_del = 1; - } - else if (ext_learned) - /* The neighbor is remote and that is the notification we got. */ - { - /* TODO: Evaluate if we need to do anything here. */ - return 0; - } - else - /* Neighbor has moved from remote to local. */ - { - UNSET_FLAG (n->flags, ZEBRA_NEIGH_REMOTE); - n->r_vtep_ip.s_addr = 0; - } - } - else - { - n = zvni_neigh_add (zvni, ip); - if (!n) - { - zlog_err ("%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u", - ifp->vrf_id, ipaddr2str (ip, buf2, sizeof(buf2)), - prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, zvni->vni); - return -1; - } - } - - /* Issue delete for older info, if needed. */ - if (send_del) - zvni_neigh_send_del_to_client (zvrf, zvni->vni, &n->ip, &n->emac); - - /* Set "local" forwarding info. */ - SET_FLAG (n->flags, ZEBRA_NEIGH_LOCAL); - memcpy (&n->emac, macaddr, ETHER_ADDR_LEN); - n->ifindex = ifp->ifindex; - - /* Inform BGP if required. */ - if (send_upd) - return zvni_neigh_send_add_to_client (zvrf, zvni->vni, ip, macaddr); - - return 0; +int zebra_vxlan_local_neigh_add_update(struct interface *ifp, + struct interface *link_if, + struct ipaddr *ip, + struct ethaddr *macaddr, u_int16_t state, + u_char ext_learned) +{ + zebra_vni_t *zvni; + zebra_neigh_t *n; + struct zebra_vrf *zvrf; + char buf[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + int send_upd = 1, send_del = 0; + + /* We are only interested in neighbors on an SVI that resides on top + * of a VxLAN bridge. + */ + zvni = zvni_map_svi(ifp, link_if); + if (!zvni) + return 0; + + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + assert(zvrf); + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x " + "%s-> VNI %u", + ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)), + prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, + ifp->ifindex, state, ext_learned ? "ext-learned " : "", + zvni->vni); + + /* If same entry already exists, it might be a change or it might be a + * move from remote to local. + */ + n = zvni_neigh_lookup(zvni, ip); + if (n) { + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { + if (memcmp(n->emac.octet, macaddr->octet, + ETHER_ADDR_LEN) + == 0) { + if (n->ifindex == ifp->ifindex) + /* we're not interested in whatever has + * changed. */ + return 0; + /* client doesn't care about a purely local + * change. */ + send_upd = 0; + } else + /* If the MAC has changed, issue a delete first + * as this means a + * different MACIP route. + */ + send_del = 1; + } else if (ext_learned) + /* The neighbor is remote and that is the notification we got. + */ + { + /* TODO: Evaluate if we need to do anything here. */ + return 0; + } else + /* Neighbor has moved from remote to local. */ + { + UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); + n->r_vtep_ip.s_addr = 0; + } + } else { + n = zvni_neigh_add(zvni, ip); + if (!n) { + zlog_err( + "%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u", + ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)), + prefix_mac2str(macaddr, buf, sizeof(buf)), + ifp->name, ifp->ifindex, zvni->vni); + return -1; + } + } + + /* Issue delete for older info, if needed. */ + if (send_del) + zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, + &n->emac); + + /* Set "local" forwarding info. */ + SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); + memcpy(&n->emac, macaddr, ETHER_ADDR_LEN); + n->ifindex = ifp->ifindex; + + /* Inform BGP if required. */ + if (send_upd) + return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip, + macaddr); + + return 0; } /* * Handle message from client to delete a remote MACIP for a VNI. */ -int zebra_vxlan_remote_macip_del (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) -{ - struct stream *s; - vni_t vni; - struct ethaddr macaddr; - struct ipaddr ip; - struct in_addr vtep_ip; - zebra_vni_t *zvni; - zebra_mac_t *mac; - zebra_neigh_t *n; - u_short l = 0, ipa_len; - char buf[ETHER_ADDR_STRLEN]; - char buf1[INET6_ADDRSTRLEN]; - - s = client->ibuf; - - while (l < length) - { - /* Obtain each remote MACIP and process. */ - /* Message contains VNI, followed by MAC followed by IP (if any) - * followed by remote VTEP IP. - */ - mac = NULL; - n = NULL; - memset (&ip, 0, sizeof (ip)); - vni = (vni_t) stream_getl (s); - stream_get (&macaddr.octet, s, ETHER_ADDR_LEN); - ipa_len = stream_getl (s); - if (ipa_len) - { - ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4: IPADDR_V6; - stream_get (&ip.ip.addr, s, ipa_len); - } - l += 4 + ETHER_ADDR_LEN + 4 + ipa_len; - vtep_ip.s_addr = stream_get_ipv4(s); - l += IPV4_MAX_BYTELEN; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s", - zvrf_id (zvrf), - prefix_mac2str (&macaddr, buf, sizeof (buf)), - ipaddr2str (&ip, buf1, sizeof (buf1)), - vni, inet_ntoa (vtep_ip), - zebra_route_string (client->proto)); - - /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("Failed to locate VNI hash upon remote MACIP DEL, " - "VRF %d VNI %u", zvrf_id (zvrf), vni); - continue; - } - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon remote MACIP DEL", - vni, zvni); - continue; - } - - /* The remote VTEP specified is normally expected to exist, but it is - * possible that the peer may delete the VTEP before deleting any MACs - * referring to the VTEP, in which case the handler (see remote_vtep_del) - * would have already deleted the MACs. - */ - if (!zvni_vtep_find (zvni, &vtep_ip)) - continue; - - /* If the local VxLAN interface is not up (should be a transient - * event), there's nothing more to do. - */ - if (!if_is_operative (zvni->vxlan_if)) - continue; - - mac = zvni_mac_lookup (zvni, &macaddr); - if (ipa_len) - n = zvni_neigh_lookup (zvni, &ip); - - if (n && !mac) - { - zlog_err ("failed to locate MAC %s for neigh %s in VRF %u VNI %u", - prefix_mac2str (&macaddr, buf, sizeof (buf)), - ipaddr2str (&ip, buf1, sizeof (buf1)), - zvrf_id (zvrf), vni); - continue; - } - - /* If the remote mac or neighbor doesn't exist there is nothing more - * to do. Otherwise, uninstall the entry and then remove it. - */ - if (!mac && !n) - continue; - - /* Uninstall remote neighbor or MAC. */ - if (n) - { - /* When the MAC changes for an IP, it is possible the client may - * update the new MAC before trying to delete the "old" neighbor - * (as these are two different MACIP routes). Do the delete only - * if the MAC matches. - */ - if (CHECK_FLAG (n->flags, ZEBRA_NEIGH_REMOTE) && - (memcmp (n->emac.octet, macaddr.octet, ETHER_ADDR_LEN) == 0)) - { - zvni_neigh_uninstall (zvni, n); - zvni_neigh_del (zvni, n); - zvni_deref_ip2mac (zvni, mac, 1); - } - } - else - { - if (CHECK_FLAG (mac->flags, ZEBRA_MAC_REMOTE)) - { - if (!mac->neigh_refcnt) - { - zvni_mac_uninstall (zvni, mac, 0); - zvni_mac_del (zvni, mac); - } - else - SET_FLAG (mac->flags, ZEBRA_MAC_AUTO); - } - } - } - - return 0; +int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) +{ + struct stream *s; + vni_t vni; + struct ethaddr macaddr; + struct ipaddr ip; + struct in_addr vtep_ip; + zebra_vni_t *zvni; + zebra_mac_t *mac; + zebra_neigh_t *n; + u_short l = 0, ipa_len; + char buf[ETHER_ADDR_STRLEN]; + char buf1[INET6_ADDRSTRLEN]; + + s = client->ibuf; + + while (l < length) { + /* Obtain each remote MACIP and process. */ + /* Message contains VNI, followed by MAC followed by IP (if any) + * followed by remote VTEP IP. + */ + mac = NULL; + n = NULL; + memset(&ip, 0, sizeof(ip)); + vni = (vni_t)stream_getl(s); + stream_get(&macaddr.octet, s, ETHER_ADDR_LEN); + ipa_len = stream_getl(s); + if (ipa_len) { + ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 + : IPADDR_V6; + stream_get(&ip.ip.addr, s, ipa_len); + } + l += 4 + ETHER_ADDR_LEN + 4 + ipa_len; + vtep_ip.s_addr = stream_get_ipv4(s); + l += IPV4_MAX_BYTELEN; + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s", + zvrf_id(zvrf), + prefix_mac2str(&macaddr, buf, sizeof(buf)), + ipaddr2str(&ip, buf1, sizeof(buf1)), vni, + inet_ntoa(vtep_ip), + zebra_route_string(client->proto)); + + /* Locate VNI hash entry - expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "Failed to locate VNI hash upon remote MACIP DEL, " + "VRF %d VNI %u", + zvrf_id(zvrf), vni); + continue; + } + if (!zvni->vxlan_if) { + zlog_err( + "VNI %u hash %p doesn't have intf upon remote MACIP DEL", + vni, zvni); + continue; + } + + /* The remote VTEP specified is normally expected to exist, but + * it is + * possible that the peer may delete the VTEP before deleting + * any MACs + * referring to the VTEP, in which case the handler (see + * remote_vtep_del) + * would have already deleted the MACs. + */ + if (!zvni_vtep_find(zvni, &vtep_ip)) + continue; + + /* If the local VxLAN interface is not up (should be a transient + * event), there's nothing more to do. + */ + if (!if_is_operative(zvni->vxlan_if)) + continue; + + mac = zvni_mac_lookup(zvni, &macaddr); + if (ipa_len) + n = zvni_neigh_lookup(zvni, &ip); + + if (n && !mac) { + zlog_err( + "failed to locate MAC %s for neigh %s in VRF %u VNI %u", + prefix_mac2str(&macaddr, buf, sizeof(buf)), + ipaddr2str(&ip, buf1, sizeof(buf1)), + zvrf_id(zvrf), vni); + continue; + } + + /* If the remote mac or neighbor doesn't exist there is nothing + * more + * to do. Otherwise, uninstall the entry and then remove it. + */ + if (!mac && !n) + continue; + + /* Uninstall remote neighbor or MAC. */ + if (n) { + /* When the MAC changes for an IP, it is possible the + * client may + * update the new MAC before trying to delete the "old" + * neighbor + * (as these are two different MACIP routes). Do the + * delete only + * if the MAC matches. + */ + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) + && (memcmp(n->emac.octet, macaddr.octet, + ETHER_ADDR_LEN) + == 0)) { + zvni_neigh_uninstall(zvni, n); + zvni_neigh_del(zvni, n); + zvni_deref_ip2mac(zvni, mac, 1); + } + } else { + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { + if (!mac->neigh_refcnt) { + zvni_mac_uninstall(zvni, mac, 0); + zvni_mac_del(zvni, mac); + } else + SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); + } + } + } + + return 0; } /* @@ -2343,205 +2173,206 @@ int zebra_vxlan_remote_macip_del (struct zserv *client, int sock, * could be just the add of a MAC address or the add of a neighbor * (IP+MAC). */ -int -zebra_vxlan_remote_macip_add (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) -{ - struct stream *s; - vni_t vni; - struct ethaddr macaddr; - struct ipaddr ip; - struct in_addr vtep_ip; - zebra_vni_t *zvni; - zebra_vtep_t *zvtep; - zebra_mac_t *mac, *old_mac; - zebra_neigh_t *n; - u_short l = 0, ipa_len; - int update_mac = 0, update_neigh = 0; - char buf[ETHER_ADDR_STRLEN]; - char buf1[INET6_ADDRSTRLEN]; - u_char sticky; - - assert (EVPN_ENABLED (zvrf)); - - s = client->ibuf; - - while (l < length) - { - /* Obtain each remote MACIP and process. */ - /* Message contains VNI, followed by MAC followed by IP (if any) - * followed by remote VTEP IP. - */ - update_mac = update_neigh = 0; - mac = NULL; - n = NULL; - memset (&ip, 0, sizeof (ip)); - vni = (vni_t) stream_getl (s); - stream_get (&macaddr.octet, s, ETHER_ADDR_LEN); - ipa_len = stream_getl (s); - if (ipa_len) - { - ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4: IPADDR_V6; - stream_get (&ip.ip.addr, s, ipa_len); - } - l += 4 + ETHER_ADDR_LEN + 4 + ipa_len; - vtep_ip.s_addr = stream_get_ipv4 (s); - l += IPV4_MAX_BYTELEN; - - /* Get 'sticky' flag. */ - sticky = stream_getc(s); - l++; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Recv MACIP Add %sMAC %s IP %s VNI %u Remote VTEP %s from %s", - zvrf_id (zvrf), - sticky ? "sticky " : "", - prefix_mac2str (&macaddr, buf, sizeof (buf)), - ipaddr2str (&ip, buf1, sizeof (buf1)), - vni, inet_ntoa (vtep_ip), - zebra_route_string (client->proto)); - - /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to locate VNI hash upon remote MACIP ADD, VRF %d VNI %u", - zvrf_id (zvrf), vni); - continue; - } - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon remote MACIP add", - vni, zvni); - continue; - } - /* If the local VxLAN interface is not up (should be a transient - * event), there's nothing more to do. - */ - if (!if_is_operative (zvni->vxlan_if)) - continue; - - /* The remote VTEP specified should normally exist, but it is possible - * that when peering comes up, peer may advertise MACIP routes before - * advertising type-3 routes. - */ - zvtep = zvni_vtep_find (zvni, &vtep_ip); - if (!zvtep) - { - if (zvni_vtep_add (zvni, &vtep_ip) == NULL) - { - zlog_err ("Failed to add remote VTEP, VRF %d VNI %u zvni %p", - zvrf_id (zvrf), vni, zvni); - continue; - } - - zvni_vtep_install (zvni, &vtep_ip); - } - - /* First, check if the remote MAC is unknown or has a change. If so, - * that needs to be updated first. Note that client could install - * MAC and MACIP separately or just install the latter. - */ - mac = zvni_mac_lookup (zvni, &macaddr); - if (!mac || !CHECK_FLAG (mac->flags, ZEBRA_MAC_REMOTE) || - (CHECK_FLAG (mac->flags, ZEBRA_MAC_STICKY) ? 1: 0) != sticky || - !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)) - update_mac = 1; - - if (update_mac) - { - if (!mac) - { - mac = zvni_mac_add (zvni, &macaddr); - if (!mac) - { - zlog_warn ("%u:Failed to add MAC %s VNI %u Remote VTEP %s", - zvrf_id (zvrf), - prefix_mac2str (&macaddr, buf, sizeof (buf)), - vni, inet_ntoa (vtep_ip)); - return -1; - } - - /* Is this MAC created for a MACIP? */ - if (ipa_len) - SET_FLAG (mac->flags, ZEBRA_MAC_AUTO); - } - else if (CHECK_FLAG (mac->flags, ZEBRA_MAC_LOCAL)) - { - /* Moving from local to remote, issue delete. */ - zvni_mac_uninstall (zvni, mac, 1); - } - - /* Set "auto" and "remote" forwarding info. */ - UNSET_FLAG (mac->flags, ZEBRA_MAC_LOCAL); - memset (&mac->fwd_info, 0, sizeof (mac->fwd_info)); - SET_FLAG (mac->flags, ZEBRA_MAC_REMOTE); - mac->fwd_info.r_vtep_ip = vtep_ip; - - if (sticky) - SET_FLAG (mac->flags, ZEBRA_MAC_STICKY); - else - UNSET_FLAG (mac->flags, ZEBRA_MAC_STICKY); - - /* Install the entry. */ - zvni_mac_install (zvni, mac); - } - - /* If there is no IP, continue - after clearing AUTO flag of MAC. */ - if (!ipa_len) - { - UNSET_FLAG (mac->flags, ZEBRA_MAC_AUTO); - continue; - } - - /* Check if the remote neighbor itself is unknown or has a change. - * If so, create or update and then install the entry. - */ - n = zvni_neigh_lookup (zvni, &ip); - if (!n || !CHECK_FLAG (n->flags, ZEBRA_NEIGH_REMOTE) || - (memcmp(&n->emac, &macaddr, sizeof (macaddr)) != 0) || - !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip)) - update_neigh = 1; - - if (update_neigh) - { - if (!n) - { - n = zvni_neigh_add (zvni, &ip); - if (!n) - { - zlog_warn ("%u:Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s", - zvrf_id (zvrf), ipaddr2str (&ip, buf1, sizeof (buf1)), - prefix_mac2str (&macaddr, buf, sizeof (buf)), - vni, inet_ntoa (vtep_ip)); - return -1; - } - - /* New neighbor referring to this MAC. */ - mac->neigh_refcnt++; - } - else if (memcmp(&n->emac, &macaddr, sizeof (macaddr)) != 0) - { - /* MAC change, update ref counts for old and new MAC. */ - old_mac = zvni_mac_lookup (zvni, &n->emac); - if (old_mac) - zvni_deref_ip2mac (zvni, old_mac, 1); - mac->neigh_refcnt++; - } - - /* Set "remote" forwarding info. */ - UNSET_FLAG (n->flags, ZEBRA_NEIGH_LOCAL); - /* TODO: Handle MAC change. */ - memcpy (&n->emac, &macaddr, ETHER_ADDR_LEN); - n->r_vtep_ip = vtep_ip; - SET_FLAG (n->flags, ZEBRA_NEIGH_REMOTE); - - /* Install the entry. */ - zvni_neigh_install (zvni, n); - } - } - - return 0; +int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) +{ + struct stream *s; + vni_t vni; + struct ethaddr macaddr; + struct ipaddr ip; + struct in_addr vtep_ip; + zebra_vni_t *zvni; + zebra_vtep_t *zvtep; + zebra_mac_t *mac, *old_mac; + zebra_neigh_t *n; + u_short l = 0, ipa_len; + int update_mac = 0, update_neigh = 0; + char buf[ETHER_ADDR_STRLEN]; + char buf1[INET6_ADDRSTRLEN]; + u_char sticky; + + assert(EVPN_ENABLED(zvrf)); + + s = client->ibuf; + + while (l < length) { + /* Obtain each remote MACIP and process. */ + /* Message contains VNI, followed by MAC followed by IP (if any) + * followed by remote VTEP IP. + */ + update_mac = update_neigh = 0; + mac = NULL; + n = NULL; + memset(&ip, 0, sizeof(ip)); + vni = (vni_t)stream_getl(s); + stream_get(&macaddr.octet, s, ETHER_ADDR_LEN); + ipa_len = stream_getl(s); + if (ipa_len) { + ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 + : IPADDR_V6; + stream_get(&ip.ip.addr, s, ipa_len); + } + l += 4 + ETHER_ADDR_LEN + 4 + ipa_len; + vtep_ip.s_addr = stream_get_ipv4(s); + l += IPV4_MAX_BYTELEN; + + /* Get 'sticky' flag. */ + sticky = stream_getc(s); + l++; + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Recv MACIP Add %sMAC %s IP %s VNI %u Remote VTEP %s from %s", + zvrf_id(zvrf), sticky ? "sticky " : "", + prefix_mac2str(&macaddr, buf, sizeof(buf)), + ipaddr2str(&ip, buf1, sizeof(buf1)), vni, + inet_ntoa(vtep_ip), + zebra_route_string(client->proto)); + + /* Locate VNI hash entry - expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to locate VNI hash upon remote MACIP ADD, VRF %d VNI %u", + zvrf_id(zvrf), vni); + continue; + } + if (!zvni->vxlan_if) { + zlog_err( + "VNI %u hash %p doesn't have intf upon remote MACIP add", + vni, zvni); + continue; + } + /* If the local VxLAN interface is not up (should be a transient + * event), there's nothing more to do. + */ + if (!if_is_operative(zvni->vxlan_if)) + continue; + + /* The remote VTEP specified should normally exist, but it is + * possible + * that when peering comes up, peer may advertise MACIP routes + * before + * advertising type-3 routes. + */ + zvtep = zvni_vtep_find(zvni, &vtep_ip); + if (!zvtep) { + if (zvni_vtep_add(zvni, &vtep_ip) == NULL) { + zlog_err( + "Failed to add remote VTEP, VRF %d VNI %u zvni %p", + zvrf_id(zvrf), vni, zvni); + continue; + } + + zvni_vtep_install(zvni, &vtep_ip); + } + + /* First, check if the remote MAC is unknown or has a change. If + * so, + * that needs to be updated first. Note that client could + * install + * MAC and MACIP separately or just install the latter. + */ + mac = zvni_mac_lookup(zvni, &macaddr); + if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) + || (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0) + != sticky + || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)) + update_mac = 1; + + if (update_mac) { + if (!mac) { + mac = zvni_mac_add(zvni, &macaddr); + if (!mac) { + zlog_warn( + "%u:Failed to add MAC %s VNI %u Remote VTEP %s", + zvrf_id(zvrf), + prefix_mac2str(&macaddr, buf, + sizeof(buf)), + vni, inet_ntoa(vtep_ip)); + return -1; + } + + /* Is this MAC created for a MACIP? */ + if (ipa_len) + SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); + } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { + /* Moving from local to remote, issue delete. */ + zvni_mac_uninstall(zvni, mac, 1); + } + + /* Set "auto" and "remote" forwarding info. */ + UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); + memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); + SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); + mac->fwd_info.r_vtep_ip = vtep_ip; + + if (sticky) + SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + else + UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + + /* Install the entry. */ + zvni_mac_install(zvni, mac); + } + + /* If there is no IP, continue - after clearing AUTO flag of + * MAC. */ + if (!ipa_len) { + UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO); + continue; + } + + /* Check if the remote neighbor itself is unknown or has a + * change. + * If so, create or update and then install the entry. + */ + n = zvni_neigh_lookup(zvni, &ip); + if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) + || (memcmp(&n->emac, &macaddr, sizeof(macaddr)) != 0) + || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip)) + update_neigh = 1; + + if (update_neigh) { + if (!n) { + n = zvni_neigh_add(zvni, &ip); + if (!n) { + zlog_warn( + "%u:Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s", + zvrf_id(zvrf), + ipaddr2str(&ip, buf1, + sizeof(buf1)), + prefix_mac2str(&macaddr, buf, + sizeof(buf)), + vni, inet_ntoa(vtep_ip)); + return -1; + } + + /* New neighbor referring to this MAC. */ + mac->neigh_refcnt++; + } else if (memcmp(&n->emac, &macaddr, sizeof(macaddr)) + != 0) { + /* MAC change, update ref counts for old and new + * MAC. */ + old_mac = zvni_mac_lookup(zvni, &n->emac); + if (old_mac) + zvni_deref_ip2mac(zvni, old_mac, 1); + mac->neigh_refcnt++; + } + + /* Set "remote" forwarding info. */ + UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); + /* TODO: Handle MAC change. */ + memcpy(&n->emac, &macaddr, ETHER_ADDR_LEN); + n->r_vtep_ip = vtep_ip; + SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); + + /* Install the entry. */ + zvni_neigh_install(zvni, n); + } + } + + return 0; } /* @@ -2549,61 +2380,60 @@ zebra_vxlan_remote_macip_add (struct zserv *client, int sock, * us, this must involve a multihoming scenario. Treat this as implicit delete * of any prior local MAC. */ -int -zebra_vxlan_check_del_local_mac (struct interface *ifp, - struct interface *br_if, - struct ethaddr *macaddr, - vlanid_t vid) +int zebra_vxlan_check_del_local_mac(struct interface *ifp, + struct interface *br_if, + struct ethaddr *macaddr, vlanid_t vid) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - struct zebra_l2info_vxlan *vxl; - vni_t vni; - zebra_vni_t *zvni; - zebra_mac_t *mac; - char buf[ETHER_ADDR_STRLEN]; - u_char sticky; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + struct zebra_l2info_vxlan *vxl; + vni_t vni; + zebra_vni_t *zvni; + zebra_mac_t *mac; + char buf[ETHER_ADDR_STRLEN]; + u_char sticky; - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* If EVPN is not enabled, nothing to do. */ - if (!EVPN_ENABLED(zvrf)) - return 0; + /* If EVPN is not enabled, nothing to do. */ + if (!EVPN_ENABLED(zvrf)) + return 0; - /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - return 0; + /* Locate hash entry; it is expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) + return 0; - /* If entry doesn't exist, nothing to do. */ - mac = zvni_mac_lookup (zvni, macaddr); - if (!mac) - return 0; + /* If entry doesn't exist, nothing to do. */ + mac = zvni_mac_lookup(zvni, macaddr); + if (!mac) + return 0; - /* Is it a local entry? */ - if (!CHECK_FLAG (mac->flags, ZEBRA_MAC_LOCAL)) - return 0; + /* Is it a local entry? */ + if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) + return 0; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Add/update remote MAC %s intf %s(%u) VNI %u - del local", - ifp->vrf_id, prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vni); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Add/update remote MAC %s intf %s(%u) VNI %u - del local", + ifp->vrf_id, prefix_mac2str(macaddr, buf, sizeof(buf)), + ifp->name, ifp->ifindex, vni); - /* Remove MAC from BGP. */ - sticky = CHECK_FLAG (mac->flags, ZEBRA_MAC_STICKY) ? 1: 0; - zvni_mac_send_del_to_client (zvrf, zvni->vni, macaddr, sticky); + /* Remove MAC from BGP. */ + sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0; + zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr, sticky); - /* Delete this MAC entry. */ - zvni_mac_del (zvni, mac); + /* Delete this MAC entry. */ + zvni_mac_del(zvni, mac); - return 0; + return 0; } /* @@ -2611,346 +2441,346 @@ zebra_vxlan_check_del_local_mac (struct interface *ifp, * This can happen because the remote MAC entries are also added as "dynamic", * so the kernel can ageout the entry. */ -int -zebra_vxlan_check_readd_remote_mac (struct interface *ifp, - struct interface *br_if, - struct ethaddr *macaddr, - vlanid_t vid) +int zebra_vxlan_check_readd_remote_mac(struct interface *ifp, + struct interface *br_if, + struct ethaddr *macaddr, vlanid_t vid) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - struct zebra_l2info_vxlan *vxl; - vni_t vni; - zebra_vni_t *zvni; - zebra_mac_t *mac; - char buf[ETHER_ADDR_STRLEN]; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + struct zebra_l2info_vxlan *vxl; + vni_t vni; + zebra_vni_t *zvni; + zebra_mac_t *mac; + char buf[ETHER_ADDR_STRLEN]; - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* If EVPN is not enabled, nothing to do. */ - if (!EVPN_ENABLED(zvrf)) - return 0; + /* If EVPN is not enabled, nothing to do. */ + if (!EVPN_ENABLED(zvrf)) + return 0; - /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - return 0; + /* Locate hash entry; it is expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) + return 0; - /* If entry doesn't exist, nothing to do. */ - mac = zvni_mac_lookup (zvni, macaddr); - if (!mac) - return 0; + /* If entry doesn't exist, nothing to do. */ + mac = zvni_mac_lookup(zvni, macaddr); + if (!mac) + return 0; - /* Is it a remote entry? */ - if (!CHECK_FLAG (mac->flags, ZEBRA_MAC_REMOTE)) - return 0; + /* Is it a remote entry? */ + if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) + return 0; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Del remote MAC %s intf %s(%u) VNI %u - readd", - ifp->vrf_id, prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vni); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Del remote MAC %s intf %s(%u) VNI %u - readd", + ifp->vrf_id, + prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, + ifp->ifindex, vni); - zvni_mac_install (zvni, mac); - return 0; + zvni_mac_install(zvni, mac); + return 0; } /* * Handle local MAC delete (on a port or VLAN corresponding to this VNI). */ -int -zebra_vxlan_local_mac_del (struct interface *ifp, struct interface *br_if, - struct ethaddr *macaddr, vlanid_t vid) +int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, + struct ethaddr *macaddr, vlanid_t vid) { - zebra_vni_t *zvni; - zebra_mac_t *mac; - struct zebra_vrf *zvrf; - char buf[ETHER_ADDR_STRLEN]; - u_char sticky; + zebra_vni_t *zvni; + zebra_mac_t *mac; + struct zebra_vrf *zvrf; + char buf[ETHER_ADDR_STRLEN]; + u_char sticky; - /* We are interested in MACs only on ports or (port, VLAN) that - * map to a VNI. - */ - zvni = zvni_map_vlan (ifp, br_if, vid); - if (!zvni) - return 0; - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon local MAC DEL", - zvni->vni, zvni); - return -1; - } + /* We are interested in MACs only on ports or (port, VLAN) that + * map to a VNI. + */ + zvni = zvni_map_vlan(ifp, br_if, vid); + if (!zvni) + return 0; + if (!zvni->vxlan_if) { + zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL", + zvni->vni, zvni); + return -1; + } - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Del MAC %s intf %s(%u) VID %u -> VNI %u", - ifp->vrf_id, prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vid, zvni->vni); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Del MAC %s intf %s(%u) VID %u -> VNI %u", + ifp->vrf_id, + prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, + ifp->ifindex, vid, zvni->vni); - /* If entry doesn't exist, nothing to do. */ - mac = zvni_mac_lookup (zvni, macaddr); - if (!mac) - return 0; + /* If entry doesn't exist, nothing to do. */ + mac = zvni_mac_lookup(zvni, macaddr); + if (!mac) + return 0; - /* Is it a local entry? */ - if (!CHECK_FLAG (mac->flags, ZEBRA_MAC_LOCAL)) - return 0; + /* Is it a local entry? */ + if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) + return 0; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + assert(zvrf); - /* Remove MAC from BGP. */ - sticky = CHECK_FLAG (mac->flags, ZEBRA_MAC_STICKY) ? 1: 0; - zvni_mac_send_del_to_client (zvrf, zvni->vni, macaddr, sticky); + /* Remove MAC from BGP. */ + sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0; + zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr, sticky); - /* Delete this MAC entry. */ - zvni_mac_del (zvni, mac); + /* Delete this MAC entry. */ + zvni_mac_del(zvni, mac); - return 0; + return 0; } /* * Handle local MAC add (on a port or VLAN corresponding to this VNI). */ -int -zebra_vxlan_local_mac_add_update (struct interface *ifp, struct interface *br_if, - struct ethaddr *macaddr, vlanid_t vid, - u_char sticky) -{ - zebra_vni_t *zvni; - zebra_mac_t *mac; - struct zebra_vrf *zvrf; - char buf[ETHER_ADDR_STRLEN]; - int add = 1; - u_char mac_sticky; - - /* We are interested in MACs only on ports or (port, VLAN) that - * map to a VNI. - */ - zvni = zvni_map_vlan (ifp, br_if, vid); - if (!zvni) - { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI", - ifp->vrf_id, - sticky ? "sticky " : "", - prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vid); - return 0; - } - - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon local MAC ADD", - zvni->vni, zvni); - return -1; - } - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u", - ifp->vrf_id, - sticky ? "sticky " : "", - prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vid, zvni->vni); - - /* If same entry already exists, nothing to do. */ - mac = zvni_mac_lookup (zvni, macaddr); - if (mac) - { - if (CHECK_FLAG (mac->flags, ZEBRA_MAC_LOCAL)) - { - mac_sticky = CHECK_FLAG (mac->flags, ZEBRA_MAC_STICKY) ? 1: 0; - - if (mac_sticky == sticky && - mac->fwd_info.local.ifindex == ifp->ifindex && - mac->fwd_info.local.vid == vid) - { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, " - "entry exists and has not changed ", - ifp->vrf_id, - sticky ? "sticky " : "", - prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vid, zvni->vni); - return 0; - } - - add = 0; /* This is an update of local interface. */ - } - } - - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - assert(zvrf); - - if (!mac) - { - mac = zvni_mac_add (zvni, macaddr); - if (!mac) - { - zlog_err ("%u:Failed to add MAC %s intf %s(%u) VID %u", - ifp->vrf_id, prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vid); - return -1; - } - } - - /* Set "local" forwarding info. */ - UNSET_FLAG (mac->flags, ZEBRA_MAC_REMOTE); - memset (&mac->fwd_info, 0, sizeof (mac->fwd_info)); - SET_FLAG (mac->flags, ZEBRA_MAC_LOCAL); - mac->fwd_info.local.ifindex = ifp->ifindex; - mac->fwd_info.local.vid = vid; - - if (sticky) - SET_FLAG (mac->flags, ZEBRA_MAC_STICKY); - else - UNSET_FLAG (mac->flags, ZEBRA_MAC_STICKY); - - /* Inform BGP if required. */ - if (add) - return zvni_mac_send_add_to_client (zvrf, zvni->vni, macaddr, sticky); - - return 0; +int zebra_vxlan_local_mac_add_update(struct interface *ifp, + struct interface *br_if, + struct ethaddr *macaddr, vlanid_t vid, + u_char sticky) +{ + zebra_vni_t *zvni; + zebra_mac_t *mac; + struct zebra_vrf *zvrf; + char buf[ETHER_ADDR_STRLEN]; + int add = 1; + u_char mac_sticky; + + /* We are interested in MACs only on ports or (port, VLAN) that + * map to a VNI. + */ + zvni = zvni_map_vlan(ifp, br_if, vid); + if (!zvni) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI", + ifp->vrf_id, sticky ? "sticky " : "", + prefix_mac2str(macaddr, buf, sizeof(buf)), + ifp->name, ifp->ifindex, vid); + return 0; + } + + if (!zvni->vxlan_if) { + zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD", + zvni->vni, zvni); + return -1; + } + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u", + ifp->vrf_id, sticky ? "sticky " : "", + prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, + ifp->ifindex, vid, zvni->vni); + + /* If same entry already exists, nothing to do. */ + mac = zvni_mac_lookup(zvni, macaddr); + if (mac) { + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { + mac_sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) + ? 1 + : 0; + + if (mac_sticky == sticky + && mac->fwd_info.local.ifindex == ifp->ifindex + && mac->fwd_info.local.vid == vid) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, " + "entry exists and has not changed ", + ifp->vrf_id, + sticky ? "sticky " : "", + prefix_mac2str(macaddr, buf, + sizeof(buf)), + ifp->name, ifp->ifindex, vid, + zvni->vni); + return 0; + } + + add = 0; /* This is an update of local interface. */ + } + } + + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + assert(zvrf); + + if (!mac) { + mac = zvni_mac_add(zvni, macaddr); + if (!mac) { + zlog_err("%u:Failed to add MAC %s intf %s(%u) VID %u", + ifp->vrf_id, + prefix_mac2str(macaddr, buf, sizeof(buf)), + ifp->name, ifp->ifindex, vid); + return -1; + } + } + + /* Set "local" forwarding info. */ + UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); + memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); + SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); + mac->fwd_info.local.ifindex = ifp->ifindex; + mac->fwd_info.local.vid = vid; + + if (sticky) + SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + else + UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + + /* Inform BGP if required. */ + if (add) + return zvni_mac_send_add_to_client(zvrf, zvni->vni, macaddr, + sticky); + + return 0; } /* * Handle message from client to delete a remote VTEP for a VNI. */ -int zebra_vxlan_remote_vtep_del (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) -{ - struct stream *s; - u_short l = 0; - vni_t vni; - struct in_addr vtep_ip; - zebra_vni_t *zvni; - zebra_vtep_t *zvtep; - - s = client->ibuf; - - while (l < length) - { - /* Obtain each remote VTEP and process. */ - vni = (vni_t) stream_getl (s); - l += 4; - vtep_ip.s_addr = stream_get_ipv4 (s); - l += IPV4_MAX_BYTELEN; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Recv VTEP_DEL %s VNI %u from %s", - zvrf_id (zvrf), inet_ntoa (vtep_ip), - vni, zebra_route_string (client->proto)); - - /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("Failed to locate VNI hash upon remote VTEP DEL, " - "VRF %d VNI %u", zvrf_id (zvrf), vni); - continue; - } - - /* If the remote VTEP does not exist, there's nothing more to do. - * Otherwise, uninstall any remote MACs pointing to this VTEP and - * then, the VTEP entry itself and remove it. - */ - zvtep = zvni_vtep_find (zvni, &vtep_ip); - if (!zvtep) - continue; - - zvni_neigh_del_from_vtep (zvni, 1, &vtep_ip); - zvni_mac_del_from_vtep (zvni, 1, &vtep_ip); - zvni_vtep_uninstall (zvni, &vtep_ip); - zvni_vtep_del (zvni, zvtep); - } - - return 0; +int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) +{ + struct stream *s; + u_short l = 0; + vni_t vni; + struct in_addr vtep_ip; + zebra_vni_t *zvni; + zebra_vtep_t *zvtep; + + s = client->ibuf; + + while (l < length) { + /* Obtain each remote VTEP and process. */ + vni = (vni_t)stream_getl(s); + l += 4; + vtep_ip.s_addr = stream_get_ipv4(s); + l += IPV4_MAX_BYTELEN; + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Recv VTEP_DEL %s VNI %u from %s", + zvrf_id(zvrf), inet_ntoa(vtep_ip), vni, + zebra_route_string(client->proto)); + + /* Locate VNI hash entry - expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "Failed to locate VNI hash upon remote VTEP DEL, " + "VRF %d VNI %u", + zvrf_id(zvrf), vni); + continue; + } + + /* If the remote VTEP does not exist, there's nothing more to + * do. + * Otherwise, uninstall any remote MACs pointing to this VTEP + * and + * then, the VTEP entry itself and remove it. + */ + zvtep = zvni_vtep_find(zvni, &vtep_ip); + if (!zvtep) + continue; + + zvni_neigh_del_from_vtep(zvni, 1, &vtep_ip); + zvni_mac_del_from_vtep(zvni, 1, &vtep_ip); + zvni_vtep_uninstall(zvni, &vtep_ip); + zvni_vtep_del(zvni, zvtep); + } + + return 0; } /* * Handle message from client to add a remote VTEP for a VNI. */ -int zebra_vxlan_remote_vtep_add (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) -{ - struct stream *s; - u_short l = 0; - vni_t vni; - struct in_addr vtep_ip; - zebra_vni_t *zvni; - - assert (EVPN_ENABLED (zvrf)); - - s = client->ibuf; - - while (l < length) - { - /* Obtain each remote VTEP and process. */ - vni = (vni_t) stream_getl (s); - l += 4; - vtep_ip.s_addr = stream_get_ipv4 (s); - l += IPV4_MAX_BYTELEN; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Recv VTEP_ADD %s VNI %u from %s", - zvrf_id (zvrf), inet_ntoa (vtep_ip), - vni, zebra_route_string (client->proto)); - - /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to locate VNI hash upon remote VTEP ADD, VRF %d VNI %u", - zvrf_id (zvrf), vni); - continue; - } - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon remote VTEP ADD", - zvni->vni, zvni); - continue; - } - - - /* If the remote VTEP already exists, or the local VxLAN interface is - * not up (should be a transient event), there's nothing more to do. - * Otherwise, add and install the entry. - */ - if (zvni_vtep_find (zvni, &vtep_ip)) - continue; - - if (!if_is_operative (zvni->vxlan_if)) - continue; - - if (zvni_vtep_add (zvni, &vtep_ip) == NULL) - { - zlog_err ("Failed to add remote VTEP, VRF %d VNI %u zvni %p", - zvrf_id (zvrf), vni, zvni); - continue; - } - - zvni_vtep_install (zvni, &vtep_ip); - } - - return 0; +int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) +{ + struct stream *s; + u_short l = 0; + vni_t vni; + struct in_addr vtep_ip; + zebra_vni_t *zvni; + + assert(EVPN_ENABLED(zvrf)); + + s = client->ibuf; + + while (l < length) { + /* Obtain each remote VTEP and process. */ + vni = (vni_t)stream_getl(s); + l += 4; + vtep_ip.s_addr = stream_get_ipv4(s); + l += IPV4_MAX_BYTELEN; + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Recv VTEP_ADD %s VNI %u from %s", + zvrf_id(zvrf), inet_ntoa(vtep_ip), vni, + zebra_route_string(client->proto)); + + /* Locate VNI hash entry - expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to locate VNI hash upon remote VTEP ADD, VRF %d VNI %u", + zvrf_id(zvrf), vni); + continue; + } + if (!zvni->vxlan_if) { + zlog_err( + "VNI %u hash %p doesn't have intf upon remote VTEP ADD", + zvni->vni, zvni); + continue; + } + + + /* If the remote VTEP already exists, or the local VxLAN + * interface is + * not up (should be a transient event), there's nothing more + * to do. + * Otherwise, add and install the entry. + */ + if (zvni_vtep_find(zvni, &vtep_ip)) + continue; + + if (!if_is_operative(zvni->vxlan_if)) + continue; + + if (zvni_vtep_add(zvni, &vtep_ip) == NULL) { + zlog_err( + "Failed to add remote VTEP, VRF %d VNI %u zvni %p", + zvrf_id(zvrf), vni, zvni); + continue; + } + + zvni_vtep_install(zvni, &vtep_ip); + } + + return 0; } /* * Handle SVI interface going down. At this point, this is a NOP since * the kernel deletes the neighbor entries on this SVI (if any). */ -int -zebra_vxlan_svi_down (struct interface *ifp, struct interface *link_if) +int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if) { - return 0; + return 0; } /* @@ -2958,358 +2788,348 @@ zebra_vxlan_svi_down (struct interface *ifp, struct interface *link_if) * but if this is a SVI on a VxLAN bridge, we need to install any remote * neighbor entries (which will be used for EVPN ARP suppression). */ -int -zebra_vxlan_svi_up (struct interface *ifp, struct interface *link_if) +int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if) { - zebra_vni_t *zvni; - struct neigh_walk_ctx n_wctx; + zebra_vni_t *zvni; + struct neigh_walk_ctx n_wctx; - zvni = zvni_map_svi (ifp, link_if); - if (!zvni) - return 0; + zvni = zvni_map_svi(ifp, link_if); + if (!zvni) + return 0; - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon SVI up", - zvni->vni, zvni); - return -1; - } + if (!zvni->vxlan_if) { + zlog_err("VNI %u hash %p doesn't have intf upon SVI up", + zvni->vni, zvni); + return -1; + } - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:SVI %s(%u) VNI %u is UP, installing neighbors", - ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:SVI %s(%u) VNI %u is UP, installing neighbors", + ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni); - /* Install any remote neighbors for this VNI. */ - memset (&n_wctx, 0, sizeof (struct neigh_walk_ctx)); - n_wctx.zvni = zvni; - hash_iterate(zvni->neigh_table, zvni_install_neigh_hash, &n_wctx); + /* Install any remote neighbors for this VNI. */ + memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx)); + n_wctx.zvni = zvni; + hash_iterate(zvni->neigh_table, zvni_install_neigh_hash, &n_wctx); - return 0; + return 0; } /* * Handle VxLAN interface down - update BGP if required, and do * internal cleanup. */ -int -zebra_vxlan_if_down (struct interface *ifp) +int zebra_vxlan_if_down(struct interface *ifp) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - zebra_vni_t *zvni; - struct zebra_l2info_vxlan *vxl; - vni_t vni; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + zebra_vni_t *zvni; + struct zebra_l2info_vxlan *vxl; + vni_t vni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* If EVPN is not enabled, nothing further to be done. */ - if (!EVPN_ENABLED(zvrf)) - return 0; + /* If EVPN is not enabled, nothing further to be done. */ + if (!EVPN_ENABLED(zvrf)) + return 0; - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Intf %s(%u) VNI %u is DOWN", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Intf %s(%u) VNI %u is DOWN", ifp->vrf_id, + ifp->name, ifp->ifindex, vni); - /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to locate VNI hash at DOWN, VRF %d IF %s(%u) VNI %u", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); - return -1; - } + /* Locate hash entry; it is expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to locate VNI hash at DOWN, VRF %d IF %s(%u) VNI %u", + ifp->vrf_id, ifp->name, ifp->ifindex, vni); + return -1; + } - assert (zvni->vxlan_if == ifp); + assert(zvni->vxlan_if == ifp); - /* Delete this VNI from BGP. */ - zvni_send_del_to_client (zvrf, zvni->vni); + /* Delete this VNI from BGP. */ + zvni_send_del_to_client(zvrf, zvni->vni); - /* Free up all neighbors and MACs, if any. */ - zvni_neigh_del_all (zvrf, zvni, 1, 0, DEL_ALL_NEIGH); - zvni_mac_del_all (zvrf, zvni, 1, 0, DEL_ALL_MAC); + /* Free up all neighbors and MACs, if any. */ + zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH); + zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC); - /* Free up all remote VTEPs, if any. */ - zvni_vtep_del_all (zvni, 1); + /* Free up all remote VTEPs, if any. */ + zvni_vtep_del_all(zvni, 1); - return 0; + return 0; } /* * Handle VxLAN interface up - update BGP if required. */ -int -zebra_vxlan_if_up (struct interface *ifp) +int zebra_vxlan_if_up(struct interface *ifp) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - zebra_vni_t *zvni; - struct zebra_l2info_vxlan *vxl; - vni_t vni; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + zebra_vni_t *zvni; + struct zebra_l2info_vxlan *vxl; + vni_t vni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* If EVPN is not enabled, nothing further to be done. */ - if (!EVPN_ENABLED(zvrf)) - return 0; + /* If EVPN is not enabled, nothing further to be done. */ + if (!EVPN_ENABLED(zvrf)) + return 0; - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Intf %s(%u) VNI %u is UP", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Intf %s(%u) VNI %u is UP", ifp->vrf_id, + ifp->name, ifp->ifindex, vni); - /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to locate VNI hash at UP, VRF %d IF %s(%u) VNI %u", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); - return -1; - } + /* Locate hash entry; it is expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to locate VNI hash at UP, VRF %d IF %s(%u) VNI %u", + ifp->vrf_id, ifp->name, ifp->ifindex, vni); + return -1; + } - assert (zvni->vxlan_if == ifp); + assert(zvni->vxlan_if == ifp); - /* If part of a bridge, inform BGP about this VNI. */ - /* Also, read and populate local MACs and neighbors. */ - if (zif->brslave_info.br_if) - { - zvni_send_add_to_client (zvrf, zvni); - zvni_read_mac_neigh (zvrf, zvni, ifp); - } + /* If part of a bridge, inform BGP about this VNI. */ + /* Also, read and populate local MACs and neighbors. */ + if (zif->brslave_info.br_if) { + zvni_send_add_to_client(zvrf, zvni); + zvni_read_mac_neigh(zvrf, zvni, ifp); + } - return 0; + return 0; } /* * Handle VxLAN interface delete. Locate and remove entry in hash table * and update BGP, if required. */ -int -zebra_vxlan_if_del (struct interface *ifp) +int zebra_vxlan_if_del(struct interface *ifp) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - zebra_vni_t *zvni; - struct zebra_l2info_vxlan *vxl; - vni_t vni; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + zebra_vni_t *zvni; + struct zebra_l2info_vxlan *vxl; + vni_t vni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* If EVPN is not enabled, nothing further to be done. */ - if (!EVPN_ENABLED(zvrf)) - return 0; + /* If EVPN is not enabled, nothing further to be done. */ + if (!EVPN_ENABLED(zvrf)) + return 0; - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Del VNI %u intf %s(%u)", - ifp->vrf_id, vni, ifp->name, ifp->ifindex); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Del VNI %u intf %s(%u)", ifp->vrf_id, vni, + ifp->name, ifp->ifindex); - /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to locate VNI hash at del, VRF %d IF %s(%u) VNI %u", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); - return 0; - } + /* Locate hash entry; it is expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to locate VNI hash at del, VRF %d IF %s(%u) VNI %u", + ifp->vrf_id, ifp->name, ifp->ifindex, vni); + return 0; + } - /* Delete VNI from BGP. */ - zvni_send_del_to_client (zvrf, zvni->vni); + /* Delete VNI from BGP. */ + zvni_send_del_to_client(zvrf, zvni->vni); - /* Free up all neighbors and MAC, if any. */ - zvni_neigh_del_all (zvrf, zvni, 0, 0, DEL_ALL_NEIGH); - zvni_mac_del_all (zvrf, zvni, 0, 0, DEL_ALL_MAC); + /* Free up all neighbors and MAC, if any. */ + zvni_neigh_del_all(zvrf, zvni, 0, 0, DEL_ALL_NEIGH); + zvni_mac_del_all(zvrf, zvni, 0, 0, DEL_ALL_MAC); - /* Free up all remote VTEPs, if any. */ - zvni_vtep_del_all (zvni, 0); + /* Free up all remote VTEPs, if any. */ + zvni_vtep_del_all(zvni, 0); - /* Delete the hash entry. */ - if (zvni_del (zvrf, zvni)) - { - zlog_err ("Failed to del VNI hash %p, VRF %d IF %s(%u) VNI %u", - zvni, ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni); - return -1; - } + /* Delete the hash entry. */ + if (zvni_del(zvrf, zvni)) { + zlog_err("Failed to del VNI hash %p, VRF %d IF %s(%u) VNI %u", + zvni, ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni); + return -1; + } - return 0; + return 0; } /* * Handle VxLAN interface update - change to tunnel IP, master or VLAN. */ -int -zebra_vxlan_if_update (struct interface *ifp, u_int16_t chgflags) -{ - struct zebra_if *zif; - struct zebra_vrf *zvrf; - zebra_vni_t *zvni; - struct zebra_l2info_vxlan *vxl; - vni_t vni; - - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); - - /* If EVPN is not enabled, nothing further to be done. */ - if (!EVPN_ENABLED(zvrf)) - return 0; - - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; - - /* Update VNI hash. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to find VNI hash on update, VRF %d IF %s(%u) VNI %u", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); - return -1; - } - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Update VNI %u intf %s(%u) VLAN %u local IP %s " - "master %u chg 0x%x", - ifp->vrf_id, vni, ifp->name, ifp->ifindex, - vxl->access_vlan, inet_ntoa (vxl->vtep_ip), - zif->brslave_info.bridge_ifindex, chgflags); - - /* Removed from bridge? */ - if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE) && - (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) - { - /* Delete from client, remove all remote VTEPs */ - /* Also, free up all MACs and neighbors. */ - zvni_send_del_to_client (zvrf, zvni->vni); - zvni_neigh_del_all (zvrf, zvni, 1, 0, DEL_ALL_NEIGH); - zvni_mac_del_all (zvrf, zvni, 1, 0, DEL_ALL_MAC); - zvni_vtep_del_all (zvni, 1); - } - else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) - { - /* Remove all existing local neighbors and MACs for this VNI - * (including from BGP) - */ - zvni_neigh_del_all (zvrf, zvni, 0, 1, DEL_LOCAL_MAC); - zvni_mac_del_all (zvrf, zvni, 0, 1, DEL_LOCAL_MAC); - } - - zvni->local_vtep_ip = vxl->vtep_ip; - zvni->vxlan_if = ifp; - - /* Take further actions needed. Note that if we are here, there is a - * change of interest. - */ - /* If down or not mapped to a bridge, we're done. */ - if (!if_is_operative (ifp) || !zif->brslave_info.br_if) - return 0; - - /* Inform BGP, if there is a change of interest. */ - if (chgflags & (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE)) - zvni_send_add_to_client (zvrf, zvni); - - /* If there is a valid new master or a VLAN mapping change, read and - * populate local MACs and neighbors. Also, reinstall any remote MACs - * and neighbors for this VNI (based on new VLAN). - */ - if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) - zvni_read_mac_neigh (zvrf, zvni, ifp); - else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) - { - struct mac_walk_ctx m_wctx; - struct neigh_walk_ctx n_wctx; - - zvni_read_mac_neigh (zvrf, zvni, ifp); - - memset (&m_wctx, 0, sizeof (struct mac_walk_ctx)); - m_wctx.zvni = zvni; - hash_iterate(zvni->mac_table, zvni_install_mac_hash, &m_wctx); - - memset (&n_wctx, 0, sizeof (struct neigh_walk_ctx)); - n_wctx.zvni = zvni; - hash_iterate(zvni->neigh_table, zvni_install_neigh_hash, &n_wctx); - } - - return 0; +int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags) +{ + struct zebra_if *zif; + struct zebra_vrf *zvrf; + zebra_vni_t *zvni; + struct zebra_l2info_vxlan *vxl; + vni_t vni; + + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); + + /* If EVPN is not enabled, nothing further to be done. */ + if (!EVPN_ENABLED(zvrf)) + return 0; + + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; + + /* Update VNI hash. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to find VNI hash on update, VRF %d IF %s(%u) VNI %u", + ifp->vrf_id, ifp->name, ifp->ifindex, vni); + return -1; + } + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Update VNI %u intf %s(%u) VLAN %u local IP %s " + "master %u chg 0x%x", + ifp->vrf_id, vni, ifp->name, ifp->ifindex, + vxl->access_vlan, inet_ntoa(vxl->vtep_ip), + zif->brslave_info.bridge_ifindex, chgflags); + + /* Removed from bridge? */ + if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE) + && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) { + /* Delete from client, remove all remote VTEPs */ + /* Also, free up all MACs and neighbors. */ + zvni_send_del_to_client(zvrf, zvni->vni); + zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH); + zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC); + zvni_vtep_del_all(zvni, 1); + } else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) { + /* Remove all existing local neighbors and MACs for this VNI + * (including from BGP) + */ + zvni_neigh_del_all(zvrf, zvni, 0, 1, DEL_LOCAL_MAC); + zvni_mac_del_all(zvrf, zvni, 0, 1, DEL_LOCAL_MAC); + } + + zvni->local_vtep_ip = vxl->vtep_ip; + zvni->vxlan_if = ifp; + + /* Take further actions needed. Note that if we are here, there is a + * change of interest. + */ + /* If down or not mapped to a bridge, we're done. */ + if (!if_is_operative(ifp) || !zif->brslave_info.br_if) + return 0; + + /* Inform BGP, if there is a change of interest. */ + if (chgflags + & (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE)) + zvni_send_add_to_client(zvrf, zvni); + + /* If there is a valid new master or a VLAN mapping change, read and + * populate local MACs and neighbors. Also, reinstall any remote MACs + * and neighbors for this VNI (based on new VLAN). + */ + if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) + zvni_read_mac_neigh(zvrf, zvni, ifp); + else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) { + struct mac_walk_ctx m_wctx; + struct neigh_walk_ctx n_wctx; + + zvni_read_mac_neigh(zvrf, zvni, ifp); + + memset(&m_wctx, 0, sizeof(struct mac_walk_ctx)); + m_wctx.zvni = zvni; + hash_iterate(zvni->mac_table, zvni_install_mac_hash, &m_wctx); + + memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx)); + n_wctx.zvni = zvni; + hash_iterate(zvni->neigh_table, zvni_install_neigh_hash, + &n_wctx); + } + + return 0; } /* * Handle VxLAN interface add. */ -int -zebra_vxlan_if_add (struct interface *ifp) +int zebra_vxlan_if_add(struct interface *ifp) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - zebra_vni_t *zvni; - struct zebra_l2info_vxlan *vxl; - vni_t vni; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + zebra_vni_t *zvni; + struct zebra_l2info_vxlan *vxl; + vni_t vni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* If EVPN is not enabled, nothing further to be done. */ - if (!EVPN_ENABLED(zvrf)) - return 0; + /* If EVPN is not enabled, nothing further to be done. */ + if (!EVPN_ENABLED(zvrf)) + return 0; - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Add VNI %u intf %s(%u) VLAN %u local IP %s master %u", - ifp->vrf_id, vni, ifp->name, ifp->ifindex, - vxl->access_vlan, inet_ntoa (vxl->vtep_ip), - zif->brslave_info.bridge_ifindex); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Add VNI %u intf %s(%u) VLAN %u local IP %s master %u", + ifp->vrf_id, vni, ifp->name, ifp->ifindex, + vxl->access_vlan, inet_ntoa(vxl->vtep_ip), + zif->brslave_info.bridge_ifindex); - /* Create or update VNI hash. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zvni = zvni_add (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to add VNI hash, VRF %d IF %s(%u) VNI %u", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); - return -1; - } - } + /* Create or update VNI hash. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zvni = zvni_add(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to add VNI hash, VRF %d IF %s(%u) VNI %u", + ifp->vrf_id, ifp->name, ifp->ifindex, vni); + return -1; + } + } - zvni->local_vtep_ip = vxl->vtep_ip; - zvni->vxlan_if = ifp; + zvni->local_vtep_ip = vxl->vtep_ip; + zvni->vxlan_if = ifp; - /* If down or not mapped to a bridge, we're done. */ - if (!if_is_operative (ifp) || !zif->brslave_info.br_if) - return 0; + /* If down or not mapped to a bridge, we're done. */ + if (!if_is_operative(ifp) || !zif->brslave_info.br_if) + return 0; - /* Inform BGP */ - zvni_send_add_to_client (zvrf, zvni); + /* Inform BGP */ + zvni_send_add_to_client(zvrf, zvni); - /* Read and populate local MACs and neighbors */ - zvni_read_mac_neigh (zvrf, zvni, ifp); + /* Read and populate local MACs and neighbors */ + zvni_read_mac_neigh(zvrf, zvni, ifp); - return 0; + return 0; } /* @@ -3318,63 +3138,57 @@ zebra_vxlan_if_add (struct interface *ifp) * when disabled, the entries should be deleted and remote VTEPs and MACs * uninstalled from the kernel. */ -int zebra_vxlan_advertise_all_vni (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf) { - struct stream *s; - int advertise; + struct stream *s; + int advertise; - s = client->ibuf; - advertise = stream_getc (s); + s = client->ibuf; + advertise = stream_getc(s); - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:EVPN VNI Adv %s, currently %s", - zvrf_id (zvrf), advertise ? "enabled" : "disabled", - EVPN_ENABLED(zvrf) ? "enabled" : "disabled"); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:EVPN VNI Adv %s, currently %s", zvrf_id(zvrf), + advertise ? "enabled" : "disabled", + EVPN_ENABLED(zvrf) ? "enabled" : "disabled"); - if (zvrf->advertise_all_vni == advertise) - return 0; + if (zvrf->advertise_all_vni == advertise) + return 0; - zvrf->advertise_all_vni = advertise; - if (EVPN_ENABLED(zvrf)) - { - /* Build VNI hash table and inform BGP. */ - zvni_build_hash_table (zvrf); + zvrf->advertise_all_vni = advertise; + if (EVPN_ENABLED(zvrf)) { + /* Build VNI hash table and inform BGP. */ + zvni_build_hash_table(zvrf); - /* Read the MAC FDB */ - macfdb_read (zvrf->zns); + /* Read the MAC FDB */ + macfdb_read(zvrf->zns); - /* Read neighbors */ - neigh_read (zvrf->zns); - } - else - { - /* Cleanup VTEPs for all VNIs - uninstall from - * kernel and free entries. - */ - hash_iterate (zvrf->vni_table, zvni_cleanup_all, zvrf); - } + /* Read neighbors */ + neigh_read(zvrf->zns); + } else { + /* Cleanup VTEPs for all VNIs - uninstall from + * kernel and free entries. + */ + hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf); + } - return 0; + return 0; } /* * Allocate VNI hash table for this VRF and do other initialization. * NOTE: Currently supported only for default VRF. */ -void -zebra_vxlan_init_tables (struct zebra_vrf *zvrf) +void zebra_vxlan_init_tables(struct zebra_vrf *zvrf) { - if (!zvrf) - return; - zvrf->vni_table = hash_create(vni_hash_keymake, - vni_hash_cmp, - "Zebra VRF VNI Table"); + if (!zvrf) + return; + zvrf->vni_table = hash_create(vni_hash_keymake, vni_hash_cmp, + "Zebra VRF VNI Table"); } /* Close all VNI handling */ -void -zebra_vxlan_close_tables (struct zebra_vrf *zvrf) +void zebra_vxlan_close_tables(struct zebra_vrf *zvrf) { - hash_iterate (zvrf->vni_table, zvni_cleanup_all, zvrf); + hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf); } diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index e5f0bd2f6..f9ecd8333 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -41,68 +41,73 @@ #define ZEBRA_VXLIF_MASTER_CHANGE 0x2 #define ZEBRA_VXLIF_VLAN_CHANGE 0x4 -extern void zebra_vxlan_print_macs_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni); -extern void zebra_vxlan_print_macs_all_vni (struct vty *vty, - struct zebra_vrf *zvrf); -extern void zebra_vxlan_print_macs_all_vni_vtep (struct vty *vty, - struct zebra_vrf *zvrf, - struct in_addr vtep_ip); -extern void zebra_vxlan_print_specific_mac_vni (struct vty *vty, - struct zebra_vrf *zvrf, vni_t vni, struct ethaddr *mac); -extern void zebra_vxlan_print_macs_vni_vtep (struct vty *vty, - struct zebra_vrf *zvrf, vni_t vni, struct in_addr vtep_ip); -extern void zebra_vxlan_print_neigh_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni); -extern void zebra_vxlan_print_neigh_all_vni (struct vty *vty, - struct zebra_vrf *zvrf); -extern void zebra_vxlan_print_specific_neigh_vni (struct vty *vty, - struct zebra_vrf *zvrf, vni_t vni, struct ipaddr *ip); -extern void zebra_vxlan_print_neigh_vni_vtep (struct vty *vty, - struct zebra_vrf *zvrf, vni_t vni, struct in_addr vtep_ip); -extern void zebra_vxlan_print_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni); -extern void zebra_vxlan_print_vnis (struct vty *vty, struct zebra_vrf *zvrf); +extern void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni); +extern void zebra_vxlan_print_macs_all_vni(struct vty *vty, + struct zebra_vrf *zvrf); +extern void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, + struct zebra_vrf *zvrf, + struct in_addr vtep_ip); +extern void zebra_vxlan_print_specific_mac_vni(struct vty *vty, + struct zebra_vrf *zvrf, + vni_t vni, struct ethaddr *mac); +extern void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, + struct zebra_vrf *zvrf, vni_t vni, + struct in_addr vtep_ip); +extern void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni); +extern void zebra_vxlan_print_neigh_all_vni(struct vty *vty, + struct zebra_vrf *zvrf); +extern void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, + struct zebra_vrf *zvrf, + vni_t vni, struct ipaddr *ip); +extern void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, + struct zebra_vrf *zvrf, vni_t vni, + struct in_addr vtep_ip); +extern void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni); +extern void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf); -extern int zebra_vxlan_svi_up (struct interface *ifp, struct interface *link_if); -extern int zebra_vxlan_svi_down (struct interface *ifp, struct interface *link_if); -extern int zebra_vxlan_local_neigh_add_update (struct interface *ifp, - struct interface *link_if, - struct ipaddr *ip, - struct ethaddr *macaddr, - u_int16_t state, - u_char ext_learned); -extern int zebra_vxlan_local_neigh_del (struct interface *ifp, - struct interface *link_if, - struct ipaddr *ip); -extern int zebra_vxlan_remote_macip_add (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf); -extern int zebra_vxlan_remote_macip_del (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf); -extern int zebra_vxlan_local_mac_add_update (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid, - u_char sticky); -extern int zebra_vxlan_local_mac_del (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid); -extern int zebra_vxlan_check_readd_remote_mac (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid); -extern int zebra_vxlan_check_del_local_mac (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid); -extern int zebra_vxlan_if_up (struct interface *ifp); -extern int zebra_vxlan_if_down (struct interface *ifp); -extern int zebra_vxlan_if_add (struct interface *ifp); -extern int zebra_vxlan_if_update (struct interface *ifp, u_int16_t chgflags); -extern int zebra_vxlan_if_del (struct interface *ifp); -extern int zebra_vxlan_remote_vtep_add (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf); -extern int zebra_vxlan_remote_vtep_del (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf); -extern int zebra_vxlan_advertise_all_vni (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf); -extern void zebra_vxlan_init_tables (struct zebra_vrf *zvrf); -extern void zebra_vxlan_close_tables (struct zebra_vrf *); +extern int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if); +extern int zebra_vxlan_svi_down(struct interface *ifp, + struct interface *link_if); +extern int zebra_vxlan_local_neigh_add_update( + struct interface *ifp, struct interface *link_if, struct ipaddr *ip, + struct ethaddr *macaddr, u_int16_t state, u_char ext_learned); +extern int zebra_vxlan_local_neigh_del(struct interface *ifp, + struct interface *link_if, + struct ipaddr *ip); +extern int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf); +extern int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf); +extern int zebra_vxlan_local_mac_add_update(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid, + u_char sticky); +extern int zebra_vxlan_local_mac_del(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid); +extern int zebra_vxlan_check_readd_remote_mac(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, + vlanid_t vid); +extern int zebra_vxlan_check_del_local_mac(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid); +extern int zebra_vxlan_if_up(struct interface *ifp); +extern int zebra_vxlan_if_down(struct interface *ifp); +extern int zebra_vxlan_if_add(struct interface *ifp); +extern int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags); +extern int zebra_vxlan_if_del(struct interface *ifp); +extern int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf); +extern int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf); +extern int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock, + u_short length, + struct zebra_vrf *zvrf); +extern void zebra_vxlan_init_tables(struct zebra_vrf *zvrf); +extern void zebra_vxlan_close_tables(struct zebra_vrf *); #endif /* _ZEBRA_VXLAN_H */ diff --git a/zebra/zebra_vxlan_null.c b/zebra/zebra_vxlan_null.c index b0f09930b..bbed5ddb0 100644 --- a/zebra/zebra_vxlan_null.c +++ b/zebra/zebra_vxlan_null.c @@ -30,168 +30,156 @@ #include "zebra/zebra_l2.h" #include "zebra/zebra_vxlan.h" -void -zebra_vxlan_print_macs_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) +void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni) { } -void zebra_vxlan_print_macs_all_vni (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf) { } -void zebra_vxlan_print_macs_all_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf, struct in_addr vtep_ip) +void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, + struct zebra_vrf *zvrf, + struct in_addr vtep_ip) { } -void -zebra_vxlan_print_specific_mac_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct ethaddr *mac) +void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni, struct ethaddr *mac) { } -void -zebra_vxlan_print_macs_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct in_addr vtep_ip) +void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni, struct in_addr vtep_ip) { } -void -zebra_vxlan_print_neigh_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni) +void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni) { } -void -zebra_vxlan_print_neigh_all_vni (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf) { } -void -zebra_vxlan_print_specific_neigh_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct ipaddr *ip) +void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, + struct zebra_vrf *zvrf, vni_t vni, + struct ipaddr *ip) { } -void zebra_vxlan_print_neigh_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct in_addr vtep_ip) +void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni, struct in_addr vtep_ip) { } -void -zebra_vxlan_print_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) +void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) { } -void -zebra_vxlan_print_vnis (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf) { } -int zebra_vxlan_svi_up (struct interface *ifp, struct interface *link_if) +int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if) { - return 0; + return 0; } -int zebra_vxlan_svi_down (struct interface *ifp, struct interface *link_if) +int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if) { - return 0; + return 0; } -int zebra_vxlan_remote_macip_add (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { - return 0; + return 0; } -int zebra_vxlan_remote_macip_del (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { - return 0; + return 0; } -int zebra_vxlan_local_mac_add_update (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid, - u_char sticky) +int zebra_vxlan_local_mac_add_update(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid, + u_char sticky) { - return 0; + return 0; } -int zebra_vxlan_local_mac_del (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid) +int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, + struct ethaddr *mac, vlanid_t vid) { - return 0; + return 0; } -int zebra_vxlan_check_readd_remote_mac (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid) +int zebra_vxlan_check_readd_remote_mac(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid) { - return 0; + return 0; } -int zebra_vxlan_check_del_local_mac (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid) +int zebra_vxlan_check_del_local_mac(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid) { - return 0; + return 0; } -int -zebra_vxlan_if_up (struct interface *ifp) +int zebra_vxlan_if_up(struct interface *ifp) { - return 0; + return 0; } -int -zebra_vxlan_if_down (struct interface *ifp) +int zebra_vxlan_if_down(struct interface *ifp) { - return 0; + return 0; } -int -zebra_vxlan_if_add (struct interface *ifp) +int zebra_vxlan_if_add(struct interface *ifp) { - return 0; + return 0; } -int -zebra_vxlan_if_update (struct interface *ifp, u_int16_t chgflags) +int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags) { - return 0; + return 0; } -int -zebra_vxlan_if_del (struct interface *ifp) +int zebra_vxlan_if_del(struct interface *ifp) { - return 0; + return 0; } -int zebra_vxlan_remote_vtep_add (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { - return 0; + return 0; } -int zebra_vxlan_remote_vtep_del (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { - return 0; + return 0; } -int zebra_vxlan_advertise_all_vni (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf) { - return 0; + return 0; } -void -zebra_vxlan_init_tables (struct zebra_vrf *zvrf) +void zebra_vxlan_init_tables(struct zebra_vrf *zvrf) { } -void -zebra_vxlan_close_tables (struct zebra_vrf *zvrf) +void zebra_vxlan_close_tables(struct zebra_vrf *zvrf) { } diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h index 0de86c3bc..fbde72292 100644 --- a/zebra/zebra_vxlan_private.h +++ b/zebra/zebra_vxlan_private.h @@ -42,15 +42,14 @@ typedef struct zebra_neigh_t_ zebra_neigh_t; * * Right now, this just has each remote VTEP's IP address. */ -struct zebra_vtep_t_ -{ - /* Remote IP. */ - /* NOTE: Can only be IPv4 right now. */ - struct in_addr vtep_ip; - - /* Links. */ - struct zebra_vtep_t_ *next; - struct zebra_vtep_t_ *prev; +struct zebra_vtep_t_ { + /* Remote IP. */ + /* NOTE: Can only be IPv4 right now. */ + struct in_addr vtep_ip; + + /* Links. */ + struct zebra_vtep_t_ *next; + struct zebra_vtep_t_ *prev; }; @@ -60,25 +59,24 @@ struct zebra_vtep_t_ * Contains information pertaining to a VNI: * - the list of remote VTEPs (with this VNI) */ -struct zebra_vni_t_ -{ - /* VNI - key */ - vni_t vni; +struct zebra_vni_t_ { + /* VNI - key */ + vni_t vni; - /* Corresponding VxLAN interface. */ - struct interface *vxlan_if; + /* Corresponding VxLAN interface. */ + struct interface *vxlan_if; - /* List of remote VTEPs */ - zebra_vtep_t *vteps; + /* List of remote VTEPs */ + zebra_vtep_t *vteps; - /* Local IP */ - struct in_addr local_vtep_ip; + /* Local IP */ + struct in_addr local_vtep_ip; - /* List of local or remote MAC */ - struct hash *mac_table; + /* List of local or remote MAC */ + struct hash *mac_table; - /* List of local or remote neighbors (MAC+IP) */ - struct hash *neigh_table; + /* List of local or remote neighbors (MAC+IP) */ + struct hash *neigh_table; }; /* @@ -93,53 +91,49 @@ struct zebra_vni_t_ * information. The correct VNI will be obtained as zebra maintains * the mapping (of VLAN to VNI). */ -struct zebra_mac_t_ -{ - /* MAC address. */ - struct ethaddr macaddr; +struct zebra_mac_t_ { + /* MAC address. */ + struct ethaddr macaddr; - u_int32_t flags; + u_int32_t flags; #define ZEBRA_MAC_LOCAL 0x01 #define ZEBRA_MAC_REMOTE 0x02 #define ZEBRA_MAC_AUTO 0x04 /* Auto created for neighbor. */ #define ZEBRA_MAC_STICKY 0x08 /* Static MAC */ - /* Local or remote info. */ - union - { - struct - { - ifindex_t ifindex; - vlanid_t vid; - } local; + /* Local or remote info. */ + union { + struct { + ifindex_t ifindex; + vlanid_t vid; + } local; - struct in_addr r_vtep_ip; - } fwd_info; + struct in_addr r_vtep_ip; + } fwd_info; - u_int32_t neigh_refcnt; + u_int32_t neigh_refcnt; }; /* * Context for MAC hash walk - used by callbacks. */ -struct mac_walk_ctx -{ - zebra_vni_t *zvni; /* VNI hash */ - struct zebra_vrf *zvrf; /* VRF - for client notification. */ - int uninstall; /* uninstall from kernel? */ - int upd_client; /* uninstall from client? */ - - u_int32_t flags; +struct mac_walk_ctx { + zebra_vni_t *zvni; /* VNI hash */ + struct zebra_vrf *zvrf; /* VRF - for client notification. */ + int uninstall; /* uninstall from kernel? */ + int upd_client; /* uninstall from client? */ + + u_int32_t flags; #define DEL_LOCAL_MAC 0x1 #define DEL_REMOTE_MAC 0x2 #define DEL_ALL_MAC (DEL_LOCAL_MAC | DEL_REMOTE_MAC) #define DEL_REMOTE_MAC_FROM_VTEP 0x4 #define SHOW_REMOTE_MAC_FROM_VTEP 0x8 - struct in_addr r_vtep_ip; /* To walk MACs from specific VTEP */ + struct in_addr r_vtep_ip; /* To walk MACs from specific VTEP */ - struct vty *vty; /* Used by VTY handlers */ - u_int32_t count; /* Used by VTY handlers */ + struct vty *vty; /* Used by VTY handlers */ + u_int32_t count; /* Used by VTY handlers */ }; /* @@ -153,47 +147,45 @@ struct mac_walk_ctx * it is sufficient for zebra to maintain against the VNI. The correct * VNI will be obtained as zebra maintains the mapping (of VLAN to VNI). */ -struct zebra_neigh_t_ -{ - /* IP address. */ - struct ipaddr ip; +struct zebra_neigh_t_ { + /* IP address. */ + struct ipaddr ip; - /* MAC address. */ - struct ethaddr emac; + /* MAC address. */ + struct ethaddr emac; - /* Underlying interface. */ - ifindex_t ifindex; + /* Underlying interface. */ + ifindex_t ifindex; - u_int32_t flags; + u_int32_t flags; #define ZEBRA_NEIGH_LOCAL 0x01 #define ZEBRA_NEIGH_REMOTE 0x02 - /* Remote VTEP IP - applicable only for remote neighbors. */ - struct in_addr r_vtep_ip; + /* Remote VTEP IP - applicable only for remote neighbors. */ + struct in_addr r_vtep_ip; }; /* * Context for neighbor hash walk - used by callbacks. */ -struct neigh_walk_ctx -{ - zebra_vni_t *zvni; /* VNI hash */ - struct zebra_vrf *zvrf; /* VRF - for client notification. */ - int uninstall; /* uninstall from kernel? */ - int upd_client; /* uninstall from client? */ - - u_int32_t flags; +struct neigh_walk_ctx { + zebra_vni_t *zvni; /* VNI hash */ + struct zebra_vrf *zvrf; /* VRF - for client notification. */ + int uninstall; /* uninstall from kernel? */ + int upd_client; /* uninstall from client? */ + + u_int32_t flags; #define DEL_LOCAL_NEIGH 0x1 #define DEL_REMOTE_NEIGH 0x2 #define DEL_ALL_NEIGH (DEL_LOCAL_NEIGH | DEL_REMOTE_NEIGH) #define DEL_REMOTE_NEIGH_FROM_VTEP 0x4 #define SHOW_REMOTE_NEIGH_FROM_VTEP 0x8 - struct in_addr r_vtep_ip; /* To walk neighbors from specific VTEP */ + struct in_addr r_vtep_ip; /* To walk neighbors from specific VTEP */ - struct vty *vty; /* Used by VTY handlers */ - u_int32_t count; /* Used by VTY handlers */ - u_char addr_width; /* Used by VTY handlers */ + struct vty *vty; /* Used by VTY handlers */ + u_int32_t count; /* Used by VTY handlers */ + u_char addr_width; /* Used by VTY handlers */ }; #endif /* _ZEBRA_VXLAN_PRIVATE_H */ diff --git a/zebra/zserv.c b/zebra/zserv.c index 15feb78c0..3bc5f83f6 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -59,150 +59,145 @@ /* Event list of zebra. */ enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE }; -static void zebra_event (enum event event, int sock, struct zserv *client); +static void zebra_event(enum event event, int sock, struct zserv *client); extern struct zebra_privs_t zserv_privs; -static void zebra_client_close (struct zserv *client); - -static int -zserv_delayed_close(struct thread *thread) -{ - struct zserv *client = THREAD_ARG(thread); - - client->t_suicide = NULL; - zebra_client_close(client); - return 0; -} - -static int -zserv_flush_data(struct thread *thread) -{ - struct zserv *client = THREAD_ARG(thread); - - client->t_write = NULL; - if (client->t_suicide) - { - zebra_client_close(client); - return -1; - } - switch (buffer_flush_available(client->wb, client->sock)) - { - case BUFFER_ERROR: - zlog_warn("%s: buffer_flush_available failed on zserv client fd %d, " - "closing", __func__, client->sock); - zebra_client_close(client); - client = NULL; - break; - case BUFFER_PENDING: - client->t_write = NULL; - thread_add_write(zebrad.master, zserv_flush_data, client, client->sock, - &client->t_write); - break; - case BUFFER_EMPTY: - break; - } - - if (client) - client->last_write_time = monotime(NULL); - return 0; -} - -int -zebra_server_send_message(struct zserv *client) -{ - if (client->t_suicide) - return -1; - - if (client->is_synchronous) - return 0; - - stream_set_getp(client->obuf, 0); - client->last_write_cmd = stream_getw_from(client->obuf, 6); - switch (buffer_write(client->wb, client->sock, STREAM_DATA(client->obuf), - stream_get_endp(client->obuf))) - { - case BUFFER_ERROR: - zlog_warn("%s: buffer_write failed to zserv client fd %d, closing", - __func__, client->sock); - /* Schedule a delayed close since many of the functions that call this - one do not check the return code. They do not allow for the - possibility that an I/O error may have caused the client to be - deleted. */ - client->t_suicide = NULL; - thread_add_event(zebrad.master, zserv_delayed_close, client, 0, - &client->t_suicide); - return -1; - case BUFFER_EMPTY: - THREAD_OFF(client->t_write); - break; - case BUFFER_PENDING: - thread_add_write(zebrad.master, zserv_flush_data, client, client->sock, - &client->t_write); - break; - } - - client->last_write_time = monotime(NULL); - return 0; -} - -void -zserv_create_header (struct stream *s, uint16_t cmd, vrf_id_t vrf_id) -{ - /* length placeholder, caller can update */ - stream_putw (s, ZEBRA_HEADER_SIZE); - stream_putc (s, ZEBRA_HEADER_MARKER); - stream_putc (s, ZSERV_VERSION); - stream_putw (s, vrf_id); - stream_putw (s, cmd); -} - -static void -zserv_encode_interface (struct stream *s, struct interface *ifp) -{ - /* Interface information. */ - stream_put (s, ifp->name, INTERFACE_NAMSIZ); - stream_putl (s, ifp->ifindex); - stream_putc (s, ifp->status); - stream_putq (s, ifp->flags); - stream_putc (s, ifp->ptm_enable); - stream_putc (s, ifp->ptm_status); - stream_putl (s, ifp->metric); - stream_putl (s, ifp->speed); - stream_putl (s, ifp->mtu); - stream_putl (s, ifp->mtu6); - stream_putl (s, ifp->bandwidth); - stream_putl (s, ifp->ll_type); - stream_putl (s, ifp->hw_addr_len); - if (ifp->hw_addr_len) - stream_put (s, ifp->hw_addr, ifp->hw_addr_len); - - /* Then, Traffic Engineering parameters if any */ - if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params)) - { - stream_putc (s, 1); - zebra_interface_link_params_write (s, ifp); - } - else - stream_putc (s, 0); - - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); -} - -static void -zserv_encode_vrf (struct stream *s, struct zebra_vrf *zvrf) -{ - struct vrf_data data; - - data.l.table_id = zvrf->table_id; - /* Pass the tableid */ - stream_put (s, &data, sizeof (struct vrf_data)); - /* Interface information. */ - stream_put (s, zvrf_name (zvrf), VRF_NAMSIZ); - - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); +static void zebra_client_close(struct zserv *client); + +static int zserv_delayed_close(struct thread *thread) +{ + struct zserv *client = THREAD_ARG(thread); + + client->t_suicide = NULL; + zebra_client_close(client); + return 0; +} + +static int zserv_flush_data(struct thread *thread) +{ + struct zserv *client = THREAD_ARG(thread); + + client->t_write = NULL; + if (client->t_suicide) { + zebra_client_close(client); + return -1; + } + switch (buffer_flush_available(client->wb, client->sock)) { + case BUFFER_ERROR: + zlog_warn( + "%s: buffer_flush_available failed on zserv client fd %d, " + "closing", + __func__, client->sock); + zebra_client_close(client); + client = NULL; + break; + case BUFFER_PENDING: + client->t_write = NULL; + thread_add_write(zebrad.master, zserv_flush_data, client, + client->sock, &client->t_write); + break; + case BUFFER_EMPTY: + break; + } + + if (client) + client->last_write_time = monotime(NULL); + return 0; +} + +int zebra_server_send_message(struct zserv *client) +{ + if (client->t_suicide) + return -1; + + if (client->is_synchronous) + return 0; + + stream_set_getp(client->obuf, 0); + client->last_write_cmd = stream_getw_from(client->obuf, 6); + switch (buffer_write(client->wb, client->sock, + STREAM_DATA(client->obuf), + stream_get_endp(client->obuf))) { + case BUFFER_ERROR: + zlog_warn( + "%s: buffer_write failed to zserv client fd %d, closing", + __func__, client->sock); + /* Schedule a delayed close since many of the functions that + call this + one do not check the return code. They do not allow for the + possibility that an I/O error may have caused the client to + be + deleted. */ + client->t_suicide = NULL; + thread_add_event(zebrad.master, zserv_delayed_close, client, 0, + &client->t_suicide); + return -1; + case BUFFER_EMPTY: + THREAD_OFF(client->t_write); + break; + case BUFFER_PENDING: + thread_add_write(zebrad.master, zserv_flush_data, client, + client->sock, &client->t_write); + break; + } + + client->last_write_time = monotime(NULL); + return 0; +} + +void zserv_create_header(struct stream *s, uint16_t cmd, vrf_id_t vrf_id) +{ + /* length placeholder, caller can update */ + stream_putw(s, ZEBRA_HEADER_SIZE); + stream_putc(s, ZEBRA_HEADER_MARKER); + stream_putc(s, ZSERV_VERSION); + stream_putw(s, vrf_id); + stream_putw(s, cmd); +} + +static void zserv_encode_interface(struct stream *s, struct interface *ifp) +{ + /* Interface information. */ + stream_put(s, ifp->name, INTERFACE_NAMSIZ); + stream_putl(s, ifp->ifindex); + stream_putc(s, ifp->status); + stream_putq(s, ifp->flags); + stream_putc(s, ifp->ptm_enable); + stream_putc(s, ifp->ptm_status); + stream_putl(s, ifp->metric); + stream_putl(s, ifp->speed); + stream_putl(s, ifp->mtu); + stream_putl(s, ifp->mtu6); + stream_putl(s, ifp->bandwidth); + stream_putl(s, ifp->ll_type); + stream_putl(s, ifp->hw_addr_len); + if (ifp->hw_addr_len) + stream_put(s, ifp->hw_addr, ifp->hw_addr_len); + + /* Then, Traffic Engineering parameters if any */ + if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params)) { + stream_putc(s, 1); + zebra_interface_link_params_write(s, ifp); + } else + stream_putc(s, 0); + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); +} + +static void zserv_encode_vrf(struct stream *s, struct zebra_vrf *zvrf) +{ + struct vrf_data data; + + data.l.table_id = zvrf->table_id; + /* Pass the tableid */ + stream_put(s, &data, sizeof(struct vrf_data)); + /* Interface information. */ + stream_put(s, zvrf_name(zvrf), VRF_NAMSIZ); + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); } /* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */ @@ -216,99 +211,94 @@ zserv_encode_vrf (struct stream *s, struct zebra_vrf *zvrf) * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is * received) */ -int -zsend_interface_add (struct zserv *client, struct interface *ifp) +int zsend_interface_add(struct zserv *client, struct interface *ifp) { - struct stream *s; + struct stream *s; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_INTERFACE_ADD, ifp->vrf_id); - zserv_encode_interface (s, ifp); + zserv_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf_id); + zserv_encode_interface(s, ifp); - client->ifadd_cnt++; - return zebra_server_send_message(client); + client->ifadd_cnt++; + return zebra_server_send_message(client); } /* Interface deletion from zebra daemon. */ -int -zsend_interface_delete (struct zserv *client, struct interface *ifp) +int zsend_interface_delete(struct zserv *client, struct interface *ifp) { - struct stream *s; + struct stream *s; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id); - zserv_encode_interface (s, ifp); + zserv_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id); + zserv_encode_interface(s, ifp); - client->ifdel_cnt++; - return zebra_server_send_message (client); + client->ifdel_cnt++; + return zebra_server_send_message(client); } -int -zsend_vrf_add (struct zserv *client, struct zebra_vrf *zvrf) +int zsend_vrf_add(struct zserv *client, struct zebra_vrf *zvrf) { - struct stream *s; + struct stream *s; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_VRF_ADD, zvrf_id (zvrf)); - zserv_encode_vrf (s, zvrf); + zserv_create_header(s, ZEBRA_VRF_ADD, zvrf_id(zvrf)); + zserv_encode_vrf(s, zvrf); - client->vrfadd_cnt++; - return zebra_server_send_message(client); + client->vrfadd_cnt++; + return zebra_server_send_message(client); } /* VRF deletion from zebra daemon. */ -int -zsend_vrf_delete (struct zserv *client, struct zebra_vrf *zvrf) +int zsend_vrf_delete(struct zserv *client, struct zebra_vrf *zvrf) { - struct stream *s; + struct stream *s; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_VRF_DELETE, zvrf_id (zvrf)); - zserv_encode_vrf (s, zvrf); + zserv_create_header(s, ZEBRA_VRF_DELETE, zvrf_id(zvrf)); + zserv_encode_vrf(s, zvrf); - client->vrfdel_cnt++; - return zebra_server_send_message (client); + client->vrfdel_cnt++; + return zebra_server_send_message(client); } -int -zsend_interface_link_params (struct zserv *client, struct interface *ifp) +int zsend_interface_link_params(struct zserv *client, struct interface *ifp) { - struct stream *s; + struct stream *s; - /* Check this client need interface information. */ - if (! client->ifinfo) - return 0; + /* Check this client need interface information. */ + if (!client->ifinfo) + return 0; - if (!ifp->link_params) - return 0; - s = client->obuf; - stream_reset (s); + if (!ifp->link_params) + return 0; + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id); + zserv_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id); - /* Add Interface Index */ - stream_putl (s, ifp->ifindex); + /* Add Interface Index */ + stream_putl(s, ifp->ifindex); - /* Then TE Link Parameters */ - if (zebra_interface_link_params_write (s, ifp) == 0) - return 0; + /* Then TE Link Parameters */ + if (zebra_interface_link_params_write(s, ifp) == 0) + return 0; - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message (client); + return zebra_server_send_message(client); } /* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or - * ZEBRA_INTERFACE_ADDRESS_DELETE to the client. + * ZEBRA_INTERFACE_ADDRESS_DELETE to the client. * * A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations: * - in response to a 3-byte ZEBRA_INTERFACE_ADD request @@ -323,13 +313,13 @@ zsend_interface_link_params (struct zserv *client, struct interface *ifp) * - for the vty commands "ip address A.B.C.D/M [<secondary>|<label LINE>]" * and "no bandwidth <1-10000000>", "ipv6 address X:X::X:X/M" * - when an RTM_NEWADDR message is received from the kernel, - * - * The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE: + * + * The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE: * * zsend_interface_address(DELETE) - * ^ - * | - * zebra_interface_address_delete_update + * ^ + * | + * zebra_interface_address_delete_update * ^ ^ ^ * | | if_delete_update * | | @@ -345,232 +335,230 @@ zsend_interface_link_params (struct zserv *client, struct interface *ifp) * ["no ipv6 address X:X::X:X/M"] * */ -int -zsend_interface_address (int cmd, struct zserv *client, - struct interface *ifp, struct connected *ifc) -{ - int blen; - struct stream *s; - struct prefix *p; - - s = client->obuf; - stream_reset (s); - - zserv_create_header (s, cmd, ifp->vrf_id); - stream_putl (s, ifp->ifindex); - - /* Interface address flag. */ - stream_putc (s, ifc->flags); - - /* Prefix information. */ - p = ifc->address; - stream_putc (s, p->family); - blen = prefix_blen (p); - stream_put (s, &p->u.prefix, blen); - - /* - * XXX gnu version does not send prefixlen for ZEBRA_INTERFACE_ADDRESS_DELETE - * but zebra_interface_address_delete_read() in the gnu version - * expects to find it - */ - stream_putc (s, p->prefixlen); - - /* Destination. */ - p = ifc->destination; - if (p) - stream_put (s, &p->u.prefix, blen); - else - stream_put (s, NULL, blen); +int zsend_interface_address(int cmd, struct zserv *client, + struct interface *ifp, struct connected *ifc) +{ + int blen; + struct stream *s; + struct prefix *p; + + s = client->obuf; + stream_reset(s); + + zserv_create_header(s, cmd, ifp->vrf_id); + stream_putl(s, ifp->ifindex); + + /* Interface address flag. */ + stream_putc(s, ifc->flags); + + /* Prefix information. */ + p = ifc->address; + stream_putc(s, p->family); + blen = prefix_blen(p); + stream_put(s, &p->u.prefix, blen); + + /* + * XXX gnu version does not send prefixlen for + * ZEBRA_INTERFACE_ADDRESS_DELETE + * but zebra_interface_address_delete_read() in the gnu version + * expects to find it + */ + stream_putc(s, p->prefixlen); + + /* Destination. */ + p = ifc->destination; + if (p) + stream_put(s, &p->u.prefix, blen); + else + stream_put(s, NULL, blen); - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - client->connected_rt_add_cnt++; - return zebra_server_send_message(client); + client->connected_rt_add_cnt++; + return zebra_server_send_message(client); } -static int -zsend_interface_nbr_address (int cmd, struct zserv *client, - struct interface *ifp, struct nbr_connected *ifc) +static int zsend_interface_nbr_address(int cmd, struct zserv *client, + struct interface *ifp, + struct nbr_connected *ifc) { - int blen; - struct stream *s; - struct prefix *p; + int blen; + struct stream *s; + struct prefix *p; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, cmd, ifp->vrf_id); - stream_putl (s, ifp->ifindex); + zserv_create_header(s, cmd, ifp->vrf_id); + stream_putl(s, ifp->ifindex); - /* Prefix information. */ - p = ifc->address; - stream_putc (s, p->family); - blen = prefix_blen (p); - stream_put (s, &p->u.prefix, blen); + /* Prefix information. */ + p = ifc->address; + stream_putc(s, p->family); + blen = prefix_blen(p); + stream_put(s, &p->u.prefix, blen); - /* - * XXX gnu version does not send prefixlen for ZEBRA_INTERFACE_ADDRESS_DELETE - * but zebra_interface_address_delete_read() in the gnu version - * expects to find it - */ - stream_putc (s, p->prefixlen); + /* + * XXX gnu version does not send prefixlen for + * ZEBRA_INTERFACE_ADDRESS_DELETE + * but zebra_interface_address_delete_read() in the gnu version + * expects to find it + */ + stream_putc(s, p->prefixlen); - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client); + return zebra_server_send_message(client); } /* Interface address addition. */ -static void -zebra_interface_nbr_address_add_update (struct interface *ifp, - struct nbr_connected *ifc) -{ - struct listnode *node, *nnode; - struct zserv *client; - struct prefix *p; - - if (IS_ZEBRA_DEBUG_EVENT) - { - char buf[INET6_ADDRSTRLEN]; - - p = ifc->address; - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_ADD %s/%d on %s", - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN), - p->prefixlen, ifc->ifp->name); - } +static void zebra_interface_nbr_address_add_update(struct interface *ifp, + struct nbr_connected *ifc) +{ + struct listnode *node, *nnode; + struct zserv *client; + struct prefix *p; + + if (IS_ZEBRA_DEBUG_EVENT) { + char buf[INET6_ADDRSTRLEN]; + + p = ifc->address; + zlog_debug( + "MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_ADD %s/%d on %s", + inet_ntop(p->family, &p->u.prefix, buf, + INET6_ADDRSTRLEN), + p->prefixlen, ifc->ifp->name); + } - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_ADD, client, ifp, ifc); + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_ADD, + client, ifp, ifc); } /* Interface address deletion. */ -static void -zebra_interface_nbr_address_delete_update (struct interface *ifp, - struct nbr_connected *ifc) -{ - struct listnode *node, *nnode; - struct zserv *client; - struct prefix *p; - - if (IS_ZEBRA_DEBUG_EVENT) - { - char buf[INET6_ADDRSTRLEN]; - - p = ifc->address; - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_DELETE %s/%d on %s", - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN), - p->prefixlen, ifc->ifp->name); - } +static void zebra_interface_nbr_address_delete_update(struct interface *ifp, + struct nbr_connected *ifc) +{ + struct listnode *node, *nnode; + struct zserv *client; + struct prefix *p; + + if (IS_ZEBRA_DEBUG_EVENT) { + char buf[INET6_ADDRSTRLEN]; + + p = ifc->address; + zlog_debug( + "MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_DELETE %s/%d on %s", + inet_ntop(p->family, &p->u.prefix, buf, + INET6_ADDRSTRLEN), + p->prefixlen, ifc->ifp->name); + } - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_DELETE, client, ifp, ifc); + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE, + client, ifp, ifc); } /* Send addresses on interface to client */ -int -zsend_interface_addresses (struct zserv *client, struct interface *ifp) +int zsend_interface_addresses(struct zserv *client, struct interface *ifp) { - struct listnode *cnode, *cnnode; - struct connected *c; - struct nbr_connected *nc; + struct listnode *cnode, *cnnode; + struct connected *c; + struct nbr_connected *nc; - /* Send interface addresses. */ - for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, c)) - { - if (!CHECK_FLAG (c->conf, ZEBRA_IFC_REAL)) - continue; + /* Send interface addresses. */ + for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) { + if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL)) + continue; - if (zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client, - ifp, c) < 0) - return -1; - } + if (zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_ADD, client, + ifp, c) + < 0) + return -1; + } - /* Send interface neighbors. */ - for (ALL_LIST_ELEMENTS (ifp->nbr_connected, cnode, cnnode, nc)) - { - if (zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_ADD, - client, ifp, nc) < 0) - return -1; - } + /* Send interface neighbors. */ + for (ALL_LIST_ELEMENTS(ifp->nbr_connected, cnode, cnnode, nc)) { + if (zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_ADD, + client, ifp, nc) + < 0) + return -1; + } - return 0; + return 0; } /* Notify client about interface moving from one VRF to another. * Whether client is interested in old and new VRF is checked by caller. */ -int -zsend_interface_vrf_update (struct zserv *client, struct interface *ifp, - vrf_id_t vrf_id) +int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp, + vrf_id_t vrf_id) { - struct stream *s; + struct stream *s; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id); + zserv_create_header(s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id); - /* Fill in the ifIndex of the interface and its new VRF (id) */ - stream_putl (s, ifp->ifindex); - stream_putw (s, vrf_id); + /* Fill in the ifIndex of the interface and its new VRF (id) */ + stream_putl(s, ifp->ifindex); + stream_putw(s, vrf_id); - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - client->if_vrfchg_cnt++; - return zebra_server_send_message(client); + client->if_vrfchg_cnt++; + return zebra_server_send_message(client); } /* Add new nbr connected IPv6 address */ -void -nbr_connected_add_ipv6 (struct interface *ifp, struct in6_addr *address) +void nbr_connected_add_ipv6(struct interface *ifp, struct in6_addr *address) { - struct nbr_connected *ifc; - struct prefix p; + struct nbr_connected *ifc; + struct prefix p; - p.family = AF_INET6; - IPV6_ADDR_COPY (&p.u.prefix, address); - p.prefixlen = IPV6_MAX_PREFIXLEN; + p.family = AF_INET6; + IPV6_ADDR_COPY(&p.u.prefix, address); + p.prefixlen = IPV6_MAX_PREFIXLEN; - if (!(ifc = listnode_head(ifp->nbr_connected))) - { - /* new addition */ - ifc = nbr_connected_new (); - ifc->address = prefix_new(); - ifc->ifp = ifp; - listnode_add (ifp->nbr_connected, ifc); - } + if (!(ifc = listnode_head(ifp->nbr_connected))) { + /* new addition */ + ifc = nbr_connected_new(); + ifc->address = prefix_new(); + ifc->ifp = ifp; + listnode_add(ifp->nbr_connected, ifc); + } - prefix_copy(ifc->address, &p); + prefix_copy(ifc->address, &p); - zebra_interface_nbr_address_add_update (ifp, ifc); + zebra_interface_nbr_address_add_update(ifp, ifc); - if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, address, 1); + if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, address, 1); } -void -nbr_connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address) +void nbr_connected_delete_ipv6(struct interface *ifp, struct in6_addr *address) { - struct nbr_connected *ifc; - struct prefix p; + struct nbr_connected *ifc; + struct prefix p; - p.family = AF_INET6; - IPV6_ADDR_COPY (&p.u.prefix, address); - p.prefixlen = IPV6_MAX_PREFIXLEN; + p.family = AF_INET6; + IPV6_ADDR_COPY(&p.u.prefix, address); + p.prefixlen = IPV6_MAX_PREFIXLEN; - ifc = nbr_connected_check(ifp, &p); - if (!ifc) - return; + ifc = nbr_connected_check(ifp, &p); + if (!ifc) + return; - listnode_delete (ifp->nbr_connected, ifc); + listnode_delete(ifp->nbr_connected, ifc); - zebra_interface_nbr_address_delete_update (ifp, ifc); + zebra_interface_nbr_address_delete_update(ifp, ifc); - if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, address, 0); + if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, address, 0); - nbr_connected_free (ifc); + nbr_connected_free(ifc); } /* @@ -583,23 +571,22 @@ nbr_connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address) * - a vty command modifying the bandwidth of an interface is received. * The ZEBRA_INTERFACE_DOWN message is sent when an if_down is detected. */ -int -zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp) +int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp) { - struct stream *s; + struct stream *s; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, cmd, ifp->vrf_id); - zserv_encode_interface (s, ifp); + zserv_create_header(s, cmd, ifp->vrf_id); + zserv_encode_interface(s, ifp); - if (cmd == ZEBRA_INTERFACE_UP) - client->ifup_cnt++; - else - client->ifdown_cnt++; + if (cmd == ZEBRA_INTERFACE_UP) + client->ifup_cnt++; + else + client->ifdown_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client); } /* @@ -609,441 +596,413 @@ zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp) * away or ignored by the receiver. This is the leaner function that is not a * duplicate of the zapi_ipv4_route_add/del. * - * The primary difference is that this function merely sends a single NH instead of + * The primary difference is that this function merely sends a single NH instead + * of * all the nexthops. */ -int -zsend_redistribute_route (int add, struct zserv *client, struct prefix *p, - struct prefix *src_p, struct route_entry *re) -{ - afi_t afi; - int cmd; - int psize; - struct stream *s; - struct nexthop *nexthop; - unsigned long nhnummark = 0, messmark = 0; - int nhnum = 0; - u_char zapi_flags = 0; - struct nexthop dummy_nh; - - afi = family2afi (p->family); - if (add) - { - switch (afi) - { - case AFI_IP: - cmd = ZEBRA_REDISTRIBUTE_IPV4_ADD; - client->redist_v4_add_cnt++; - break; - case AFI_IP6: - cmd = ZEBRA_REDISTRIBUTE_IPV6_ADD; - client->redist_v6_add_cnt++; - break; - default: - return -1; - } - } - else - { - switch (afi) - { - case AFI_IP: - cmd = ZEBRA_REDISTRIBUTE_IPV4_DEL; - client->redist_v4_del_cnt++; - break; - case AFI_IP6: - cmd = ZEBRA_REDISTRIBUTE_IPV6_DEL; - client->redist_v6_del_cnt++; - break; - default: - return -1; - } - } - - s = client->obuf; - stream_reset (s); - memset(&dummy_nh, 0, sizeof(struct nexthop)); - - zserv_create_header (s, cmd, re->vrf_id); - - /* Put type and nexthop. */ - stream_putc (s, re->type); - stream_putw (s, re->instance); - stream_putl (s, re->flags); - - /* marker for message flags field */ - messmark = stream_get_endp (s); - stream_putc (s, 0); - - /* Prefix. */ - psize = PSIZE (p->prefixlen); - stream_putc (s, p->prefixlen); - stream_write (s, (u_char *) & p->u.prefix, psize); - - if (src_p) - { - SET_FLAG (zapi_flags, ZAPI_MESSAGE_SRCPFX); - psize = PSIZE (src_p->prefixlen); - stream_putc (s, src_p->prefixlen); - stream_write (s, (u_char *) & src_p->u.prefix, psize); - } - - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - { - /* We don't send any nexthops when there's a multipath */ - if (re->nexthop_active_num > 1 && client->proto != ZEBRA_ROUTE_LDP) - { - SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX); - - stream_putc(s, 1); - if (p->family == AF_INET) - { - stream_put_in_addr (s, &dummy_nh.gate.ipv4); - } - else if (p->family == AF_INET6) - { - stream_write (s, (u_char *) &dummy_nh.gate.ipv6, 16); - } - else - { - /* We don't handle anything else now, abort */ - zlog_err("%s: Unable to redistribute route of unknown family, %d\n", - __func__, p->family); - return -1; - } - stream_putc (s, 1); - stream_putl (s, 0); /* dummy ifindex */ - break; +int zsend_redistribute_route(int add, struct zserv *client, struct prefix *p, + struct prefix *src_p, struct route_entry *re) +{ + afi_t afi; + int cmd; + int psize; + struct stream *s; + struct nexthop *nexthop; + unsigned long nhnummark = 0, messmark = 0; + int nhnum = 0; + u_char zapi_flags = 0; + struct nexthop dummy_nh; + + afi = family2afi(p->family); + if (add) { + switch (afi) { + case AFI_IP: + cmd = ZEBRA_REDISTRIBUTE_IPV4_ADD; + client->redist_v4_add_cnt++; + break; + case AFI_IP6: + cmd = ZEBRA_REDISTRIBUTE_IPV6_ADD; + client->redist_v6_add_cnt++; + break; + default: + return -1; + } + } else { + switch (afi) { + case AFI_IP: + cmd = ZEBRA_REDISTRIBUTE_IPV4_DEL; + client->redist_v4_del_cnt++; + break; + case AFI_IP6: + cmd = ZEBRA_REDISTRIBUTE_IPV6_DEL; + client->redist_v6_del_cnt++; + break; + default: + return -1; + } } - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - { - SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX); - if (nhnummark == 0) - { - nhnummark = stream_get_endp (s); - stream_putc (s, 1); /* placeholder */ - } - nhnum++; - - switch(nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - stream_put_in_addr (s, &nexthop->gate.ipv4); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - /* Only BGP supports IPv4 prefix with IPv6 NH, so kill this */ - if (p->family == AF_INET) - stream_put_in_addr(s, &dummy_nh.gate.ipv4); - else - stream_write (s, (u_char *) &nexthop->gate.ipv6, 16); - break; - default: - if (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD - || cmd == ZEBRA_REDISTRIBUTE_IPV4_DEL) - { - struct in_addr empty; - memset (&empty, 0, sizeof (struct in_addr)); - stream_write (s, (u_char *) &empty, IPV4_MAX_BYTELEN); - } - else - { - struct in6_addr empty; - memset (&empty, 0, sizeof (struct in6_addr)); - stream_write (s, (u_char *) &empty, IPV6_MAX_BYTELEN); - } - } - - /* Interface index. */ - stream_putc (s, 1); - stream_putl (s, nexthop->ifindex); - - /* ldpd needs all nexthops */ - if (client->proto != ZEBRA_ROUTE_LDP) - break; - } - } - - /* Distance */ - SET_FLAG (zapi_flags, ZAPI_MESSAGE_DISTANCE); - stream_putc (s, re->distance); - - /* Metric */ - SET_FLAG (zapi_flags, ZAPI_MESSAGE_METRIC); - stream_putl (s, re->metric); - - /* Tag */ - if (re->tag) - { - SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG); - stream_putl(s, re->tag); - } - - /* MTU */ - SET_FLAG (zapi_flags, ZAPI_MESSAGE_MTU); - stream_putl (s, re->mtu); - - /* write real message flags value */ - stream_putc_at (s, messmark, zapi_flags); - - /* Write next-hop number */ - if (nhnummark) - stream_putc_at (s, nhnummark, nhnum); - - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); - - return zebra_server_send_message(client); -} - -static int -zsend_write_nexthop (struct stream *s, struct nexthop *nexthop) -{ - stream_putc (s, nexthop->type); - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - stream_put_in_addr (s, &nexthop->gate.ipv4); - stream_putl (s, nexthop->ifindex); - break; - case NEXTHOP_TYPE_IPV6: - stream_put (s, &nexthop->gate.ipv6, 16); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_put (s, &nexthop->gate.ipv6, 16); - stream_putl (s, nexthop->ifindex); - break; - case NEXTHOP_TYPE_IFINDEX: - stream_putl (s, nexthop->ifindex); - break; - default: - /* do nothing */ - break; - } - return 1; -} + s = client->obuf; + stream_reset(s); + memset(&dummy_nh, 0, sizeof(struct nexthop)); -/* Nexthop register */ -static int -zserv_rnh_register (struct zserv *client, int sock, u_short length, - rnh_type_t type, struct zebra_vrf *zvrf) -{ - struct rnh *rnh; - struct stream *s; - struct prefix p; - u_short l = 0; - u_char flags = 0; - - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("rnh_register msg from client %s: length=%d, type=%s\n", - zebra_route_string(client->proto), length, - (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route"); - - s = client->ibuf; - - client->nh_reg_time = monotime(NULL); - - while (l < length) - { - flags = stream_getc(s); - p.family = stream_getw(s); - p.prefixlen = stream_getc(s); - l += 4; - if (p.family == AF_INET) - { - p.u.prefix4.s_addr = stream_get_ipv4(s); - l += IPV4_MAX_BYTELEN; - } - else if (p.family == AF_INET6) - { - stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN); - l += IPV6_MAX_BYTELEN; - } - else - { - zlog_err("rnh_register: Received unknown family type %d\n", - p.family); - return -1; + zserv_create_header(s, cmd, re->vrf_id); + + /* Put type and nexthop. */ + stream_putc(s, re->type); + stream_putw(s, re->instance); + stream_putl(s, re->flags); + + /* marker for message flags field */ + messmark = stream_get_endp(s); + stream_putc(s, 0); + + /* Prefix. */ + psize = PSIZE(p->prefixlen); + stream_putc(s, p->prefixlen); + stream_write(s, (u_char *)&p->u.prefix, psize); + + if (src_p) { + SET_FLAG(zapi_flags, ZAPI_MESSAGE_SRCPFX); + psize = PSIZE(src_p->prefixlen); + stream_putc(s, src_p->prefixlen); + stream_write(s, (u_char *)&src_p->u.prefix, psize); } - rnh = zebra_add_rnh(&p, zvrf_id (zvrf), type); - if (type == RNH_NEXTHOP_TYPE) - { - if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) - SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); - else if (!flags && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) - UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); + + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { + /* We don't send any nexthops when there's a multipath */ + if (re->nexthop_active_num > 1 + && client->proto != ZEBRA_ROUTE_LDP) { + SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX); + + stream_putc(s, 1); + if (p->family == AF_INET) { + stream_put_in_addr(s, &dummy_nh.gate.ipv4); + } else if (p->family == AF_INET6) { + stream_write(s, (u_char *)&dummy_nh.gate.ipv6, + 16); + } else { + /* We don't handle anything else now, abort */ + zlog_err( + "%s: Unable to redistribute route of unknown family, %d\n", + __func__, p->family); + return -1; + } + stream_putc(s, 1); + stream_putl(s, 0); /* dummy ifindex */ + break; + } + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) { + SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX); + if (nhnummark == 0) { + nhnummark = stream_get_endp(s); + stream_putc(s, 1); /* placeholder */ + } + nhnum++; + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + stream_put_in_addr(s, &nexthop->gate.ipv4); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + /* Only BGP supports IPv4 prefix with IPv6 NH, + * so kill this */ + if (p->family == AF_INET) + stream_put_in_addr(s, + &dummy_nh.gate.ipv4); + else + stream_write( + s, + (u_char *)&nexthop->gate.ipv6, + 16); + break; + default: + if (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD + || cmd == ZEBRA_REDISTRIBUTE_IPV4_DEL) { + struct in_addr empty; + memset(&empty, 0, + sizeof(struct in_addr)); + stream_write(s, (u_char *)&empty, + IPV4_MAX_BYTELEN); + } else { + struct in6_addr empty; + memset(&empty, 0, + sizeof(struct in6_addr)); + stream_write(s, (u_char *)&empty, + IPV6_MAX_BYTELEN); + } + } + + /* Interface index. */ + stream_putc(s, 1); + stream_putl(s, nexthop->ifindex); + + /* ldpd needs all nexthops */ + if (client->proto != ZEBRA_ROUTE_LDP) + break; + } } - else if (type == RNH_IMPORT_CHECK_TYPE) - { - if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) - SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); - else if (!flags && CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) - UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); + + /* Distance */ + SET_FLAG(zapi_flags, ZAPI_MESSAGE_DISTANCE); + stream_putc(s, re->distance); + + /* Metric */ + SET_FLAG(zapi_flags, ZAPI_MESSAGE_METRIC); + stream_putl(s, re->metric); + + /* Tag */ + if (re->tag) { + SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG); + stream_putl(s, re->tag); } - zebra_add_rnh_client(rnh, client, type, zvrf_id (zvrf)); - /* Anything not AF_INET/INET6 has been filtered out above */ - zebra_evaluate_rnh(zvrf_id (zvrf), p.family, 1, type, &p); - } - return 0; + /* MTU */ + SET_FLAG(zapi_flags, ZAPI_MESSAGE_MTU); + stream_putl(s, re->mtu); + + /* write real message flags value */ + stream_putc_at(s, messmark, zapi_flags); + + /* Write next-hop number */ + if (nhnummark) + stream_putc_at(s, nhnummark, nhnum); + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + return zebra_server_send_message(client); +} + +static int zsend_write_nexthop(struct stream *s, struct nexthop *nexthop) +{ + stream_putc(s, nexthop->type); + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + stream_put_in_addr(s, &nexthop->gate.ipv4); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV6: + stream_put(s, &nexthop->gate.ipv6, 16); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_put(s, &nexthop->gate.ipv6, 16); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IFINDEX: + stream_putl(s, nexthop->ifindex); + break; + default: + /* do nothing */ + break; + } + return 1; } /* Nexthop register */ -static int -zserv_rnh_unregister (struct zserv *client, int sock, u_short length, - rnh_type_t type, struct zebra_vrf *zvrf) -{ - struct rnh *rnh; - struct stream *s; - struct prefix p; - u_short l = 0; - - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("rnh_unregister msg from client %s: length=%d\n", - zebra_route_string(client->proto), length); - - s = client->ibuf; - - while (l < length) - { - (void)stream_getc(s); //Connected or not. Not used in this function - p.family = stream_getw(s); - p.prefixlen = stream_getc(s); - l += 4; - if (p.family == AF_INET) - { - p.u.prefix4.s_addr = stream_get_ipv4(s); - l += IPV4_MAX_BYTELEN; - } - else if (p.family == AF_INET6) - { - stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN); - l += IPV6_MAX_BYTELEN; - } - else - { - zlog_err("rnh_register: Received unknown family type %d\n", - p.family); - return -1; +static int zserv_rnh_register(struct zserv *client, int sock, u_short length, + rnh_type_t type, struct zebra_vrf *zvrf) +{ + struct rnh *rnh; + struct stream *s; + struct prefix p; + u_short l = 0; + u_char flags = 0; + + if (IS_ZEBRA_DEBUG_NHT) + zlog_debug( + "rnh_register msg from client %s: length=%d, type=%s\n", + zebra_route_string(client->proto), length, + (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route"); + + s = client->ibuf; + + client->nh_reg_time = monotime(NULL); + + while (l < length) { + flags = stream_getc(s); + p.family = stream_getw(s); + p.prefixlen = stream_getc(s); + l += 4; + if (p.family == AF_INET) { + p.u.prefix4.s_addr = stream_get_ipv4(s); + l += IPV4_MAX_BYTELEN; + } else if (p.family == AF_INET6) { + stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN); + l += IPV6_MAX_BYTELEN; + } else { + zlog_err( + "rnh_register: Received unknown family type %d\n", + p.family); + return -1; + } + rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type); + if (type == RNH_NEXTHOP_TYPE) { + if (flags + && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) + SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); + else if (!flags + && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) + UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); + } else if (type == RNH_IMPORT_CHECK_TYPE) { + if (flags + && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) + SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); + else if (!flags && CHECK_FLAG(rnh->flags, + ZEBRA_NHT_EXACT_MATCH)) + UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); + } + + zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); + /* Anything not AF_INET/INET6 has been filtered out above */ + zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p); } - rnh = zebra_lookup_rnh(&p, zvrf_id (zvrf), type); - if (rnh) - { - client->nh_dereg_time = monotime(NULL); - zebra_remove_rnh_client(rnh, client, type); + return 0; +} + +/* Nexthop register */ +static int zserv_rnh_unregister(struct zserv *client, int sock, u_short length, + rnh_type_t type, struct zebra_vrf *zvrf) +{ + struct rnh *rnh; + struct stream *s; + struct prefix p; + u_short l = 0; + + if (IS_ZEBRA_DEBUG_NHT) + zlog_debug("rnh_unregister msg from client %s: length=%d\n", + zebra_route_string(client->proto), length); + + s = client->ibuf; + + while (l < length) { + (void)stream_getc( + s); // Connected or not. Not used in this function + p.family = stream_getw(s); + p.prefixlen = stream_getc(s); + l += 4; + if (p.family == AF_INET) { + p.u.prefix4.s_addr = stream_get_ipv4(s); + l += IPV4_MAX_BYTELEN; + } else if (p.family == AF_INET6) { + stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN); + l += IPV6_MAX_BYTELEN; + } else { + zlog_err( + "rnh_register: Received unknown family type %d\n", + p.family); + return -1; + } + rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type); + if (rnh) { + client->nh_dereg_time = monotime(NULL); + zebra_remove_rnh_client(rnh, client, type); + } } - } - return 0; + return 0; } #define ZEBRA_MIN_FEC_LENGTH 5 /* FEC register */ -static int -zserv_fec_register (struct zserv *client, int sock, u_short length) -{ - struct stream *s; - struct zebra_vrf *zvrf; - u_short l = 0; - struct prefix p; - u_int16_t flags; - u_int32_t label_index = MPLS_INVALID_LABEL_INDEX; - - s = client->ibuf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - return 0; // unexpected - - /* - * The minimum amount of data that can be sent for one fec - * registration - */ - if (length < ZEBRA_MIN_FEC_LENGTH) - { - zlog_err ("fec_register: Received a fec register of length %d, it is of insufficient size to properly decode", - length); - return -1; - } - - while (l < length) - { - flags = stream_getw(s); - p.family = stream_getw(s); - if (p.family != AF_INET && - p.family != AF_INET6) - { - zlog_err ("fec_register: Received unknown family type %d\n", - p.family); - return -1; - } - p.prefixlen = stream_getc(s); - l += 5; - stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); - l += PSIZE(p.prefixlen); - if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) - { - label_index = stream_getl(s); - l += 4; - } - else - label_index = MPLS_INVALID_LABEL_INDEX; - zebra_mpls_fec_register (zvrf, &p, label_index, client); - } - - return 0; +static int zserv_fec_register(struct zserv *client, int sock, u_short length) +{ + struct stream *s; + struct zebra_vrf *zvrf; + u_short l = 0; + struct prefix p; + u_int16_t flags; + u_int32_t label_index = MPLS_INVALID_LABEL_INDEX; + + s = client->ibuf; + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) + return 0; // unexpected + + /* + * The minimum amount of data that can be sent for one fec + * registration + */ + if (length < ZEBRA_MIN_FEC_LENGTH) { + zlog_err( + "fec_register: Received a fec register of length %d, it is of insufficient size to properly decode", + length); + return -1; + } + + while (l < length) { + flags = stream_getw(s); + p.family = stream_getw(s); + if (p.family != AF_INET && p.family != AF_INET6) { + zlog_err( + "fec_register: Received unknown family type %d\n", + p.family); + return -1; + } + p.prefixlen = stream_getc(s); + l += 5; + stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); + l += PSIZE(p.prefixlen); + if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) { + label_index = stream_getl(s); + l += 4; + } else + label_index = MPLS_INVALID_LABEL_INDEX; + zebra_mpls_fec_register(zvrf, &p, label_index, client); + } + + return 0; } /* FEC unregister */ -static int -zserv_fec_unregister (struct zserv *client, int sock, u_short length) -{ - struct stream *s; - struct zebra_vrf *zvrf; - u_short l = 0; - struct prefix p; - //u_int16_t flags; - - s = client->ibuf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - return 0; // unexpected - - /* - * The minimum amount of data that can be sent for one - * fec unregistration - */ - if (length < ZEBRA_MIN_FEC_LENGTH) - { - zlog_err ("fec_unregister: Received a fec unregister of length %d, it is of insufficient size to properly decode", - length); - return -1; - } - - while (l < length) - { - //flags = stream_getw(s); - (void)stream_getw(s); - p.family = stream_getw(s); - if (p.family != AF_INET && - p.family != AF_INET6) - { - zlog_err ("fec_unregister: Received unknown family type %d\n", - p.family); - return -1; - } - p.prefixlen = stream_getc(s); - l += 5; - stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); - l += PSIZE(p.prefixlen); - zebra_mpls_fec_unregister (zvrf, &p, client); - } - - return 0; +static int zserv_fec_unregister(struct zserv *client, int sock, u_short length) +{ + struct stream *s; + struct zebra_vrf *zvrf; + u_short l = 0; + struct prefix p; + // u_int16_t flags; + + s = client->ibuf; + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) + return 0; // unexpected + + /* + * The minimum amount of data that can be sent for one + * fec unregistration + */ + if (length < ZEBRA_MIN_FEC_LENGTH) { + zlog_err( + "fec_unregister: Received a fec unregister of length %d, it is of insufficient size to properly decode", + length); + return -1; + } + + while (l < length) { + // flags = stream_getw(s); + (void)stream_getw(s); + p.family = stream_getw(s); + if (p.family != AF_INET && p.family != AF_INET6) { + zlog_err( + "fec_unregister: Received unknown family type %d\n", + p.family); + return -1; + } + p.prefixlen = stream_getc(s); + l += 5; + stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); + l += PSIZE(p.prefixlen); + zebra_mpls_fec_unregister(zvrf, &p, client); + } + + return 0; } /* @@ -1051,1514 +1010,1510 @@ zserv_fec_unregister (struct zserv *client, int sock, u_short length) Query unicast rib if nexthop is not found on mrib. Returns both route metric and protocol distance. */ -static int -zsend_ipv4_nexthop_lookup_mrib (struct zserv *client, struct in_addr addr, struct route_entry *re, struct zebra_vrf *zvrf) -{ - struct stream *s; - unsigned long nump; - u_char num; - struct nexthop *nexthop; - - /* Get output stream. */ - s = client->obuf; - stream_reset (s); - - /* Fill in result. */ - zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id (zvrf)); - stream_put_in_addr (s, &addr); - - if (re) - { - stream_putc (s, re->distance); - stream_putl (s, re->metric); - num = 0; - nump = stream_get_endp(s); /* remember position for nexthop_num */ - stream_putc (s, 0); /* reserve room for nexthop_num */ - /* Only non-recursive routes are elegible to resolve the nexthop we - * are looking up. Therefore, we will just iterate over the top - * chain of nexthops. */ - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - num += zsend_write_nexthop (s, nexthop); - - stream_putc_at (s, nump, num); /* store nexthop_num */ - } - else - { - stream_putc (s, 0); /* distance */ - stream_putl (s, 0); /* metric */ - stream_putc (s, 0); /* nexthop_num */ - } - - stream_putw_at (s, 0, stream_get_endp (s)); - - return zebra_server_send_message(client); +static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, + struct in_addr addr, + struct route_entry *re, + struct zebra_vrf *zvrf) +{ + struct stream *s; + unsigned long nump; + u_char num; + struct nexthop *nexthop; + + /* Get output stream. */ + s = client->obuf; + stream_reset(s); + + /* Fill in result. */ + zserv_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf)); + stream_put_in_addr(s, &addr); + + if (re) { + stream_putc(s, re->distance); + stream_putl(s, re->metric); + num = 0; + nump = stream_get_endp( + s); /* remember position for nexthop_num */ + stream_putc(s, 0); /* reserve room for nexthop_num */ + /* Only non-recursive routes are elegible to resolve the nexthop + * we + * are looking up. Therefore, we will just iterate over the top + * chain of nexthops. */ + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + num += zsend_write_nexthop(s, nexthop); + + stream_putc_at(s, nump, num); /* store nexthop_num */ + } else { + stream_putc(s, 0); /* distance */ + stream_putl(s, 0); /* metric */ + stream_putc(s, 0); /* nexthop_num */ + } + + stream_putw_at(s, 0, stream_get_endp(s)); + + return zebra_server_send_message(client); } /* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */ -int -zsend_router_id_update (struct zserv *client, struct prefix *p, - vrf_id_t vrf_id) +int zsend_router_id_update(struct zserv *client, struct prefix *p, + vrf_id_t vrf_id) { - struct stream *s; - int blen; + struct stream *s; + int blen; - /* Check this client need interface information. */ - if (! vrf_bitmap_check (client->ridinfo, vrf_id)) - return 0; + /* Check this client need interface information. */ + if (!vrf_bitmap_check(client->ridinfo, vrf_id)) + return 0; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - /* Message type. */ - zserv_create_header (s, ZEBRA_ROUTER_ID_UPDATE, vrf_id); + /* Message type. */ + zserv_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id); - /* Prefix information. */ - stream_putc (s, p->family); - blen = prefix_blen (p); - stream_put (s, &p->u.prefix, blen); - stream_putc (s, p->prefixlen); + /* Prefix information. */ + stream_putc(s, p->family); + blen = prefix_blen(p); + stream_put(s, &p->u.prefix, blen); + stream_putc(s, p->prefixlen); - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client); + return zebra_server_send_message(client); } /* Register zebra server interface information. Send current all interface and address information. */ -static int -zread_interface_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) +static int zread_interface_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { - struct vrf *vrf; - struct listnode *ifnode, *ifnnode; - struct interface *ifp; + struct vrf *vrf; + struct listnode *ifnode, *ifnnode; + struct interface *ifp; - /* Interface information is needed. */ - vrf_bitmap_set (client->ifinfo, zvrf_id (zvrf)); + /* Interface information is needed. */ + vrf_bitmap_set(client->ifinfo, zvrf_id(zvrf)); - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - { - for (ALL_LIST_ELEMENTS (vrf->iflist, ifnode, ifnnode, ifp)) - { - /* Skip pseudo interface. */ - if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - continue; + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + { + for (ALL_LIST_ELEMENTS(vrf->iflist, ifnode, ifnnode, ifp)) { + /* Skip pseudo interface. */ + if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) + continue; - if (zsend_interface_add (client, ifp) < 0) - return -1; + if (zsend_interface_add(client, ifp) < 0) + return -1; - if (zsend_interface_addresses (client, ifp) < 0) - return -1; - } - } - return 0; + if (zsend_interface_addresses(client, ifp) < 0) + return -1; + } + } + return 0; } /* Unregister zebra server interface information. */ -static int -zread_interface_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) +static int zread_interface_delete(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { - vrf_bitmap_unset (client->ifinfo, zvrf_id (zvrf)); - return 0; + vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf)); + return 0; } -void -zserv_nexthop_num_warn (const char *caller, const struct prefix *p, const unsigned int nexthop_num) +void zserv_nexthop_num_warn(const char *caller, const struct prefix *p, + const unsigned int nexthop_num) { - if (nexthop_num > multipath_num) - { - char buff[PREFIX2STR_BUFFER]; - prefix2str(p, buff, sizeof (buff)); - zlog_warn("%s: Prefix %s has %d nexthops, but we can only use the first %d", - caller, buff, nexthop_num, multipath_num); - } + if (nexthop_num > multipath_num) { + char buff[PREFIX2STR_BUFFER]; + prefix2str(p, buff, sizeof(buff)); + zlog_warn( + "%s: Prefix %s has %d nexthops, but we can only use the first %d", + caller, buff, nexthop_num, multipath_num); + } } /* This function support multiple nexthop. */ -/* +/* * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and - * add kernel route. + * add kernel route. */ -static int -zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) -{ - int i; - struct route_entry *re; - struct prefix p; - u_char message; - struct in_addr nhop_addr; - u_char nexthop_num; - u_char nexthop_type; - struct stream *s; - ifindex_t ifindex; - safi_t safi; - int ret; - mpls_label_t label; - struct nexthop *nexthop; - - /* Get input stream. */ - s = client->ibuf; - - /* Allocate new re. */ - re = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - - /* Type, flags, message. */ - re->type = stream_getc (s); - re->instance = stream_getw (s); - re->flags = stream_getl (s); - message = stream_getc (s); - safi = stream_getw (s); - re->uptime = time (NULL); - - /* IPv4 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = stream_getc (s); - stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen)); - - /* VRF ID */ - re->vrf_id = zvrf_id (zvrf); - - /* Nexthop parse. */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) - { - nexthop_num = stream_getc (s); - zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); - - for (i = 0; i < nexthop_num; i++) - { - nexthop_type = stream_getc (s); - - switch (nexthop_type) - { - case NEXTHOP_TYPE_IFINDEX: - ifindex = stream_getl (s); - route_entry_nexthop_ifindex_add (re, ifindex); - break; - case NEXTHOP_TYPE_IPV4: - nhop_addr.s_addr = stream_get_ipv4 (s); - nexthop = route_entry_nexthop_ipv4_add (re, &nhop_addr, NULL); - /* For labeled-unicast, each nexthop is followed by label. */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL)) - { - label = (mpls_label_t)stream_getl (s); - nexthop_add_labels (nexthop, nexthop->nh_label_type, 1, &label); - } - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - nhop_addr.s_addr = stream_get_ipv4 (s); - ifindex = stream_getl (s); - route_entry_nexthop_ipv4_ifindex_add (re, &nhop_addr, NULL, ifindex); - break; - case NEXTHOP_TYPE_IPV6: - stream_forward_getp (s, IPV6_MAX_BYTELEN); - break; - case NEXTHOP_TYPE_BLACKHOLE: - route_entry_nexthop_blackhole_add (re); - break; - } +static int zread_ipv4_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) +{ + int i; + struct route_entry *re; + struct prefix p; + u_char message; + struct in_addr nhop_addr; + u_char nexthop_num; + u_char nexthop_type; + struct stream *s; + ifindex_t ifindex; + safi_t safi; + int ret; + mpls_label_t label; + struct nexthop *nexthop; + + /* Get input stream. */ + s = client->ibuf; + + /* Allocate new re. */ + re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + + /* Type, flags, message. */ + re->type = stream_getc(s); + re->instance = stream_getw(s); + re->flags = stream_getl(s); + message = stream_getc(s); + safi = stream_getw(s); + re->uptime = time(NULL); + + /* IPv4 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = stream_getc(s); + stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen)); + + /* VRF ID */ + re->vrf_id = zvrf_id(zvrf); + + /* Nexthop parse. */ + if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) { + nexthop_num = stream_getc(s); + zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, + nexthop_num); + + for (i = 0; i < nexthop_num; i++) { + nexthop_type = stream_getc(s); + + switch (nexthop_type) { + case NEXTHOP_TYPE_IFINDEX: + ifindex = stream_getl(s); + route_entry_nexthop_ifindex_add(re, ifindex); + break; + case NEXTHOP_TYPE_IPV4: + nhop_addr.s_addr = stream_get_ipv4(s); + nexthop = route_entry_nexthop_ipv4_add( + re, &nhop_addr, NULL); + /* For labeled-unicast, each nexthop is followed + * by label. */ + if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) { + label = (mpls_label_t)stream_getl(s); + nexthop_add_labels( + nexthop, nexthop->nh_label_type, + 1, &label); + } + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + nhop_addr.s_addr = stream_get_ipv4(s); + ifindex = stream_getl(s); + route_entry_nexthop_ipv4_ifindex_add( + re, &nhop_addr, NULL, ifindex); + break; + case NEXTHOP_TYPE_IPV6: + stream_forward_getp(s, IPV6_MAX_BYTELEN); + break; + case NEXTHOP_TYPE_BLACKHOLE: + route_entry_nexthop_blackhole_add(re); + break; + } + } } - } - /* Distance. */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) - re->distance = stream_getc (s); + /* Distance. */ + if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) + re->distance = stream_getc(s); - /* Metric. */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) - re->metric = stream_getl (s); - - /* Tag */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG)) - re->tag = stream_getl (s); - else - re->tag = 0; + /* Metric. */ + if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) + re->metric = stream_getl(s); - if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU)) - re->mtu = stream_getl (s); - else - re->mtu = 0; + /* Tag */ + if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) + re->tag = stream_getl(s); + else + re->tag = 0; - /* Table */ - re->table = zvrf->table_id; + if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU)) + re->mtu = stream_getl(s); + else + re->mtu = 0; + + /* Table */ + re->table = zvrf->table_id; - ret = rib_add_multipath (AFI_IP, safi, &p, NULL, re); + ret = rib_add_multipath(AFI_IP, safi, &p, NULL, re); - /* Stats */ - if (ret > 0) - client->v4_route_add_cnt++; - else if (ret < 0) - client->v4_route_upd8_cnt++; - return 0; + /* Stats */ + if (ret > 0) + client->v4_route_add_cnt++; + else if (ret < 0) + client->v4_route_upd8_cnt++; + return 0; } /* Zebra server IPv4 prefix delete function. */ -static int -zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) -{ - int i; - struct stream *s; - struct zapi_ipv4 api; - struct in_addr nexthop; - union g_addr *nexthop_p; - unsigned long ifindex; - struct prefix p; - u_char nexthop_num; - u_char nexthop_type; - u_int32_t table_id; - - s = client->ibuf; - ifindex = 0; - nexthop.s_addr = 0; - nexthop_p = NULL; - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - api.safi = stream_getw (s); - - /* IPv4 prefix. */ - memset (&p, 0, sizeof (struct prefix)); - p.family = AF_INET; - p.prefixlen = stream_getc (s); - stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - nexthop_num = stream_getc (s); - - for (i = 0; i < nexthop_num; i++) - { - nexthop_type = stream_getc (s); - - switch (nexthop_type) - { - case NEXTHOP_TYPE_IFINDEX: - ifindex = stream_getl (s); - break; - case NEXTHOP_TYPE_IPV4: - nexthop.s_addr = stream_get_ipv4 (s); - /* For labeled-unicast, each nexthop is followed by label, but - * we don't care for delete. - */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_LABEL)) - stream_forward_getp (s, sizeof(u_int32_t)); - nexthop_p = (union g_addr *)&nexthop; - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - nexthop.s_addr = stream_get_ipv4 (s); - nexthop_p = (union g_addr *)&nexthop; - ifindex = stream_getl (s); - break; - case NEXTHOP_TYPE_IPV6: - stream_forward_getp (s, IPV6_MAX_BYTELEN); - break; - } +static int zread_ipv4_delete(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) +{ + int i; + struct stream *s; + struct zapi_ipv4 api; + struct in_addr nexthop; + union g_addr *nexthop_p; + unsigned long ifindex; + struct prefix p; + u_char nexthop_num; + u_char nexthop_type; + u_int32_t table_id; + + s = client->ibuf; + ifindex = 0; + nexthop.s_addr = 0; + nexthop_p = NULL; + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.instance = stream_getw(s); + api.flags = stream_getl(s); + api.message = stream_getc(s); + api.safi = stream_getw(s); + + /* IPv4 prefix. */ + memset(&p, 0, sizeof(struct prefix)); + p.family = AF_INET; + p.prefixlen = stream_getc(s); + stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen)); + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + nexthop_num = stream_getc(s); + + for (i = 0; i < nexthop_num; i++) { + nexthop_type = stream_getc(s); + + switch (nexthop_type) { + case NEXTHOP_TYPE_IFINDEX: + ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IPV4: + nexthop.s_addr = stream_get_ipv4(s); + /* For labeled-unicast, each nexthop is followed + * by label, but + * we don't care for delete. + */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL)) + stream_forward_getp(s, + sizeof(u_int32_t)); + nexthop_p = (union g_addr *)&nexthop; + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + nexthop.s_addr = stream_get_ipv4(s); + nexthop_p = (union g_addr *)&nexthop; + ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IPV6: + stream_forward_getp(s, IPV6_MAX_BYTELEN); + break; + } + } } - } - - /* Distance. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - else - api.distance = 0; - - /* Metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - /* tag */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl (s); - else - api.tag = 0; - - table_id = zvrf->table_id; - - rib_delete (AFI_IP, api.safi, zvrf_id (zvrf), api.type, api.instance, - api.flags, &p, NULL, nexthop_p, ifindex, table_id); - client->v4_route_del_cnt++; - return 0; + + /* Distance. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + else + api.distance = 0; + + /* Metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + else + api.metric = 0; + + /* tag */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getl(s); + else + api.tag = 0; + + table_id = zvrf->table_id; + + rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance, + api.flags, &p, NULL, nexthop_p, ifindex, table_id); + client->v4_route_del_cnt++; + return 0; } /* MRIB Nexthop lookup for IPv4. */ -static int -zread_ipv4_nexthop_lookup_mrib (struct zserv *client, u_short length, struct zebra_vrf *zvrf) +static int zread_ipv4_nexthop_lookup_mrib(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { - struct in_addr addr; - struct route_entry *re; + struct in_addr addr; + struct route_entry *re; - addr.s_addr = stream_get_ipv4 (client->ibuf); - re = rib_match_ipv4_multicast (zvrf_id (zvrf), addr, NULL); - return zsend_ipv4_nexthop_lookup_mrib (client, addr, re, zvrf); + addr.s_addr = stream_get_ipv4(client->ibuf); + re = rib_match_ipv4_multicast(zvrf_id(zvrf), addr, NULL); + return zsend_ipv4_nexthop_lookup_mrib(client, addr, re, zvrf); } /* Zebra server IPv6 prefix add function. */ -static int -zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) -{ - unsigned int i; - struct stream *s; - struct in6_addr nhop_addr; - struct route_entry *re; - u_char message; - u_char nexthop_num; - u_char nexthop_type; - struct prefix p; - safi_t safi; - static struct in6_addr nexthops[MULTIPATH_NUM]; - static unsigned int ifindices[MULTIPATH_NUM]; - int ret; - static mpls_label_t labels[MULTIPATH_NUM]; - mpls_label_t label; - struct nexthop *nexthop; - - /* Get input stream. */ - s = client->ibuf; - - memset (&nhop_addr, 0, sizeof (struct in6_addr)); - - /* Allocate new re. */ - re = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - - /* Type, flags, message. */ - re->type = stream_getc (s); - re->instance = stream_getw (s); - re->flags = stream_getl (s); - message = stream_getc (s); - safi = stream_getw (s); - re->uptime = time (NULL); - - /* IPv4 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = stream_getc (s); - stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen)); - - /* VRF ID */ - re->vrf_id = zvrf_id (zvrf); - - /* We need to give nh-addr, nh-ifindex with the same next-hop object - * to the re to ensure that IPv6 multipathing works; need to coalesce - * these. Clients should send the same number of paired set of - * next-hop-addr/next-hop-ifindices. */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) - { - unsigned int nh_count = 0; - unsigned int if_count = 0; - unsigned int max_nh_if = 0; - - nexthop_num = stream_getc (s); - zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); - for (i = 0; i < nexthop_num; i++) - { - nexthop_type = stream_getc (s); - - switch (nexthop_type) - { - case NEXTHOP_TYPE_IPV6: - stream_get (&nhop_addr, s, 16); - if (nh_count < MULTIPATH_NUM) - { - /* For labeled-unicast, each nexthop is followed by label. */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL)) - { - label = (mpls_label_t)stream_getl (s); - labels[nh_count] = label; - } - nexthops[nh_count] = nhop_addr; - nh_count++; - } - break; - case NEXTHOP_TYPE_IFINDEX: - if (if_count < multipath_num) { - ifindices[if_count++] = stream_getl (s); - } - break; - case NEXTHOP_TYPE_BLACKHOLE: - route_entry_nexthop_blackhole_add (re); - break; - } +static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, + u_short length, + struct zebra_vrf *zvrf) +{ + unsigned int i; + struct stream *s; + struct in6_addr nhop_addr; + struct route_entry *re; + u_char message; + u_char nexthop_num; + u_char nexthop_type; + struct prefix p; + safi_t safi; + static struct in6_addr nexthops[MULTIPATH_NUM]; + static unsigned int ifindices[MULTIPATH_NUM]; + int ret; + static mpls_label_t labels[MULTIPATH_NUM]; + mpls_label_t label; + struct nexthop *nexthop; + + /* Get input stream. */ + s = client->ibuf; + + memset(&nhop_addr, 0, sizeof(struct in6_addr)); + + /* Allocate new re. */ + re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + + /* Type, flags, message. */ + re->type = stream_getc(s); + re->instance = stream_getw(s); + re->flags = stream_getl(s); + message = stream_getc(s); + safi = stream_getw(s); + re->uptime = time(NULL); + + /* IPv4 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = stream_getc(s); + stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen)); + + /* VRF ID */ + re->vrf_id = zvrf_id(zvrf); + + /* We need to give nh-addr, nh-ifindex with the same next-hop object + * to the re to ensure that IPv6 multipathing works; need to coalesce + * these. Clients should send the same number of paired set of + * next-hop-addr/next-hop-ifindices. */ + if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) { + unsigned int nh_count = 0; + unsigned int if_count = 0; + unsigned int max_nh_if = 0; + + nexthop_num = stream_getc(s); + zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, + nexthop_num); + for (i = 0; i < nexthop_num; i++) { + nexthop_type = stream_getc(s); + + switch (nexthop_type) { + case NEXTHOP_TYPE_IPV6: + stream_get(&nhop_addr, s, 16); + if (nh_count < MULTIPATH_NUM) { + /* For labeled-unicast, each nexthop is + * followed by label. */ + if (CHECK_FLAG(message, + ZAPI_MESSAGE_LABEL)) { + label = (mpls_label_t) + stream_getl(s); + labels[nh_count] = label; + } + nexthops[nh_count] = nhop_addr; + nh_count++; + } + break; + case NEXTHOP_TYPE_IFINDEX: + if (if_count < multipath_num) { + ifindices[if_count++] = stream_getl(s); + } + break; + case NEXTHOP_TYPE_BLACKHOLE: + route_entry_nexthop_blackhole_add(re); + break; + } + } + + max_nh_if = (nh_count > if_count) ? nh_count : if_count; + for (i = 0; i < max_nh_if; i++) { + if ((i < nh_count) + && !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) { + if ((i < if_count) && ifindices[i]) + nexthop = + route_entry_nexthop_ipv6_ifindex_add( + re, &nexthops[i], + ifindices[i]); + else + nexthop = route_entry_nexthop_ipv6_add( + re, &nexthops[i]); + + if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) + nexthop_add_labels( + nexthop, nexthop->nh_label_type, + 1, &labels[i]); + } else { + if ((i < if_count) && ifindices[i]) + route_entry_nexthop_ifindex_add( + re, ifindices[i]); + } + } } - max_nh_if = (nh_count > if_count) ? nh_count : if_count; - for (i = 0; i < max_nh_if; i++) - { - if ((i < nh_count) && !IN6_IS_ADDR_UNSPECIFIED (&nexthops[i])) { - if ((i < if_count) && ifindices[i]) - nexthop = route_entry_nexthop_ipv6_ifindex_add (re, &nexthops[i], ifindices[i]); - else - nexthop = route_entry_nexthop_ipv6_add (re, &nexthops[i]); - - if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL)) - nexthop_add_labels (nexthop, nexthop->nh_label_type, 1, &labels[i]); - } - else { - if ((i < if_count) && ifindices[i]) - route_entry_nexthop_ifindex_add (re, ifindices[i]); - } - } - } - - /* Distance. */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) - re->distance = stream_getc (s); - - /* Metric. */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) - re->metric = stream_getl (s); - - /* Tag */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG)) - re->tag = stream_getl (s); - else - re->tag = 0; - - if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU)) - re->mtu = stream_getl (s); - else - re->mtu = 0; - - /* Table */ - re->table = zvrf->table_id; - - ret = rib_add_multipath (AFI_IP6, safi, &p, NULL, re); - /* Stats */ - if (ret > 0) - client->v4_route_add_cnt++; - else if (ret < 0) - client->v4_route_upd8_cnt++; - - return 0; -} - -static int -zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) -{ - unsigned int i; - struct stream *s; - struct in6_addr nhop_addr; - struct route_entry *re; - u_char message; - u_char nexthop_num; - u_char nexthop_type; - struct prefix p; - struct prefix_ipv6 src_p, *src_pp; - safi_t safi; - static struct in6_addr nexthops[MULTIPATH_NUM]; - static unsigned int ifindices[MULTIPATH_NUM]; - int ret; - static mpls_label_t labels[MULTIPATH_NUM]; - mpls_label_t label; - struct nexthop *nexthop; - - /* Get input stream. */ - s = client->ibuf; - - memset (&nhop_addr, 0, sizeof (struct in6_addr)); - - /* Allocate new re. */ - re = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - - /* Type, flags, message. */ - re->type = stream_getc (s); - re->instance = stream_getw (s); - re->flags = stream_getl (s); - message = stream_getc (s); - safi = stream_getw (s); - re->uptime = time (NULL); - - /* IPv6 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = stream_getc (s); - stream_get (&p.u.prefix6, s, PSIZE (p.prefixlen)); - - if (CHECK_FLAG (message, ZAPI_MESSAGE_SRCPFX)) - { - memset (&src_p, 0, sizeof (struct prefix_ipv6)); - src_p.family = AF_INET6; - src_p.prefixlen = stream_getc (s); - stream_get (&src_p.prefix, s, PSIZE (src_p.prefixlen)); - src_pp = &src_p; - } - else - src_pp = NULL; - - /* We need to give nh-addr, nh-ifindex with the same next-hop object - * to the re to ensure that IPv6 multipathing works; need to coalesce - * these. Clients should send the same number of paired set of - * next-hop-addr/next-hop-ifindices. */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) - { - unsigned int nh_count = 0; - unsigned int if_count = 0; - unsigned int max_nh_if = 0; - - nexthop_num = stream_getc (s); - zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); - for (i = 0; i < nexthop_num; i++) - { - nexthop_type = stream_getc (s); - - switch (nexthop_type) - { - case NEXTHOP_TYPE_IPV6: - stream_get (&nhop_addr, s, 16); - if (nh_count < MULTIPATH_NUM) - { - /* For labeled-unicast, each nexthop is followed by label. */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL)) - { - label = (mpls_label_t)stream_getl (s); - labels[nh_count] = label; - } - nexthops[nh_count++] = nhop_addr; - } - break; - case NEXTHOP_TYPE_IFINDEX: - if (if_count < multipath_num) { - ifindices[if_count++] = stream_getl (s); - } - break; - case NEXTHOP_TYPE_BLACKHOLE: - route_entry_nexthop_blackhole_add (re); - break; - } - } + /* Distance. */ + if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) + re->distance = stream_getc(s); - max_nh_if = (nh_count > if_count) ? nh_count : if_count; - for (i = 0; i < max_nh_if; i++) - { - if ((i < nh_count) && !IN6_IS_ADDR_UNSPECIFIED (&nexthops[i])) { - if ((i < if_count) && ifindices[i]) - nexthop = route_entry_nexthop_ipv6_ifindex_add (re, &nexthops[i], ifindices[i]); - else - nexthop = route_entry_nexthop_ipv6_add (re, &nexthops[i]); - if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL)) - nexthop_add_labels (nexthop, nexthop->nh_label_type, 1, &labels[i]); - } - else { - if ((i < if_count) && ifindices[i]) - route_entry_nexthop_ifindex_add (re, ifindices[i]); - } + /* Metric. */ + if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) + re->metric = stream_getl(s); + + /* Tag */ + if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) + re->tag = stream_getl(s); + else + re->tag = 0; + + if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU)) + re->mtu = stream_getl(s); + else + re->mtu = 0; + + /* Table */ + re->table = zvrf->table_id; + + ret = rib_add_multipath(AFI_IP6, safi, &p, NULL, re); + /* Stats */ + if (ret > 0) + client->v4_route_add_cnt++; + else if (ret < 0) + client->v4_route_upd8_cnt++; + + return 0; +} + +static int zread_ipv6_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) +{ + unsigned int i; + struct stream *s; + struct in6_addr nhop_addr; + struct route_entry *re; + u_char message; + u_char nexthop_num; + u_char nexthop_type; + struct prefix p; + struct prefix_ipv6 src_p, *src_pp; + safi_t safi; + static struct in6_addr nexthops[MULTIPATH_NUM]; + static unsigned int ifindices[MULTIPATH_NUM]; + int ret; + static mpls_label_t labels[MULTIPATH_NUM]; + mpls_label_t label; + struct nexthop *nexthop; + + /* Get input stream. */ + s = client->ibuf; + + memset(&nhop_addr, 0, sizeof(struct in6_addr)); + + /* Allocate new re. */ + re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + + /* Type, flags, message. */ + re->type = stream_getc(s); + re->instance = stream_getw(s); + re->flags = stream_getl(s); + message = stream_getc(s); + safi = stream_getw(s); + re->uptime = time(NULL); + + /* IPv6 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + p.prefixlen = stream_getc(s); + stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen)); + + if (CHECK_FLAG(message, ZAPI_MESSAGE_SRCPFX)) { + memset(&src_p, 0, sizeof(struct prefix_ipv6)); + src_p.family = AF_INET6; + src_p.prefixlen = stream_getc(s); + stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); + src_pp = &src_p; + } else + src_pp = NULL; + + /* We need to give nh-addr, nh-ifindex with the same next-hop object + * to the re to ensure that IPv6 multipathing works; need to coalesce + * these. Clients should send the same number of paired set of + * next-hop-addr/next-hop-ifindices. */ + if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) { + unsigned int nh_count = 0; + unsigned int if_count = 0; + unsigned int max_nh_if = 0; + + nexthop_num = stream_getc(s); + zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, + nexthop_num); + for (i = 0; i < nexthop_num; i++) { + nexthop_type = stream_getc(s); + + switch (nexthop_type) { + case NEXTHOP_TYPE_IPV6: + stream_get(&nhop_addr, s, 16); + if (nh_count < MULTIPATH_NUM) { + /* For labeled-unicast, each nexthop is + * followed by label. */ + if (CHECK_FLAG(message, + ZAPI_MESSAGE_LABEL)) { + label = (mpls_label_t) + stream_getl(s); + labels[nh_count] = label; + } + nexthops[nh_count++] = nhop_addr; + } + break; + case NEXTHOP_TYPE_IFINDEX: + if (if_count < multipath_num) { + ifindices[if_count++] = stream_getl(s); + } + break; + case NEXTHOP_TYPE_BLACKHOLE: + route_entry_nexthop_blackhole_add(re); + break; + } + } + + max_nh_if = (nh_count > if_count) ? nh_count : if_count; + for (i = 0; i < max_nh_if; i++) { + if ((i < nh_count) + && !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) { + if ((i < if_count) && ifindices[i]) + nexthop = + route_entry_nexthop_ipv6_ifindex_add( + re, &nexthops[i], + ifindices[i]); + else + nexthop = route_entry_nexthop_ipv6_add( + re, &nexthops[i]); + if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) + nexthop_add_labels( + nexthop, nexthop->nh_label_type, + 1, &labels[i]); + } else { + if ((i < if_count) && ifindices[i]) + route_entry_nexthop_ifindex_add( + re, ifindices[i]); + } + } } - } - /* Distance. */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) - re->distance = stream_getc (s); + /* Distance. */ + if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) + re->distance = stream_getc(s); + + /* Metric. */ + if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) + re->metric = stream_getl(s); - /* Metric. */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) - re->metric = stream_getl (s); - - /* Tag */ - if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG)) - re->tag = stream_getl (s); - else - re->tag = 0; + /* Tag */ + if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) + re->tag = stream_getl(s); + else + re->tag = 0; - if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU)) - re->mtu = stream_getl (s); - else - re->mtu = 0; + if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU)) + re->mtu = stream_getl(s); + else + re->mtu = 0; - /* VRF ID */ - re->vrf_id = zvrf_id (zvrf); - re->table = zvrf->table_id; + /* VRF ID */ + re->vrf_id = zvrf_id(zvrf); + re->table = zvrf->table_id; - ret = rib_add_multipath (AFI_IP6, safi, &p, src_pp, re); - /* Stats */ - if (ret > 0) - client->v6_route_add_cnt++; - else if (ret < 0) - client->v6_route_upd8_cnt++; + ret = rib_add_multipath(AFI_IP6, safi, &p, src_pp, re); + /* Stats */ + if (ret > 0) + client->v6_route_add_cnt++; + else if (ret < 0) + client->v6_route_upd8_cnt++; - return 0; + return 0; } /* Zebra server IPv6 prefix delete function. */ -static int -zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) -{ - int i; - struct stream *s; - struct zapi_ipv6 api; - struct in6_addr nexthop; - union g_addr *pnexthop = NULL; - unsigned long ifindex; - struct prefix p; - struct prefix_ipv6 src_p, *src_pp; - - s = client->ibuf; - ifindex = 0; - memset (&nexthop, 0, sizeof (struct in6_addr)); - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - api.safi = stream_getw (s); - - /* IPv4 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = stream_getc (s); - stream_get (&p.u.prefix6, s, PSIZE (p.prefixlen)); - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_SRCPFX)) - { - memset (&src_p, 0, sizeof (struct prefix_ipv6)); - src_p.family = AF_INET6; - src_p.prefixlen = stream_getc (s); - stream_get (&src_p.prefix, s, PSIZE (src_p.prefixlen)); - src_pp = &src_p; - } - else - src_pp = NULL; - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - u_char nexthop_type; - - api.nexthop_num = stream_getc (s); - for (i = 0; i < api.nexthop_num; i++) - { - nexthop_type = stream_getc (s); - - switch (nexthop_type) - { - case NEXTHOP_TYPE_IPV6: - stream_get (&nexthop, s, 16); - /* For labeled-unicast, each nexthop is followed by label, but - * we don't care for delete. - */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_LABEL)) - stream_forward_getp (s, sizeof(u_int32_t)); - pnexthop = (union g_addr *)&nexthop; - break; - case NEXTHOP_TYPE_IFINDEX: - ifindex = stream_getl (s); - break; - } +static int zread_ipv6_delete(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) +{ + int i; + struct stream *s; + struct zapi_ipv6 api; + struct in6_addr nexthop; + union g_addr *pnexthop = NULL; + unsigned long ifindex; + struct prefix p; + struct prefix_ipv6 src_p, *src_pp; + + s = client->ibuf; + ifindex = 0; + memset(&nexthop, 0, sizeof(struct in6_addr)); + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.instance = stream_getw(s); + api.flags = stream_getl(s); + api.message = stream_getc(s); + api.safi = stream_getw(s); + + /* IPv4 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + p.prefixlen = stream_getc(s); + stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen)); + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { + memset(&src_p, 0, sizeof(struct prefix_ipv6)); + src_p.family = AF_INET6; + src_p.prefixlen = stream_getc(s); + stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); + src_pp = &src_p; + } else + src_pp = NULL; + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + u_char nexthop_type; + + api.nexthop_num = stream_getc(s); + for (i = 0; i < api.nexthop_num; i++) { + nexthop_type = stream_getc(s); + + switch (nexthop_type) { + case NEXTHOP_TYPE_IPV6: + stream_get(&nexthop, s, 16); + /* For labeled-unicast, each nexthop is followed + * by label, but + * we don't care for delete. + */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL)) + stream_forward_getp(s, + sizeof(u_int32_t)); + pnexthop = (union g_addr *)&nexthop; + break; + case NEXTHOP_TYPE_IFINDEX: + ifindex = stream_getl(s); + break; + } + } } - } - - /* Distance. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - else - api.distance = 0; - - /* Metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - /* tag */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl (s); - else - api.tag = 0; - - if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) - rib_delete (AFI_IP6, api.safi, zvrf_id (zvrf), api.type, api.instance, - api.flags, &p, src_pp, NULL, ifindex, client->rtm_table); - else - rib_delete (AFI_IP6, api.safi, zvrf_id (zvrf), api.type, api.instance, - api.flags, &p, src_pp, pnexthop, ifindex, client->rtm_table); - - client->v6_route_del_cnt++; - return 0; + + /* Distance. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + else + api.distance = 0; + + /* Metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + else + api.metric = 0; + + /* tag */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getl(s); + else + api.tag = 0; + + if (IN6_IS_ADDR_UNSPECIFIED(&nexthop)) + rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, + api.instance, api.flags, &p, src_pp, NULL, ifindex, + client->rtm_table); + else + rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, + api.instance, api.flags, &p, src_pp, pnexthop, + ifindex, client->rtm_table); + + client->v6_route_del_cnt++; + return 0; } /* Register zebra server router-id information. Send current router-id */ -static int -zread_router_id_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) +static int zread_router_id_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { - struct prefix p; + struct prefix p; - /* Router-id information is needed. */ - vrf_bitmap_set (client->ridinfo, zvrf_id (zvrf)); + /* Router-id information is needed. */ + vrf_bitmap_set(client->ridinfo, zvrf_id(zvrf)); - router_id_get (&p, zvrf_id (zvrf)); + router_id_get(&p, zvrf_id(zvrf)); - return zsend_router_id_update (client, &p, zvrf_id (zvrf)); + return zsend_router_id_update(client, &p, zvrf_id(zvrf)); } /* Unregister zebra server router-id information. */ -static int -zread_router_id_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) +static int zread_router_id_delete(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { - vrf_bitmap_unset (client->ridinfo, zvrf_id (zvrf)); - return 0; + vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf)); + return 0; } /* Tie up route-type and client->sock */ -static void -zread_hello (struct zserv *client) +static void zread_hello(struct zserv *client) { - /* type of protocol (lib/zebra.h) */ - u_char proto; - u_short instance; + /* type of protocol (lib/zebra.h) */ + u_char proto; + u_short instance; - proto = stream_getc (client->ibuf); - instance = stream_getw (client->ibuf); + proto = stream_getc(client->ibuf); + instance = stream_getw(client->ibuf); - /* accept only dynamic routing protocols */ - if ((proto < ZEBRA_ROUTE_MAX) - && (proto > ZEBRA_ROUTE_STATIC)) - { - zlog_notice ("client %d says hello and bids fair to announce only %s routes", - client->sock, zebra_route_string(proto)); - if (instance) - zlog_notice ("client protocol instance %d", instance); + /* accept only dynamic routing protocols */ + if ((proto < ZEBRA_ROUTE_MAX) && (proto > ZEBRA_ROUTE_STATIC)) { + zlog_notice( + "client %d says hello and bids fair to announce only %s routes", + client->sock, zebra_route_string(proto)); + if (instance) + zlog_notice("client protocol instance %d", instance); - client->proto = proto; - client->instance = instance; - } + client->proto = proto; + client->instance = instance; + } } /* Unregister all information in a VRF. */ -static int -zread_vrf_unregister (struct zserv *client, u_short length, struct zebra_vrf *zvrf) -{ - int i; - afi_t afi; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - vrf_bitmap_unset (client->redist[afi][i], zvrf_id (zvrf)); - vrf_bitmap_unset (client->redist_default, zvrf_id (zvrf)); - vrf_bitmap_unset (client->ifinfo, zvrf_id (zvrf)); - vrf_bitmap_unset (client->ridinfo, zvrf_id (zvrf)); - - return 0; -} - -static void -zread_mpls_labels (int command, struct zserv *client, u_short length, - vrf_id_t vrf_id) -{ - struct stream *s; - enum lsp_types_t type; - struct prefix prefix; - enum nexthop_types_t gtype; - union g_addr gate; - ifindex_t ifindex; - mpls_label_t in_label, out_label; - u_int8_t distance; - struct zebra_vrf *zvrf; - - zvrf = vrf_info_lookup (vrf_id); - if (!zvrf) - return; - - /* Get input stream. */ - s = client->ibuf; - - /* Get data. */ - type = stream_getc (s); - prefix.family = stream_getl (s); - switch (prefix.family) - { - case AF_INET: - prefix.u.prefix4.s_addr = stream_get_ipv4 (s); - prefix.prefixlen = stream_getc (s); - gate.ipv4.s_addr = stream_get_ipv4 (s); - break; - case AF_INET6: - stream_get (&prefix.u.prefix6, s, 16); - prefix.prefixlen = stream_getc (s); - stream_get (&gate.ipv6, s, 16); - break; - default: - return; - } - ifindex = stream_getl (s); - distance = stream_getc (s); - in_label = stream_getl (s); - out_label = stream_getl (s); - - switch (prefix.family) - { - case AF_INET: - if (ifindex) - gtype = NEXTHOP_TYPE_IPV4_IFINDEX; - else - gtype = NEXTHOP_TYPE_IPV4; - break; - case AF_INET6: - if (ifindex) - gtype = NEXTHOP_TYPE_IPV6_IFINDEX; - else - gtype = NEXTHOP_TYPE_IPV6; - break; - default: - return; - } - - if (! mpls_enabled) - return; - - if (command == ZEBRA_MPLS_LABELS_ADD) - { - mpls_lsp_install (zvrf, type, in_label, out_label, gtype, &gate, - ifindex); - if (out_label != MPLS_IMP_NULL_LABEL) - mpls_ftn_update (1, zvrf, type, &prefix, gtype, &gate, ifindex, - distance, out_label); - } - else if (command == ZEBRA_MPLS_LABELS_DELETE) - { - mpls_lsp_uninstall (zvrf, type, in_label, gtype, &gate, ifindex); - if (out_label != MPLS_IMP_NULL_LABEL) - mpls_ftn_update (0, zvrf, type, &prefix, gtype, &gate, ifindex, - distance, out_label); - } +static int zread_vrf_unregister(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) +{ + int i; + afi_t afi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf)); + vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf)); + vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf)); + vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf)); + + return 0; +} + +static void zread_mpls_labels(int command, struct zserv *client, u_short length, + vrf_id_t vrf_id) +{ + struct stream *s; + enum lsp_types_t type; + struct prefix prefix; + enum nexthop_types_t gtype; + union g_addr gate; + ifindex_t ifindex; + mpls_label_t in_label, out_label; + u_int8_t distance; + struct zebra_vrf *zvrf; + + zvrf = vrf_info_lookup(vrf_id); + if (!zvrf) + return; + + /* Get input stream. */ + s = client->ibuf; + + /* Get data. */ + type = stream_getc(s); + prefix.family = stream_getl(s); + switch (prefix.family) { + case AF_INET: + prefix.u.prefix4.s_addr = stream_get_ipv4(s); + prefix.prefixlen = stream_getc(s); + gate.ipv4.s_addr = stream_get_ipv4(s); + break; + case AF_INET6: + stream_get(&prefix.u.prefix6, s, 16); + prefix.prefixlen = stream_getc(s); + stream_get(&gate.ipv6, s, 16); + break; + default: + return; + } + ifindex = stream_getl(s); + distance = stream_getc(s); + in_label = stream_getl(s); + out_label = stream_getl(s); + + switch (prefix.family) { + case AF_INET: + if (ifindex) + gtype = NEXTHOP_TYPE_IPV4_IFINDEX; + else + gtype = NEXTHOP_TYPE_IPV4; + break; + case AF_INET6: + if (ifindex) + gtype = NEXTHOP_TYPE_IPV6_IFINDEX; + else + gtype = NEXTHOP_TYPE_IPV6; + break; + default: + return; + } + + if (!mpls_enabled) + return; + + if (command == ZEBRA_MPLS_LABELS_ADD) { + mpls_lsp_install(zvrf, type, in_label, out_label, gtype, &gate, + ifindex); + if (out_label != MPLS_IMP_NULL_LABEL) + mpls_ftn_update(1, zvrf, type, &prefix, gtype, &gate, + ifindex, distance, out_label); + } else if (command == ZEBRA_MPLS_LABELS_DELETE) { + mpls_lsp_uninstall(zvrf, type, in_label, gtype, &gate, ifindex); + if (out_label != MPLS_IMP_NULL_LABEL) + mpls_ftn_update(0, zvrf, type, &prefix, gtype, &gate, + ifindex, distance, out_label); + } } /* Send response to a label manager connect request to client */ -static int -zsend_label_manager_connect_response (struct zserv *client, vrf_id_t vrf_id, u_short result) +static int zsend_label_manager_connect_response(struct zserv *client, + vrf_id_t vrf_id, u_short result) { - struct stream *s; + struct stream *s; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id); + zserv_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id); - /* result */ - stream_putc (s, result); + /* result */ + stream_putc(s, result); - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - return writen (client->sock, s->data, stream_get_endp (s)); + return writen(client->sock, s->data, stream_get_endp(s)); } -static void -zread_label_manager_connect (struct zserv *client, vrf_id_t vrf_id) +static void zread_label_manager_connect(struct zserv *client, vrf_id_t vrf_id) { - struct stream *s; - /* type of protocol (lib/zebra.h) */ - u_char proto; - u_short instance; + struct stream *s; + /* type of protocol (lib/zebra.h) */ + u_char proto; + u_short instance; - /* Get input stream. */ - s = client->ibuf; + /* Get input stream. */ + s = client->ibuf; - /* Get data. */ - proto = stream_getc (s); - instance = stream_getw (s); + /* Get data. */ + proto = stream_getc(s); + instance = stream_getw(s); - /* accept only dynamic routing protocols */ - if ((proto >= ZEBRA_ROUTE_MAX) - || (proto <= ZEBRA_ROUTE_STATIC)) - { - zlog_err ("client %d has wrong protocol %s", - client->sock, zebra_route_string(proto)); - zsend_label_manager_connect_response (client, vrf_id, 1); - return; - } - zlog_notice ("client %d with instance %u connected as %s", - client->sock, instance, zebra_route_string(proto)); - client->proto = proto; - client->instance = instance; - - /* - Release previous labels of same protocol and instance. - This is done in case it restarted from an unexpected shutdown. - */ - release_daemon_chunks (proto, instance); - - zlog_debug (" Label Manager client connected: sock %d, proto %s, instance %u", - client->sock, zebra_route_string(proto), instance); - /* send response back */ - zsend_label_manager_connect_response (client, vrf_id, 0); + /* accept only dynamic routing protocols */ + if ((proto >= ZEBRA_ROUTE_MAX) || (proto <= ZEBRA_ROUTE_STATIC)) { + zlog_err("client %d has wrong protocol %s", client->sock, + zebra_route_string(proto)); + zsend_label_manager_connect_response(client, vrf_id, 1); + return; + } + zlog_notice("client %d with instance %u connected as %s", client->sock, + instance, zebra_route_string(proto)); + client->proto = proto; + client->instance = instance; + + /* + Release previous labels of same protocol and instance. + This is done in case it restarted from an unexpected shutdown. + */ + release_daemon_chunks(proto, instance); + + zlog_debug( + " Label Manager client connected: sock %d, proto %s, instance %u", + client->sock, zebra_route_string(proto), instance); + /* send response back */ + zsend_label_manager_connect_response(client, vrf_id, 0); } /* Send response to a get label chunk request to client */ -static int -zsend_assign_label_chunk_response (struct zserv *client, vrf_id_t vrf_id, - struct label_manager_chunk *lmc) +static int zsend_assign_label_chunk_response(struct zserv *client, + vrf_id_t vrf_id, + struct label_manager_chunk *lmc) { - struct stream *s; - - s = client->obuf; - stream_reset (s); + struct stream *s; - zserv_create_header (s, ZEBRA_GET_LABEL_CHUNK, vrf_id); + s = client->obuf; + stream_reset(s); - if (lmc) - { - /* keep */ - stream_putc (s, lmc->keep); - /* start and end labels */ - stream_putl (s, lmc->start); - stream_putl (s, lmc->end); + zserv_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id); - } + if (lmc) { + /* keep */ + stream_putc(s, lmc->keep); + /* start and end labels */ + stream_putl(s, lmc->start); + stream_putl(s, lmc->end); + } - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - return writen (client->sock, s->data, stream_get_endp (s)); + return writen(client->sock, s->data, stream_get_endp(s)); } -static void -zread_get_label_chunk (struct zserv *client, vrf_id_t vrf_id) +static void zread_get_label_chunk(struct zserv *client, vrf_id_t vrf_id) { - struct stream *s; - u_char keep; - uint32_t size; - struct label_manager_chunk *lmc; + struct stream *s; + u_char keep; + uint32_t size; + struct label_manager_chunk *lmc; - /* Get input stream. */ - s = client->ibuf; + /* Get input stream. */ + s = client->ibuf; - /* Get data. */ - keep = stream_getc (s); - size = stream_getl (s); + /* Get data. */ + keep = stream_getc(s); + size = stream_getl(s); - lmc = assign_label_chunk (client->proto, client->instance, keep, size); - if (!lmc) - zlog_err ("%s: Unable to assign Label Chunk of size %u", __func__, size); - else - zlog_debug ("Assigned Label Chunk %u - %u to %u", - lmc->start, lmc->end, keep); - /* send response back */ - zsend_assign_label_chunk_response (client, vrf_id, lmc); + lmc = assign_label_chunk(client->proto, client->instance, keep, size); + if (!lmc) + zlog_err("%s: Unable to assign Label Chunk of size %u", + __func__, size); + else + zlog_debug("Assigned Label Chunk %u - %u to %u", lmc->start, + lmc->end, keep); + /* send response back */ + zsend_assign_label_chunk_response(client, vrf_id, lmc); +} + +static void zread_release_label_chunk(struct zserv *client) +{ + struct stream *s; + uint32_t start, end; + + /* Get input stream. */ + s = client->ibuf; + + /* Get data. */ + start = stream_getl(s); + end = stream_getl(s); + + release_label_chunk(client->proto, client->instance, start, end); +} +static void zread_label_manager_request(int cmd, struct zserv *client, + vrf_id_t vrf_id) +{ + /* to avoid sending other messages like ZERBA_INTERFACE_UP */ + if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) + client->is_synchronous = 1; + + /* external label manager */ + if (lm_is_external) + zread_relay_label_manager_request(cmd, client, vrf_id); + /* this is a label manager */ + else { + if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) + zread_label_manager_connect(client, vrf_id); + else { + /* Sanity: don't allow 'unidentified' requests */ + if (!client->proto) { + zlog_err( + "Got label request from an unidentified client"); + return; + } + if (cmd == ZEBRA_GET_LABEL_CHUNK) + zread_get_label_chunk(client, vrf_id); + else if (cmd == ZEBRA_RELEASE_LABEL_CHUNK) + zread_release_label_chunk(client); + } + } } -static void -zread_release_label_chunk (struct zserv *client) +/* Cleanup registered nexthops (across VRFs) upon client disconnect. */ +static void zebra_client_close_cleanup_rnh(struct zserv *client) { - struct stream *s; - uint32_t start, end; - - /* Get input stream. */ - s = client->ibuf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - /* Get data. */ - start = stream_getl (s); - end = stream_getl (s); - - release_label_chunk (client->proto, client->instance, start, end); + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + { + if ((zvrf = vrf->info) != NULL) { + zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET, client, + RNH_NEXTHOP_TYPE); + zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET6, + client, RNH_NEXTHOP_TYPE); + zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET, client, + RNH_IMPORT_CHECK_TYPE); + zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET6, + client, RNH_IMPORT_CHECK_TYPE); + if (client->proto == ZEBRA_ROUTE_LDP) { + hash_iterate(zvrf->lsp_table, + mpls_ldp_lsp_uninstall_all, + zvrf->lsp_table); + mpls_ldp_ftn_uninstall_all(zvrf, AFI_IP); + mpls_ldp_ftn_uninstall_all(zvrf, AFI_IP6); + } + } + } } -static void -zread_label_manager_request (int cmd, struct zserv *client, vrf_id_t vrf_id) + +/* Close zebra client. */ +static void zebra_client_close(struct zserv *client) { - /* to avoid sending other messages like ZERBA_INTERFACE_UP */ - if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) - client->is_synchronous = 1; + /* Send client de-registration to BFD */ + zebra_ptm_bfd_client_deregister(client->proto); - /* external label manager */ - if (lm_is_external) - zread_relay_label_manager_request (cmd, client, vrf_id); - /* this is a label manager */ - else - { - if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) - zread_label_manager_connect (client, vrf_id); - else - { - /* Sanity: don't allow 'unidentified' requests */ - if (!client->proto) - { - zlog_err ("Got label request from an unidentified client"); - return; - } - if (cmd == ZEBRA_GET_LABEL_CHUNK) - zread_get_label_chunk (client, vrf_id); - else if (cmd == ZEBRA_RELEASE_LABEL_CHUNK) - zread_release_label_chunk (client); - } - } -} + /* Cleanup any registered nexthops - across all VRFs. */ + zebra_client_close_cleanup_rnh(client); -/* Cleanup registered nexthops (across VRFs) upon client disconnect. */ -static void -zebra_client_close_cleanup_rnh (struct zserv *client) -{ - struct vrf *vrf; - struct zebra_vrf *zvrf; - - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - { - if ((zvrf = vrf->info) != NULL) - { - zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET, client, RNH_NEXTHOP_TYPE); - zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET6, client, RNH_NEXTHOP_TYPE); - zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET, client, RNH_IMPORT_CHECK_TYPE); - zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET6, client, RNH_IMPORT_CHECK_TYPE); - if (client->proto == ZEBRA_ROUTE_LDP) - { - hash_iterate(zvrf->lsp_table, mpls_ldp_lsp_uninstall_all, - zvrf->lsp_table); - mpls_ldp_ftn_uninstall_all (zvrf, AFI_IP); - mpls_ldp_ftn_uninstall_all (zvrf, AFI_IP6); - } - } - } -} + /* Release Label Manager chunks */ + release_daemon_chunks(client->proto, client->instance); -/* Close zebra client. */ -static void -zebra_client_close (struct zserv *client) -{ - /* Send client de-registration to BFD */ - zebra_ptm_bfd_client_deregister(client->proto); - - /* Cleanup any registered nexthops - across all VRFs. */ - zebra_client_close_cleanup_rnh (client); - - /* Release Label Manager chunks */ - release_daemon_chunks (client->proto, client->instance); - - /* Cleanup any FECs registered by this client. */ - zebra_mpls_cleanup_fecs_for_client (vrf_info_lookup(VRF_DEFAULT), client); - - /* Close file descriptor. */ - if (client->sock) - { - unsigned long nroutes; - - close (client->sock); - nroutes = rib_score_proto (client->proto, client->instance); - zlog_notice ("client %d disconnected. %lu %s routes removed from the rib", - client->sock, nroutes, zebra_route_string (client->proto)); - client->sock = -1; - } - - /* Free stream buffers. */ - if (client->ibuf) - stream_free (client->ibuf); - if (client->obuf) - stream_free (client->obuf); - if (client->wb) - buffer_free(client->wb); - - /* Release threads. */ - if (client->t_read) - thread_cancel (client->t_read); - if (client->t_write) - thread_cancel (client->t_write); - if (client->t_suicide) - thread_cancel (client->t_suicide); - - /* Free bitmaps. */ - for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) - for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) - vrf_bitmap_free (client->redist[afi][i]); - - vrf_bitmap_free (client->redist_default); - vrf_bitmap_free (client->ifinfo); - vrf_bitmap_free (client->ridinfo); - - /* Free client structure. */ - listnode_delete (zebrad.client_list, client); - XFREE (MTYPE_TMP, client); + /* Cleanup any FECs registered by this client. */ + zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT), + client); + + /* Close file descriptor. */ + if (client->sock) { + unsigned long nroutes; + + close(client->sock); + nroutes = rib_score_proto(client->proto, client->instance); + zlog_notice( + "client %d disconnected. %lu %s routes removed from the rib", + client->sock, nroutes, + zebra_route_string(client->proto)); + client->sock = -1; + } + + /* Free stream buffers. */ + if (client->ibuf) + stream_free(client->ibuf); + if (client->obuf) + stream_free(client->obuf); + if (client->wb) + buffer_free(client->wb); + + /* Release threads. */ + if (client->t_read) + thread_cancel(client->t_read); + if (client->t_write) + thread_cancel(client->t_write); + if (client->t_suicide) + thread_cancel(client->t_suicide); + + /* Free bitmaps. */ + for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) + for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) + vrf_bitmap_free(client->redist[afi][i]); + + vrf_bitmap_free(client->redist_default); + vrf_bitmap_free(client->ifinfo); + vrf_bitmap_free(client->ridinfo); + + /* Free client structure. */ + listnode_delete(zebrad.client_list, client); + XFREE(MTYPE_TMP, client); } /* Make new client. */ -static void -zebra_client_create (int sock) +static void zebra_client_create(int sock) { - struct zserv *client; - int i; - afi_t afi; + struct zserv *client; + int i; + afi_t afi; + + client = XCALLOC(MTYPE_TMP, sizeof(struct zserv)); - client = XCALLOC (MTYPE_TMP, sizeof (struct zserv)); + /* Make client input/output buffer. */ + client->sock = sock; + client->ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ); + client->obuf = stream_new(ZEBRA_MAX_PACKET_SIZ); + client->wb = buffer_new(0); - /* Make client input/output buffer. */ - client->sock = sock; - client->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ); - client->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ); - client->wb = buffer_new(0); + /* Set table number. */ + client->rtm_table = zebrad.rtm_table_default; - /* Set table number. */ - client->rtm_table = zebrad.rtm_table_default; + client->connect_time = monotime(NULL); + /* Initialize flags */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + client->redist[afi][i] = vrf_bitmap_init(); + client->redist_default = vrf_bitmap_init(); + client->ifinfo = vrf_bitmap_init(); + client->ridinfo = vrf_bitmap_init(); - client->connect_time = monotime(NULL); - /* Initialize flags */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - client->redist[afi][i] = vrf_bitmap_init (); - client->redist_default = vrf_bitmap_init (); - client->ifinfo = vrf_bitmap_init (); - client->ridinfo = vrf_bitmap_init (); + /* by default, it's not a synchronous client */ + client->is_synchronous = 0; - /* by default, it's not a synchronous client */ - client->is_synchronous = 0; + /* Add this client to linked list. */ + listnode_add(zebrad.client_list, client); - /* Add this client to linked list. */ - listnode_add (zebrad.client_list, client); - - /* Make new read thread. */ - zebra_event (ZEBRA_READ, sock, client); + /* Make new read thread. */ + zebra_event(ZEBRA_READ, sock, client); - zebra_vrf_update_all (client); + zebra_vrf_update_all(client); } /* Handler of zebra service request. */ -static int -zebra_client_read (struct thread *thread) -{ - int sock; - struct zserv *client; - size_t already; - uint16_t length, command; - uint8_t marker, version; - vrf_id_t vrf_id; - struct zebra_vrf *zvrf; - - /* Get thread data. Reset reading thread because I'm running. */ - sock = THREAD_FD (thread); - client = THREAD_ARG (thread); - client->t_read = NULL; - - if (client->t_suicide) - { - zebra_client_close(client); - return -1; - } - - /* Read length and command (if we don't have it already). */ - if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE) - { - ssize_t nbyte; - if (((nbyte = stream_read_try (client->ibuf, sock, - ZEBRA_HEADER_SIZE-already)) == 0) || - (nbyte == -1)) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("connection closed socket [%d]", sock); - zebra_client_close (client); - return -1; +static int zebra_client_read(struct thread *thread) +{ + int sock; + struct zserv *client; + size_t already; + uint16_t length, command; + uint8_t marker, version; + vrf_id_t vrf_id; + struct zebra_vrf *zvrf; + + /* Get thread data. Reset reading thread because I'm running. */ + sock = THREAD_FD(thread); + client = THREAD_ARG(thread); + client->t_read = NULL; + + if (client->t_suicide) { + zebra_client_close(client); + return -1; } - if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already)) - { - /* Try again later. */ - zebra_event (ZEBRA_READ, sock, client); - return 0; + + /* Read length and command (if we don't have it already). */ + if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE) { + ssize_t nbyte; + if (((nbyte = stream_read_try(client->ibuf, sock, + ZEBRA_HEADER_SIZE - already)) + == 0) + || (nbyte == -1)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("connection closed socket [%d]", + sock); + zebra_client_close(client); + return -1; + } + if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) { + /* Try again later. */ + zebra_event(ZEBRA_READ, sock, client); + return 0; + } + already = ZEBRA_HEADER_SIZE; } - already = ZEBRA_HEADER_SIZE; - } - - /* Reset to read from the beginning of the incoming packet. */ - stream_set_getp(client->ibuf, 0); - - /* Fetch header values */ - length = stream_getw (client->ibuf); - marker = stream_getc (client->ibuf); - version = stream_getc (client->ibuf); - vrf_id = stream_getw (client->ibuf); - command = stream_getw (client->ibuf); - - if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) - { - zlog_err("%s: socket %d version mismatch, marker %d, version %d", - __func__, sock, marker, version); - zebra_client_close (client); - return -1; - } - if (length < ZEBRA_HEADER_SIZE) - { - zlog_warn("%s: socket %d message length %u is less than header size %d", - __func__, sock, length, ZEBRA_HEADER_SIZE); - zebra_client_close (client); - return -1; - } - if (length > STREAM_SIZE(client->ibuf)) - { - zlog_warn("%s: socket %d message length %u exceeds buffer size %lu", - __func__, sock, length, (u_long)STREAM_SIZE(client->ibuf)); - zebra_client_close (client); - return -1; - } - - /* Read rest of data. */ - if (already < length) - { - ssize_t nbyte; - if (((nbyte = stream_read_try (client->ibuf, sock, - length-already)) == 0) || - (nbyte == -1)) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("connection closed [%d] when reading zebra data", sock); - zebra_client_close (client); - return -1; + + /* Reset to read from the beginning of the incoming packet. */ + stream_set_getp(client->ibuf, 0); + + /* Fetch header values */ + length = stream_getw(client->ibuf); + marker = stream_getc(client->ibuf); + version = stream_getc(client->ibuf); + vrf_id = stream_getw(client->ibuf); + command = stream_getw(client->ibuf); + + if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) { + zlog_err( + "%s: socket %d version mismatch, marker %d, version %d", + __func__, sock, marker, version); + zebra_client_close(client); + return -1; + } + if (length < ZEBRA_HEADER_SIZE) { + zlog_warn( + "%s: socket %d message length %u is less than header size %d", + __func__, sock, length, ZEBRA_HEADER_SIZE); + zebra_client_close(client); + return -1; + } + if (length > STREAM_SIZE(client->ibuf)) { + zlog_warn( + "%s: socket %d message length %u exceeds buffer size %lu", + __func__, sock, length, + (u_long)STREAM_SIZE(client->ibuf)); + zebra_client_close(client); + return -1; } - if (nbyte != (ssize_t)(length-already)) - { - /* Try again later. */ - zebra_event (ZEBRA_READ, sock, client); - return 0; + + /* Read rest of data. */ + if (already < length) { + ssize_t nbyte; + if (((nbyte = stream_read_try(client->ibuf, sock, + length - already)) + == 0) + || (nbyte == -1)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "connection closed [%d] when reading zebra data", + sock); + zebra_client_close(client); + return -1; + } + if (nbyte != (ssize_t)(length - already)) { + /* Try again later. */ + zebra_event(ZEBRA_READ, sock, client); + return 0; + } + } + + length -= ZEBRA_HEADER_SIZE; + + /* Debug packet information. */ + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("zebra message comes from socket [%d]", sock); + + if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) + zlog_debug("zebra message received [%s] %d in VRF %u", + zserv_command_string(command), length, vrf_id); + + client->last_read_time = monotime(NULL); + client->last_read_cmd = command; + + zvrf = zebra_vrf_lookup_by_id(vrf_id); + if (!zvrf) { + if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) + zlog_debug("zebra received unknown VRF[%u]", vrf_id); + goto zclient_read_out; } - } - - length -= ZEBRA_HEADER_SIZE; - - /* Debug packet information. */ - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("zebra message comes from socket [%d]", sock); - - if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) - zlog_debug ("zebra message received [%s] %d in VRF %u", - zserv_command_string (command), length, vrf_id); - - client->last_read_time = monotime(NULL); - client->last_read_cmd = command; - - zvrf = zebra_vrf_lookup_by_id (vrf_id); - if (!zvrf) - { - if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) - zlog_debug ("zebra received unknown VRF[%u]", vrf_id); - goto zclient_read_out; - } - - switch (command) - { - case ZEBRA_ROUTER_ID_ADD: - zread_router_id_add (client, length, zvrf); - break; - case ZEBRA_ROUTER_ID_DELETE: - zread_router_id_delete (client, length, zvrf); - break; - case ZEBRA_INTERFACE_ADD: - zread_interface_add (client, length, zvrf); - break; - case ZEBRA_INTERFACE_DELETE: - zread_interface_delete (client, length, zvrf); - break; - case ZEBRA_IPV4_ROUTE_ADD: - zread_ipv4_add (client, length, zvrf); - break; - case ZEBRA_IPV4_ROUTE_DELETE: - zread_ipv4_delete (client, length, zvrf); - break; - case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD: - zread_ipv4_route_ipv6_nexthop_add (client, length, zvrf); - break; - case ZEBRA_IPV4_NEXTHOP_ADD: - zread_ipv4_add(client, length, zvrf); /* LB: r1.0 merge - id was 1 */ - break; - case ZEBRA_IPV4_NEXTHOP_DELETE: - zread_ipv4_delete(client, length, zvrf); /* LB: r1.0 merge - id was 1 */ - break; - case ZEBRA_IPV6_ROUTE_ADD: - zread_ipv6_add (client, length, zvrf); - break; - case ZEBRA_IPV6_ROUTE_DELETE: - zread_ipv6_delete (client, length, zvrf); - break; - case ZEBRA_REDISTRIBUTE_ADD: - zebra_redistribute_add (command, client, length, zvrf); - break; - case ZEBRA_REDISTRIBUTE_DELETE: - zebra_redistribute_delete (command, client, length, zvrf); - break; - case ZEBRA_REDISTRIBUTE_DEFAULT_ADD: - zebra_redistribute_default_add (command, client, length, zvrf); - break; - case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE: - zebra_redistribute_default_delete (command, client, length, zvrf); - break; - case ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB: - zread_ipv4_nexthop_lookup_mrib (client, length, zvrf); - break; - case ZEBRA_HELLO: - zread_hello (client); - break; - case ZEBRA_NEXTHOP_REGISTER: - zserv_rnh_register(client, sock, length, RNH_NEXTHOP_TYPE, zvrf); - break; - case ZEBRA_NEXTHOP_UNREGISTER: - zserv_rnh_unregister(client, sock, length, RNH_NEXTHOP_TYPE, zvrf); - break; - case ZEBRA_IMPORT_ROUTE_REGISTER: - zserv_rnh_register(client, sock, length, RNH_IMPORT_CHECK_TYPE, zvrf); - break; - case ZEBRA_IMPORT_ROUTE_UNREGISTER: - zserv_rnh_unregister(client, sock, length, RNH_IMPORT_CHECK_TYPE, zvrf); - break; - case ZEBRA_BFD_DEST_UPDATE: - case ZEBRA_BFD_DEST_REGISTER: - zebra_ptm_bfd_dst_register(client, sock, length, command, zvrf); - break; - case ZEBRA_BFD_DEST_DEREGISTER: - zebra_ptm_bfd_dst_deregister(client, sock, length, zvrf); - break; - case ZEBRA_VRF_UNREGISTER: - zread_vrf_unregister (client, length, zvrf); - break; - case ZEBRA_BFD_CLIENT_REGISTER: - zebra_ptm_bfd_client_register(client, sock, length); - break; - case ZEBRA_INTERFACE_ENABLE_RADV: -#if defined (HAVE_RTADV) - zebra_interface_radv_set (client, sock, length, zvrf, 1); + + switch (command) { + case ZEBRA_ROUTER_ID_ADD: + zread_router_id_add(client, length, zvrf); + break; + case ZEBRA_ROUTER_ID_DELETE: + zread_router_id_delete(client, length, zvrf); + break; + case ZEBRA_INTERFACE_ADD: + zread_interface_add(client, length, zvrf); + break; + case ZEBRA_INTERFACE_DELETE: + zread_interface_delete(client, length, zvrf); + break; + case ZEBRA_IPV4_ROUTE_ADD: + zread_ipv4_add(client, length, zvrf); + break; + case ZEBRA_IPV4_ROUTE_DELETE: + zread_ipv4_delete(client, length, zvrf); + break; + case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD: + zread_ipv4_route_ipv6_nexthop_add(client, length, zvrf); + break; + case ZEBRA_IPV4_NEXTHOP_ADD: + zread_ipv4_add(client, length, + zvrf); /* LB: r1.0 merge - id was 1 */ + break; + case ZEBRA_IPV4_NEXTHOP_DELETE: + zread_ipv4_delete(client, length, + zvrf); /* LB: r1.0 merge - id was 1 */ + break; + case ZEBRA_IPV6_ROUTE_ADD: + zread_ipv6_add(client, length, zvrf); + break; + case ZEBRA_IPV6_ROUTE_DELETE: + zread_ipv6_delete(client, length, zvrf); + break; + case ZEBRA_REDISTRIBUTE_ADD: + zebra_redistribute_add(command, client, length, zvrf); + break; + case ZEBRA_REDISTRIBUTE_DELETE: + zebra_redistribute_delete(command, client, length, zvrf); + break; + case ZEBRA_REDISTRIBUTE_DEFAULT_ADD: + zebra_redistribute_default_add(command, client, length, zvrf); + break; + case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE: + zebra_redistribute_default_delete(command, client, length, + zvrf); + break; + case ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB: + zread_ipv4_nexthop_lookup_mrib(client, length, zvrf); + break; + case ZEBRA_HELLO: + zread_hello(client); + break; + case ZEBRA_NEXTHOP_REGISTER: + zserv_rnh_register(client, sock, length, RNH_NEXTHOP_TYPE, + zvrf); + break; + case ZEBRA_NEXTHOP_UNREGISTER: + zserv_rnh_unregister(client, sock, length, RNH_NEXTHOP_TYPE, + zvrf); + break; + case ZEBRA_IMPORT_ROUTE_REGISTER: + zserv_rnh_register(client, sock, length, RNH_IMPORT_CHECK_TYPE, + zvrf); + break; + case ZEBRA_IMPORT_ROUTE_UNREGISTER: + zserv_rnh_unregister(client, sock, length, + RNH_IMPORT_CHECK_TYPE, zvrf); + break; + case ZEBRA_BFD_DEST_UPDATE: + case ZEBRA_BFD_DEST_REGISTER: + zebra_ptm_bfd_dst_register(client, sock, length, command, zvrf); + break; + case ZEBRA_BFD_DEST_DEREGISTER: + zebra_ptm_bfd_dst_deregister(client, sock, length, zvrf); + break; + case ZEBRA_VRF_UNREGISTER: + zread_vrf_unregister(client, length, zvrf); + break; + case ZEBRA_BFD_CLIENT_REGISTER: + zebra_ptm_bfd_client_register(client, sock, length); + break; + case ZEBRA_INTERFACE_ENABLE_RADV: +#if defined(HAVE_RTADV) + zebra_interface_radv_set(client, sock, length, zvrf, 1); #endif - break; - case ZEBRA_INTERFACE_DISABLE_RADV: -#if defined (HAVE_RTADV) - zebra_interface_radv_set (client, sock, length, zvrf, 0); + break; + case ZEBRA_INTERFACE_DISABLE_RADV: +#if defined(HAVE_RTADV) + zebra_interface_radv_set(client, sock, length, zvrf, 0); #endif - break; - case ZEBRA_MPLS_LABELS_ADD: - case ZEBRA_MPLS_LABELS_DELETE: - zread_mpls_labels (command, client, length, vrf_id); - break; - case ZEBRA_IPMR_ROUTE_STATS: - zebra_ipmr_route_stats (client, sock, length, zvrf); - break; - case ZEBRA_LABEL_MANAGER_CONNECT: - case ZEBRA_GET_LABEL_CHUNK: - case ZEBRA_RELEASE_LABEL_CHUNK: - zread_label_manager_request (command, client, vrf_id); - break; - case ZEBRA_FEC_REGISTER: - zserv_fec_register (client, sock, length); - break; - case ZEBRA_FEC_UNREGISTER: - zserv_fec_unregister (client, sock, length); - break; - case ZEBRA_ADVERTISE_ALL_VNI: - zebra_vxlan_advertise_all_vni (client, sock, length, zvrf); - break; - case ZEBRA_REMOTE_VTEP_ADD: - zebra_vxlan_remote_vtep_add (client, sock, length, zvrf); - break; - case ZEBRA_REMOTE_VTEP_DEL: - zebra_vxlan_remote_vtep_del (client, sock, length, zvrf); - break; - case ZEBRA_REMOTE_MACIP_ADD: - zebra_vxlan_remote_macip_add (client, sock, length, zvrf); - break; - case ZEBRA_REMOTE_MACIP_DEL: - zebra_vxlan_remote_macip_del (client, sock, length, zvrf); - break; - default: - zlog_info ("Zebra received unknown command %d", command); - break; - } - - if (client->t_suicide) - { - /* No need to wait for thread callback, just kill immediately. */ - zebra_client_close(client); - return -1; - } - - zclient_read_out: - stream_reset (client->ibuf); - zebra_event (ZEBRA_READ, sock, client); - return 0; + break; + case ZEBRA_MPLS_LABELS_ADD: + case ZEBRA_MPLS_LABELS_DELETE: + zread_mpls_labels(command, client, length, vrf_id); + break; + case ZEBRA_IPMR_ROUTE_STATS: + zebra_ipmr_route_stats(client, sock, length, zvrf); + break; + case ZEBRA_LABEL_MANAGER_CONNECT: + case ZEBRA_GET_LABEL_CHUNK: + case ZEBRA_RELEASE_LABEL_CHUNK: + zread_label_manager_request(command, client, vrf_id); + break; + case ZEBRA_FEC_REGISTER: + zserv_fec_register(client, sock, length); + break; + case ZEBRA_FEC_UNREGISTER: + zserv_fec_unregister(client, sock, length); + break; + case ZEBRA_ADVERTISE_ALL_VNI: + zebra_vxlan_advertise_all_vni(client, sock, length, zvrf); + break; + case ZEBRA_REMOTE_VTEP_ADD: + zebra_vxlan_remote_vtep_add(client, sock, length, zvrf); + break; + case ZEBRA_REMOTE_VTEP_DEL: + zebra_vxlan_remote_vtep_del(client, sock, length, zvrf); + break; + case ZEBRA_REMOTE_MACIP_ADD: + zebra_vxlan_remote_macip_add(client, sock, length, zvrf); + break; + case ZEBRA_REMOTE_MACIP_DEL: + zebra_vxlan_remote_macip_del(client, sock, length, zvrf); + break; + default: + zlog_info("Zebra received unknown command %d", command); + break; + } + + if (client->t_suicide) { + /* No need to wait for thread callback, just kill immediately. + */ + zebra_client_close(client); + return -1; + } + +zclient_read_out: + stream_reset(client->ibuf); + zebra_event(ZEBRA_READ, sock, client); + return 0; } /* Accept code of zebra server socket. */ -static int -zebra_accept (struct thread *thread) +static int zebra_accept(struct thread *thread) { - int accept_sock; - int client_sock; - struct sockaddr_in client; - socklen_t len; + int accept_sock; + int client_sock; + struct sockaddr_in client; + socklen_t len; + + accept_sock = THREAD_FD(thread); - accept_sock = THREAD_FD (thread); + /* Reregister myself. */ + zebra_event(ZEBRA_SERV, accept_sock, NULL); - /* Reregister myself. */ - zebra_event (ZEBRA_SERV, accept_sock, NULL); + len = sizeof(struct sockaddr_in); + client_sock = accept(accept_sock, (struct sockaddr *)&client, &len); - len = sizeof (struct sockaddr_in); - client_sock = accept (accept_sock, (struct sockaddr *) &client, &len); + if (client_sock < 0) { + zlog_warn("Can't accept zebra socket: %s", + safe_strerror(errno)); + return -1; + } - if (client_sock < 0) - { - zlog_warn ("Can't accept zebra socket: %s", safe_strerror (errno)); - return -1; - } + /* Make client socket non-blocking. */ + set_nonblocking(client_sock); - /* Make client socket non-blocking. */ - set_nonblocking(client_sock); - - /* Create new zebra client. */ - zebra_client_create (client_sock); + /* Create new zebra client. */ + zebra_client_create(client_sock); - return 0; + return 0; } #ifdef HAVE_TCP_ZEBRA /* Make zebra's server socket. */ -static void -zebra_serv () -{ - int ret; - int accept_sock; - struct sockaddr_in addr; - - accept_sock = socket (AF_INET, SOCK_STREAM, 0); - - if (accept_sock < 0) - { - zlog_warn ("Can't create zserv stream socket: %s", - safe_strerror (errno)); - zlog_warn ("zebra can't provice full functionality due to above error"); - return; - } - - memset (&addr, 0, sizeof (struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_port = htons (ZEBRA_PORT); +static void zebra_serv() +{ + int ret; + int accept_sock; + struct sockaddr_in addr; + + accept_sock = socket(AF_INET, SOCK_STREAM, 0); + + if (accept_sock < 0) { + zlog_warn("Can't create zserv stream socket: %s", + safe_strerror(errno)); + zlog_warn( + "zebra can't provice full functionality due to above error"); + return; + } + + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_port = htons(ZEBRA_PORT); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - addr.sin_len = sizeof (struct sockaddr_in); + addr.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - - sockopt_reuseaddr (accept_sock); - sockopt_reuseport (accept_sock); - - if ( zserv_privs.change(ZPRIVS_RAISE) ) - zlog_err("Can't raise privileges"); - - ret = bind (accept_sock, (struct sockaddr *)&addr, - sizeof (struct sockaddr_in)); - if (ret < 0) - { - zlog_warn ("Can't bind to stream socket: %s", - safe_strerror (errno)); - zlog_warn ("zebra can't provice full functionality due to above error"); - close (accept_sock); /* Avoid sd leak. */ - return; - } - - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err("Can't lower privileges"); - - ret = listen (accept_sock, 1); - if (ret < 0) - { - zlog_warn ("Can't listen to stream socket: %s", - safe_strerror (errno)); - zlog_warn ("zebra can't provice full functionality due to above error"); - close (accept_sock); /* Avoid sd leak. */ - return; - } - - zebra_event (ZEBRA_SERV, accept_sock, NULL); + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + sockopt_reuseaddr(accept_sock); + sockopt_reuseport(accept_sock); + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + + ret = bind(accept_sock, (struct sockaddr *)&addr, + sizeof(struct sockaddr_in)); + if (ret < 0) { + zlog_warn("Can't bind to stream socket: %s", + safe_strerror(errno)); + zlog_warn( + "zebra can't provice full functionality due to above error"); + close(accept_sock); /* Avoid sd leak. */ + return; + } + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + ret = listen(accept_sock, 1); + if (ret < 0) { + zlog_warn("Can't listen to stream socket: %s", + safe_strerror(errno)); + zlog_warn( + "zebra can't provice full functionality due to above error"); + close(accept_sock); /* Avoid sd leak. */ + return; + } + + zebra_event(ZEBRA_SERV, accept_sock, NULL); } #else /* HAVE_TCP_ZEBRA */ @@ -2566,221 +2521,212 @@ zebra_serv () #include <sys/un.h> /* zebra server UNIX domain socket. */ -static void -zebra_serv_un (const char *path) -{ - int ret; - int sock, len; - struct sockaddr_un serv; - mode_t old_mask; - - /* First of all, unlink existing socket */ - unlink (path); - - /* Set umask */ - old_mask = umask (0077); - - /* Make UNIX domain socket. */ - sock = socket (AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - { - zlog_warn ("Can't create zserv unix socket: %s", - safe_strerror (errno)); - zlog_warn ("zebra can't provide full functionality due to above error"); - return; - } - - /* Make server socket. */ - memset (&serv, 0, sizeof (struct sockaddr_un)); - serv.sun_family = AF_UNIX; - strncpy (serv.sun_path, path, strlen (path)); +static void zebra_serv_un(const char *path) +{ + int ret; + int sock, len; + struct sockaddr_un serv; + mode_t old_mask; + + /* First of all, unlink existing socket */ + unlink(path); + + /* Set umask */ + old_mask = umask(0077); + + /* Make UNIX domain socket. */ + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + zlog_warn("Can't create zserv unix socket: %s", + safe_strerror(errno)); + zlog_warn( + "zebra can't provide full functionality due to above error"); + return; + } + + /* Make server socket. */ + memset(&serv, 0, sizeof(struct sockaddr_un)); + serv.sun_family = AF_UNIX; + strncpy(serv.sun_path, path, strlen(path)); #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN - len = serv.sun_len = SUN_LEN(&serv); + len = serv.sun_len = SUN_LEN(&serv); #else - len = sizeof (serv.sun_family) + strlen (serv.sun_path); + len = sizeof(serv.sun_family) + strlen(serv.sun_path); #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */ - ret = bind (sock, (struct sockaddr *) &serv, len); - if (ret < 0) - { - zlog_warn ("Can't bind to unix socket %s: %s", - path, safe_strerror (errno)); - zlog_warn ("zebra can't provide full functionality due to above error"); - close (sock); - return; - } - - ret = listen (sock, 5); - if (ret < 0) - { - zlog_warn ("Can't listen to unix socket %s: %s", - path, safe_strerror (errno)); - zlog_warn ("zebra can't provide full functionality due to above error"); - close (sock); - return; - } - - umask (old_mask); - - zebra_event (ZEBRA_SERV, sock, NULL); + ret = bind(sock, (struct sockaddr *)&serv, len); + if (ret < 0) { + zlog_warn("Can't bind to unix socket %s: %s", path, + safe_strerror(errno)); + zlog_warn( + "zebra can't provide full functionality due to above error"); + close(sock); + return; + } + + ret = listen(sock, 5); + if (ret < 0) { + zlog_warn("Can't listen to unix socket %s: %s", path, + safe_strerror(errno)); + zlog_warn( + "zebra can't provide full functionality due to above error"); + close(sock); + return; + } + + umask(old_mask); + + zebra_event(ZEBRA_SERV, sock, NULL); } #endif /* HAVE_TCP_ZEBRA */ -static void -zebra_event (enum event event, int sock, struct zserv *client) -{ - switch (event) - { - case ZEBRA_SERV: - thread_add_read(zebrad.master, zebra_accept, client, sock, NULL); - break; - case ZEBRA_READ: - client->t_read = NULL; - thread_add_read(zebrad.master, zebra_client_read, client, sock, - &client->t_read); - break; - case ZEBRA_WRITE: - /**/ - break; - } +static void zebra_event(enum event event, int sock, struct zserv *client) +{ + switch (event) { + case ZEBRA_SERV: + thread_add_read(zebrad.master, zebra_accept, client, sock, + NULL); + break; + case ZEBRA_READ: + client->t_read = NULL; + thread_add_read(zebrad.master, zebra_client_read, client, sock, + &client->t_read); + break; + case ZEBRA_WRITE: + /**/ + break; + } } #define ZEBRA_TIME_BUF 32 -static char * -zserv_time_buf(time_t *time1, char *buf, int buflen) +static char *zserv_time_buf(time_t *time1, char *buf, int buflen) { - struct tm *tm; - time_t now; + struct tm *tm; + time_t now; - assert (buf != NULL); - assert (buflen >= ZEBRA_TIME_BUF); - assert (time1 != NULL); + assert(buf != NULL); + assert(buflen >= ZEBRA_TIME_BUF); + assert(time1 != NULL); - if (!*time1) - { - snprintf(buf, buflen, "never "); - return (buf); - } + if (!*time1) { + snprintf(buf, buflen, "never "); + return (buf); + } - now = monotime(NULL); - now -= *time1; - tm = gmtime(&now); + now = monotime(NULL); + now -= *time1; + tm = gmtime(&now); - /* Making formatted timer strings. */ +/* Making formatted timer strings. */ #define ONE_DAY_SECOND 60*60*24 #define ONE_WEEK_SECOND 60*60*24*7 - if (now < ONE_DAY_SECOND) - snprintf (buf, buflen, "%02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (now < ONE_WEEK_SECOND) - snprintf (buf, buflen, "%dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - else - snprintf (buf, buflen, "%02dw%dd%02dh", - tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - return buf; -} - -static void -zebra_show_client_detail (struct vty *vty, struct zserv *client) -{ - char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF]; - char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF]; - - vty_out (vty, "Client: %s", zebra_route_string(client->proto)); - if (client->instance) - vty_out (vty, " Instance: %d", client->instance); - vty_out (vty, "\n"); - - vty_out (vty, "------------------------ \n"); - vty_out (vty, "FD: %d \n", client->sock); - vty_out (vty, "Route Table ID: %d \n", client->rtm_table); - - vty_out (vty, "Connect Time: %s \n", - zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF)); - if (client->nh_reg_time) - { - vty_out (vty, "Nexthop Registry Time: %s \n", - zserv_time_buf(&client->nh_reg_time, nhbuf, ZEBRA_TIME_BUF)); - if (client->nh_last_upd_time) - vty_out (vty, "Nexthop Last Update Time: %s \n", - zserv_time_buf(&client->nh_last_upd_time, mbuf, ZEBRA_TIME_BUF)); + if (now < ONE_DAY_SECOND) + snprintf(buf, buflen, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, + tm->tm_sec); + else if (now < ONE_WEEK_SECOND) + snprintf(buf, buflen, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, + tm->tm_min); else - vty_out (vty, "No Nexthop Update sent\n"); - } - else - vty_out (vty, "Not registered for Nexthop Updates\n"); - - vty_out (vty, "Last Msg Rx Time: %s \n", - zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF)); - vty_out (vty, "Last Msg Tx Time: %s \n", - zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF)); - if (client->last_read_time) - vty_out (vty, "Last Rcvd Cmd: %s \n", - zserv_command_string(client->last_read_cmd)); - if (client->last_write_time) - vty_out (vty, "Last Sent Cmd: %s \n", - zserv_command_string(client->last_write_cmd)); - vty_out (vty, "\n"); - - vty_out (vty, "Type Add Update Del \n"); - vty_out (vty, "================================================== \n"); - vty_out (vty, "IPv4 %-12d%-12d%-12d\n", client->v4_route_add_cnt, - client->v4_route_upd8_cnt, client->v4_route_del_cnt); - vty_out (vty, "IPv6 %-12d%-12d%-12d\n", client->v6_route_add_cnt, - client->v6_route_upd8_cnt, client->v6_route_del_cnt); - vty_out (vty, "Redist:v4 %-12d%-12d%-12d\n", client->redist_v4_add_cnt, 0, - client->redist_v4_del_cnt); - vty_out (vty, "Redist:v6 %-12d%-12d%-12d\n", client->redist_v6_add_cnt, 0, - client->redist_v6_del_cnt); - vty_out (vty, "Connected %-12d%-12d%-12d\n", client->ifadd_cnt, 0, - client->ifdel_cnt); - vty_out (vty, "BFD peer %-12d%-12d%-12d\n", client->bfd_peer_add_cnt, - client->bfd_peer_upd8_cnt, client->bfd_peer_del_cnt); - vty_out (vty, "Interface Up Notifications: %d\n",client->ifup_cnt); - vty_out (vty, "Interface Down Notifications: %d\n",client->ifdown_cnt); - vty_out (vty, "VNI add notifications: %d\n", client->vniadd_cnt); - vty_out (vty, "VNI delete notifications: %d\n", client->vnidel_cnt); - vty_out (vty, "MAC-IP add notifications: %d\n", client->macipadd_cnt); - vty_out (vty, "MAC-IP delete notifications: %d\n", client->macipdel_cnt); - - vty_out (vty, "\n"); - return; -} - -static void -zebra_show_client_brief (struct vty *vty, struct zserv *client) -{ - char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF]; - char wbuf[ZEBRA_TIME_BUF]; - - vty_out (vty, "%-8s%12s %12s%12s%8d/%-8d%8d/%-8d\n", - zebra_route_string(client->proto), - zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF), - zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF), - zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF), - client->v4_route_add_cnt+client->v4_route_upd8_cnt, - client->v4_route_del_cnt, - client->v6_route_add_cnt+client->v6_route_upd8_cnt, - client->v6_route_del_cnt); - -} - -struct zserv * -zebra_find_client (u_char proto) -{ - struct listnode *node, *nnode; - struct zserv *client; - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - if (client->proto == proto) - return client; - } - - return NULL; + snprintf(buf, buflen, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour); + return buf; +} + +static void zebra_show_client_detail(struct vty *vty, struct zserv *client) +{ + char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF]; + char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF]; + + vty_out(vty, "Client: %s", zebra_route_string(client->proto)); + if (client->instance) + vty_out(vty, " Instance: %d", client->instance); + vty_out(vty, "\n"); + + vty_out(vty, "------------------------ \n"); + vty_out(vty, "FD: %d \n", client->sock); + vty_out(vty, "Route Table ID: %d \n", client->rtm_table); + + vty_out(vty, "Connect Time: %s \n", + zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF)); + if (client->nh_reg_time) { + vty_out(vty, "Nexthop Registry Time: %s \n", + zserv_time_buf(&client->nh_reg_time, nhbuf, + ZEBRA_TIME_BUF)); + if (client->nh_last_upd_time) + vty_out(vty, "Nexthop Last Update Time: %s \n", + zserv_time_buf(&client->nh_last_upd_time, mbuf, + ZEBRA_TIME_BUF)); + else + vty_out(vty, "No Nexthop Update sent\n"); + } else + vty_out(vty, "Not registered for Nexthop Updates\n"); + + vty_out(vty, "Last Msg Rx Time: %s \n", + zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF)); + vty_out(vty, "Last Msg Tx Time: %s \n", + zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF)); + if (client->last_read_time) + vty_out(vty, "Last Rcvd Cmd: %s \n", + zserv_command_string(client->last_read_cmd)); + if (client->last_write_time) + vty_out(vty, "Last Sent Cmd: %s \n", + zserv_command_string(client->last_write_cmd)); + vty_out(vty, "\n"); + + vty_out(vty, "Type Add Update Del \n"); + vty_out(vty, "================================================== \n"); + vty_out(vty, "IPv4 %-12d%-12d%-12d\n", client->v4_route_add_cnt, + client->v4_route_upd8_cnt, client->v4_route_del_cnt); + vty_out(vty, "IPv6 %-12d%-12d%-12d\n", client->v6_route_add_cnt, + client->v6_route_upd8_cnt, client->v6_route_del_cnt); + vty_out(vty, "Redist:v4 %-12d%-12d%-12d\n", client->redist_v4_add_cnt, + 0, client->redist_v4_del_cnt); + vty_out(vty, "Redist:v6 %-12d%-12d%-12d\n", client->redist_v6_add_cnt, + 0, client->redist_v6_del_cnt); + vty_out(vty, "Connected %-12d%-12d%-12d\n", client->ifadd_cnt, 0, + client->ifdel_cnt); + vty_out(vty, "BFD peer %-12d%-12d%-12d\n", client->bfd_peer_add_cnt, + client->bfd_peer_upd8_cnt, client->bfd_peer_del_cnt); + vty_out(vty, "Interface Up Notifications: %d\n", client->ifup_cnt); + vty_out(vty, "Interface Down Notifications: %d\n", client->ifdown_cnt); + vty_out(vty, "VNI add notifications: %d\n", client->vniadd_cnt); + vty_out(vty, "VNI delete notifications: %d\n", client->vnidel_cnt); + vty_out(vty, "MAC-IP add notifications: %d\n", client->macipadd_cnt); + vty_out(vty, "MAC-IP delete notifications: %d\n", client->macipdel_cnt); + + vty_out(vty, "\n"); + return; +} + +static void zebra_show_client_brief(struct vty *vty, struct zserv *client) +{ + char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF]; + char wbuf[ZEBRA_TIME_BUF]; + + vty_out(vty, "%-8s%12s %12s%12s%8d/%-8d%8d/%-8d\n", + zebra_route_string(client->proto), + zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF), + zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF), + zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF), + client->v4_route_add_cnt + client->v4_route_upd8_cnt, + client->v4_route_del_cnt, + client->v6_route_add_cnt + client->v6_route_upd8_cnt, + client->v6_route_del_cnt); +} + +struct zserv *zebra_find_client(u_char proto) +{ + struct listnode *node, *nnode; + struct zserv *client; + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + if (client->proto == proto) + return client; + } + + return NULL; } #ifdef HAVE_NETLINK @@ -2791,8 +2737,8 @@ DEFUN (show_table, SHOW_STR "default routing table to use for all clients\n") { - vty_out (vty, "table %d\n",zebrad.rtm_table_default); - return CMD_SUCCESS; + vty_out(vty, "table %d\n", zebrad.rtm_table_default); + return CMD_SUCCESS; } DEFUN (config_table, @@ -2801,8 +2747,8 @@ DEFUN (config_table, "Configure target kernel routing table\n" "TABLE integer\n") { - zebrad.rtm_table_default = strtol (argv[1]->arg, (char**)0, 10); - return CMD_SUCCESS; + zebrad.rtm_table_default = strtol(argv[1]->arg, (char **)0, 10); + return CMD_SUCCESS; } DEFUN (no_config_table, @@ -2812,8 +2758,8 @@ DEFUN (no_config_table, "Configure target kernel routing table\n" "TABLE integer\n") { - zebrad.rtm_table_default = 0; - return CMD_SUCCESS; + zebrad.rtm_table_default = 0; + return CMD_SUCCESS; } #endif @@ -2823,19 +2769,18 @@ DEFUN (ip_forwarding, IP_STR "Turn on IP forwarding") { - int ret; + int ret; - ret = ipforward (); - if (ret == 0) - ret = ipforward_on (); + ret = ipforward(); + if (ret == 0) + ret = ipforward_on(); - if (ret == 0) - { - vty_out (vty, "Can't turn on IP forwarding\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret == 0) { + vty_out(vty, "Can't turn on IP forwarding\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_forwarding, @@ -2845,19 +2790,18 @@ DEFUN (no_ip_forwarding, IP_STR "Turn off IP forwarding") { - int ret; + int ret; - ret = ipforward (); - if (ret != 0) - ret = ipforward_off (); + ret = ipforward(); + if (ret != 0) + ret = ipforward_off(); - if (ret != 0) - { - vty_out (vty, "Can't turn off IP forwarding\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret != 0) { + vty_out(vty, "Can't turn off IP forwarding\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_zebra, @@ -2866,21 +2810,23 @@ DEFUN (show_zebra, SHOW_STR "Zebra information\n") { - struct vrf *vrf; + struct vrf *vrf; - vty_out (vty, - " Route Route Neighbor LSP LSP\n"); - vty_out (vty, - "VRF Installs Removals Updates Installs Removals\n"); - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - struct zebra_vrf *zvrf = vrf->info; - vty_out (vty,"%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n", - vrf->name, zvrf->installs, zvrf->removals, - zvrf->neigh_updates, zvrf->lsp_installs,zvrf->lsp_removals); - } + vty_out(vty, + " Route Route Neighbor LSP LSP\n"); + vty_out(vty, + "VRF Installs Removals Updates Installs Removals\n"); + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + struct zebra_vrf *zvrf = vrf->info; + vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 + " %10" PRIu64 " %10" PRIu64 "\n", + vrf->name, zvrf->installs, zvrf->removals, + zvrf->neigh_updates, zvrf->lsp_installs, + zvrf->lsp_removals); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* This command is for debugging purpose. */ @@ -2891,13 +2837,13 @@ DEFUN (show_zebra_client, "Zebra information\n" "Client information\n") { - struct listnode *node; - struct zserv *client; + struct listnode *node; + struct zserv *client; - for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) - zebra_show_client_detail(vty, client); + for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) + zebra_show_client_detail(vty, client); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* This command is for debugging purpose. */ @@ -2909,37 +2855,33 @@ DEFUN (show_zebra_client_summary, "Client information brief\n" "Brief Summary\n") { - struct listnode *node; - struct zserv *client; + struct listnode *node; + struct zserv *client; - vty_out (vty, - "Name Connect Time Last Read Last Write IPv4 Routes IPv6 Routes \n"); - vty_out (vty, - "--------------------------------------------------------------------------------\n"); + vty_out(vty, + "Name Connect Time Last Read Last Write IPv4 Routes IPv6 Routes \n"); + vty_out(vty, + "--------------------------------------------------------------------------------\n"); - for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) - zebra_show_client_brief(vty, client); + for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) + zebra_show_client_brief(vty, client); - vty_out (vty, "Routes column shows (added+updated)/deleted\n"); - return CMD_SUCCESS; + vty_out(vty, "Routes column shows (added+updated)/deleted\n"); + return CMD_SUCCESS; } /* Table configuration write function. */ -static int -config_write_table (struct vty *vty) +static int config_write_table(struct vty *vty) { - if (zebrad.rtm_table_default) - vty_out (vty, "table %d\n",zebrad.rtm_table_default); - return 0; + if (zebrad.rtm_table_default) + vty_out(vty, "table %d\n", zebrad.rtm_table_default); + return 0; } /* table node for routing tables. */ -static struct cmd_node table_node = -{ - TABLE_NODE, - "", /* This node has no interface. */ - 1 -}; +static struct cmd_node table_node = {TABLE_NODE, + "", /* This node has no interface. */ + 1}; /* Only display ip forwarding is enabled or not. */ DEFUN (show_ip_forwarding, @@ -2949,15 +2891,15 @@ DEFUN (show_ip_forwarding, IP_STR "IP forwarding status\n") { - int ret; + int ret; - ret = ipforward (); + ret = ipforward(); - if (ret == 0) - vty_out (vty, "IP forwarding is off\n"); - else - vty_out (vty, "IP forwarding is on\n"); - return CMD_SUCCESS; + if (ret == 0) + vty_out(vty, "IP forwarding is off\n"); + else + vty_out(vty, "IP forwarding is on\n"); + return CMD_SUCCESS; } /* Only display ipv6 forwarding is enabled or not. */ @@ -2968,26 +2910,25 @@ DEFUN (show_ipv6_forwarding, "IPv6 information\n" "Forwarding status\n") { - int ret; + int ret; - ret = ipforward_ipv6 (); + ret = ipforward_ipv6(); - switch (ret) - { - case -1: - vty_out (vty, "ipv6 forwarding is unknown\n"); - break; - case 0: - vty_out (vty, "ipv6 forwarding is %s\n", "off"); - break; - case 1: - vty_out (vty, "ipv6 forwarding is %s\n", "on"); - break; - default: - vty_out (vty, "ipv6 forwarding is %s\n", "off"); - break; - } - return CMD_SUCCESS; + switch (ret) { + case -1: + vty_out(vty, "ipv6 forwarding is unknown\n"); + break; + case 0: + vty_out(vty, "ipv6 forwarding is %s\n", "off"); + break; + case 1: + vty_out(vty, "ipv6 forwarding is %s\n", "on"); + break; + default: + vty_out(vty, "ipv6 forwarding is %s\n", "off"); + break; + } + return CMD_SUCCESS; } DEFUN (ipv6_forwarding, @@ -2996,19 +2937,18 @@ DEFUN (ipv6_forwarding, IPV6_STR "Turn on IPv6 forwarding") { - int ret; + int ret; - ret = ipforward_ipv6 (); - if (ret == 0) - ret = ipforward_ipv6_on (); + ret = ipforward_ipv6(); + if (ret == 0) + ret = ipforward_ipv6_on(); - if (ret == 0) - { - vty_out (vty, "Can't turn on IPv6 forwarding\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret == 0) { + vty_out(vty, "Can't turn on IPv6 forwarding\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_forwarding, @@ -3018,83 +2958,76 @@ DEFUN (no_ipv6_forwarding, IPV6_STR "Turn off IPv6 forwarding") { - int ret; + int ret; - ret = ipforward_ipv6 (); - if (ret != 0) - ret = ipforward_ipv6_off (); + ret = ipforward_ipv6(); + if (ret != 0) + ret = ipforward_ipv6_off(); - if (ret != 0) - { - vty_out (vty, "Can't turn off IPv6 forwarding\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret != 0) { + vty_out(vty, "Can't turn off IPv6 forwarding\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* IPForwarding configuration write function. */ -static int -config_write_forwarding (struct vty *vty) +static int config_write_forwarding(struct vty *vty) { - /* FIXME: Find better place for that. */ - router_id_write (vty); + /* FIXME: Find better place for that. */ + router_id_write(vty); - if (!ipforward ()) - vty_out (vty, "no ip forwarding\n"); - if (!ipforward_ipv6 ()) - vty_out (vty, "no ipv6 forwarding\n"); - vty_out (vty, "!\n"); - return 0; + if (!ipforward()) + vty_out(vty, "no ip forwarding\n"); + if (!ipforward_ipv6()) + vty_out(vty, "no ipv6 forwarding\n"); + vty_out(vty, "!\n"); + return 0; } /* table node for routing tables. */ -static struct cmd_node forwarding_node = -{ - FORWARDING_NODE, - "", /* This node has no interface. */ - 1 -}; +static struct cmd_node forwarding_node = {FORWARDING_NODE, + "", /* This node has no interface. */ + 1}; /* Initialisation of zebra and installation of commands. */ -void -zebra_init (void) +void zebra_init(void) { - /* Client list init. */ - zebrad.client_list = list_new (); + /* Client list init. */ + zebrad.client_list = list_new(); - /* Install configuration write function. */ - install_node (&table_node, config_write_table); - install_node (&forwarding_node, config_write_forwarding); + /* Install configuration write function. */ + install_node(&table_node, config_write_table); + install_node(&forwarding_node, config_write_forwarding); - install_element (VIEW_NODE, &show_ip_forwarding_cmd); - install_element (CONFIG_NODE, &ip_forwarding_cmd); - install_element (CONFIG_NODE, &no_ip_forwarding_cmd); - install_element (ENABLE_NODE, &show_zebra_cmd); - install_element (ENABLE_NODE, &show_zebra_client_cmd); - install_element (ENABLE_NODE, &show_zebra_client_summary_cmd); + install_element(VIEW_NODE, &show_ip_forwarding_cmd); + install_element(CONFIG_NODE, &ip_forwarding_cmd); + install_element(CONFIG_NODE, &no_ip_forwarding_cmd); + install_element(ENABLE_NODE, &show_zebra_cmd); + install_element(ENABLE_NODE, &show_zebra_client_cmd); + install_element(ENABLE_NODE, &show_zebra_client_summary_cmd); #ifdef HAVE_NETLINK - install_element (VIEW_NODE, &show_table_cmd); - install_element (CONFIG_NODE, &config_table_cmd); - install_element (CONFIG_NODE, &no_config_table_cmd); + install_element(VIEW_NODE, &show_table_cmd); + install_element(CONFIG_NODE, &config_table_cmd); + install_element(CONFIG_NODE, &no_config_table_cmd); #endif /* HAVE_NETLINK */ - install_element (VIEW_NODE, &show_ipv6_forwarding_cmd); - install_element (CONFIG_NODE, &ipv6_forwarding_cmd); - install_element (CONFIG_NODE, &no_ipv6_forwarding_cmd); + install_element(VIEW_NODE, &show_ipv6_forwarding_cmd); + install_element(CONFIG_NODE, &ipv6_forwarding_cmd); + install_element(CONFIG_NODE, &no_ipv6_forwarding_cmd); - /* Route-map */ - zebra_route_map_init (); + /* Route-map */ + zebra_route_map_init(); } /* Make zebra server socket, wiping any existing one (see bug #403). */ -void -zebra_zserv_socket_init (char *path) +void zebra_zserv_socket_init(char *path) { #ifdef HAVE_TCP_ZEBRA - zebra_serv (); + zebra_serv(); #else - zebra_serv_un (path ? path : ZEBRA_SERV_PATH); + zebra_serv_un(path ? path : ZEBRA_SERV_PATH); #endif /* HAVE_TCP_ZEBRA */ } diff --git a/zebra/zserv.h b/zebra/zserv.h index 2d6f6fae7..a2cf5d9f4 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -39,152 +39,151 @@ #define ZEBRA_RMAP_DEFAULT_UPDATE_TIMER 5 /* disabled by default */ /* Client structure. */ -struct zserv -{ - /* Client file descriptor. */ - int sock; - - /* Input/output buffer to the client. */ - struct stream *ibuf; - struct stream *obuf; - - /* Buffer of data waiting to be written to client. */ - struct buffer *wb; - - /* Threads for read/write. */ - struct thread *t_read; - struct thread *t_write; - - /* Thread for delayed close. */ - struct thread *t_suicide; - - /* default routing table this client munges */ - int rtm_table; - - /* This client's redistribute flag. */ - struct redist_proto mi_redist[AFI_MAX][ZEBRA_ROUTE_MAX]; - vrf_bitmap_t redist[AFI_MAX][ZEBRA_ROUTE_MAX]; - - /* Redistribute default route flag. */ - vrf_bitmap_t redist_default; - - /* Interface information. */ - vrf_bitmap_t ifinfo; - - /* Router-id information. */ - vrf_bitmap_t ridinfo; - - /* client's protocol */ - u_char proto; - u_short instance; - u_char is_synchronous; - - /* Statistics */ - u_int32_t redist_v4_add_cnt; - u_int32_t redist_v4_del_cnt; - u_int32_t redist_v6_add_cnt; - u_int32_t redist_v6_del_cnt; - u_int32_t v4_route_add_cnt; - u_int32_t v4_route_upd8_cnt; - u_int32_t v4_route_del_cnt; - u_int32_t v6_route_add_cnt; - u_int32_t v6_route_del_cnt; - u_int32_t v6_route_upd8_cnt; - u_int32_t connected_rt_add_cnt; - u_int32_t connected_rt_del_cnt; - u_int32_t ifup_cnt; - u_int32_t ifdown_cnt; - u_int32_t ifadd_cnt; - u_int32_t ifdel_cnt; - u_int32_t if_bfd_cnt; - u_int32_t bfd_peer_add_cnt; - u_int32_t bfd_peer_upd8_cnt; - u_int32_t bfd_peer_del_cnt; - u_int32_t bfd_peer_replay_cnt; - u_int32_t vrfadd_cnt; - u_int32_t vrfdel_cnt; - u_int32_t if_vrfchg_cnt; - u_int32_t bfd_client_reg_cnt; - u_int32_t vniadd_cnt; - u_int32_t vnidel_cnt; - u_int32_t macipadd_cnt; - u_int32_t macipdel_cnt; - - time_t connect_time; - time_t last_read_time; - time_t last_write_time; - time_t nh_reg_time; - time_t nh_dereg_time; - time_t nh_last_upd_time; - - int last_read_cmd; - int last_write_cmd; +struct zserv { + /* Client file descriptor. */ + int sock; + + /* Input/output buffer to the client. */ + struct stream *ibuf; + struct stream *obuf; + + /* Buffer of data waiting to be written to client. */ + struct buffer *wb; + + /* Threads for read/write. */ + struct thread *t_read; + struct thread *t_write; + + /* Thread for delayed close. */ + struct thread *t_suicide; + + /* default routing table this client munges */ + int rtm_table; + + /* This client's redistribute flag. */ + struct redist_proto mi_redist[AFI_MAX][ZEBRA_ROUTE_MAX]; + vrf_bitmap_t redist[AFI_MAX][ZEBRA_ROUTE_MAX]; + + /* Redistribute default route flag. */ + vrf_bitmap_t redist_default; + + /* Interface information. */ + vrf_bitmap_t ifinfo; + + /* Router-id information. */ + vrf_bitmap_t ridinfo; + + /* client's protocol */ + u_char proto; + u_short instance; + u_char is_synchronous; + + /* Statistics */ + u_int32_t redist_v4_add_cnt; + u_int32_t redist_v4_del_cnt; + u_int32_t redist_v6_add_cnt; + u_int32_t redist_v6_del_cnt; + u_int32_t v4_route_add_cnt; + u_int32_t v4_route_upd8_cnt; + u_int32_t v4_route_del_cnt; + u_int32_t v6_route_add_cnt; + u_int32_t v6_route_del_cnt; + u_int32_t v6_route_upd8_cnt; + u_int32_t connected_rt_add_cnt; + u_int32_t connected_rt_del_cnt; + u_int32_t ifup_cnt; + u_int32_t ifdown_cnt; + u_int32_t ifadd_cnt; + u_int32_t ifdel_cnt; + u_int32_t if_bfd_cnt; + u_int32_t bfd_peer_add_cnt; + u_int32_t bfd_peer_upd8_cnt; + u_int32_t bfd_peer_del_cnt; + u_int32_t bfd_peer_replay_cnt; + u_int32_t vrfadd_cnt; + u_int32_t vrfdel_cnt; + u_int32_t if_vrfchg_cnt; + u_int32_t bfd_client_reg_cnt; + u_int32_t vniadd_cnt; + u_int32_t vnidel_cnt; + u_int32_t macipadd_cnt; + u_int32_t macipdel_cnt; + + time_t connect_time; + time_t last_read_time; + time_t last_write_time; + time_t nh_reg_time; + time_t nh_dereg_time; + time_t nh_last_upd_time; + + int last_read_cmd; + int last_write_cmd; }; /* Zebra instance */ -struct zebra_t -{ - /* Thread master */ - struct thread_master *master; - struct list *client_list; +struct zebra_t { + /* Thread master */ + struct thread_master *master; + struct list *client_list; - /* default table */ - u_int32_t rtm_table_default; + /* default table */ + u_int32_t rtm_table_default; - /* rib work queue */ - struct work_queue *ribq; - struct meta_queue *mq; + /* rib work queue */ + struct work_queue *ribq; + struct meta_queue *mq; - /* LSP work queue */ - struct work_queue *lsp_process_q; + /* LSP work queue */ + struct work_queue *lsp_process_q; }; extern struct zebra_t zebrad; extern unsigned int multipath_num; /* Prototypes. */ -extern void zebra_init (void); -extern void zebra_if_init (void); -extern void zebra_zserv_socket_init (char *path); -extern void hostinfo_get (void); -extern void rib_init (void); -extern void interface_list (struct zebra_ns *); -extern void route_read (struct zebra_ns *); -extern void macfdb_read (struct zebra_ns *); -extern void macfdb_read_for_bridge (struct zebra_ns *, struct interface *, - struct interface *); -extern void neigh_read (struct zebra_ns *); -extern void neigh_read_for_vlan (struct zebra_ns *, struct interface *); -extern void kernel_init (struct zebra_ns *); -extern void kernel_terminate (struct zebra_ns *); -extern void zebra_route_map_init (void); -extern void zebra_vty_init (void); - -extern int zsend_vrf_add (struct zserv *, struct zebra_vrf *); -extern int zsend_vrf_delete (struct zserv *, struct zebra_vrf *); - -extern int zsend_interface_add (struct zserv *, struct interface *); -extern int zsend_interface_delete (struct zserv *, struct interface *); -extern int zsend_interface_addresses (struct zserv *, struct interface *); -extern int zsend_interface_address (int, struct zserv *, struct interface *, - struct connected *); -extern void nbr_connected_add_ipv6 (struct interface *, struct in6_addr *); -extern void nbr_connected_delete_ipv6 (struct interface *, struct in6_addr *); -extern int zsend_interface_update (int, struct zserv *, struct interface *); -extern int zsend_redistribute_route (int, struct zserv *, struct prefix *, - struct prefix *, struct route_entry *); -extern int zsend_router_id_update (struct zserv *, struct prefix *, - vrf_id_t); -extern int zsend_interface_vrf_update (struct zserv *, struct interface *, - vrf_id_t); - -extern int zsend_interface_link_params (struct zserv *, struct interface *); +extern void zebra_init(void); +extern void zebra_if_init(void); +extern void zebra_zserv_socket_init(char *path); +extern void hostinfo_get(void); +extern void rib_init(void); +extern void interface_list(struct zebra_ns *); +extern void route_read(struct zebra_ns *); +extern void macfdb_read(struct zebra_ns *); +extern void macfdb_read_for_bridge(struct zebra_ns *, struct interface *, + struct interface *); +extern void neigh_read(struct zebra_ns *); +extern void neigh_read_for_vlan(struct zebra_ns *, struct interface *); +extern void kernel_init(struct zebra_ns *); +extern void kernel_terminate(struct zebra_ns *); +extern void zebra_route_map_init(void); +extern void zebra_vty_init(void); + +extern int zsend_vrf_add(struct zserv *, struct zebra_vrf *); +extern int zsend_vrf_delete(struct zserv *, struct zebra_vrf *); + +extern int zsend_interface_add(struct zserv *, struct interface *); +extern int zsend_interface_delete(struct zserv *, struct interface *); +extern int zsend_interface_addresses(struct zserv *, struct interface *); +extern int zsend_interface_address(int, struct zserv *, struct interface *, + struct connected *); +extern void nbr_connected_add_ipv6(struct interface *, struct in6_addr *); +extern void nbr_connected_delete_ipv6(struct interface *, struct in6_addr *); +extern int zsend_interface_update(int, struct zserv *, struct interface *); +extern int zsend_redistribute_route(int, struct zserv *, struct prefix *, + struct prefix *, struct route_entry *); +extern int zsend_router_id_update(struct zserv *, struct prefix *, vrf_id_t); +extern int zsend_interface_vrf_update(struct zserv *, struct interface *, + vrf_id_t); + +extern int zsend_interface_link_params(struct zserv *, struct interface *); extern pid_t pid; -extern void zserv_create_header(struct stream *s, uint16_t cmd, vrf_id_t vrf_id); -extern void zserv_nexthop_num_warn(const char *, const struct prefix *, const unsigned int); +extern void zserv_create_header(struct stream *s, uint16_t cmd, + vrf_id_t vrf_id); +extern void zserv_nexthop_num_warn(const char *, const struct prefix *, + const unsigned int); extern int zebra_server_send_message(struct zserv *client); -extern struct zserv *zebra_find_client (u_char proto); +extern struct zserv *zebra_find_client(u_char proto); #endif /* _ZEBRA_ZEBRA_H */ |