diff options
Diffstat (limited to 'zebra/zebra_rnh.c')
| -rw-r--r-- | zebra/zebra_rnh.c | 1610 |
1 files changed, 792 insertions, 818 deletions
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index c82712b9cc..8a326c27fc 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"); } |
