diff options
Diffstat (limited to 'zebra/zebra_rnh.c')
| -rw-r--r-- | zebra/zebra_rnh.c | 89 |
1 files changed, 84 insertions, 5 deletions
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 5096e95395..d5ebbbc466 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -131,6 +131,7 @@ zebra_add_rnh (struct prefix *p, vrf_id_t vrfid, rnh_type_t type) rnh->client_list = list_new(); rnh->vrf_id = vrfid; rnh->zebra_static_route_list = list_new(); + rnh->zebra_pseudowire_list = list_new(); route_lock_node (rn); rn->info = rnh; rnh->node = rn; @@ -168,6 +169,7 @@ zebra_free_rnh (struct rnh *rnh) rnh->flags |= ZEBRA_NHT_DELETED; list_free (rnh->client_list); list_free (rnh->zebra_static_route_list); + list_free (rnh->zebra_pseudowire_list); free_state (rnh->vrf_id, rnh->state, rnh->node); XFREE (MTYPE_RNH, rnh); } @@ -222,7 +224,8 @@ zebra_remove_rnh_client (struct rnh *rnh, struct zserv *client, rnh_type_t type) } listnode_delete(rnh->client_list, client); if (list_isempty(rnh->client_list) && - list_isempty(rnh->zebra_static_route_list)) + list_isempty(rnh->zebra_static_route_list) && + list_isempty(rnh->zebra_pseudowire_list)) zebra_delete_rnh(rnh, type); } @@ -252,7 +255,8 @@ zebra_deregister_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh, listnode_delete(rnh->zebra_static_route_list, static_rn); if (list_isempty(rnh->client_list) && - list_isempty(rnh->zebra_static_route_list)) + list_isempty(rnh->zebra_static_route_list) && + list_isempty(rnh->zebra_pseudowire_list)) zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE); } @@ -301,6 +305,62 @@ zebra_deregister_rnh_static_nexthops (vrf_id_t vrf_id, struct nexthop *nexthop, } } +/* XXX move this utility function elsewhere? */ +static void +addr2hostprefix (int af, const union g_addr *addr, struct prefix *prefix) +{ + switch (af) + { + case AF_INET: + prefix->family = AF_INET; + prefix->prefixlen = IPV4_MAX_BITLEN; + prefix->u.prefix4 = addr->ipv4; + break; + case AF_INET6: + prefix->family = AF_INET6; + prefix->prefixlen = IPV6_MAX_BITLEN; + prefix->u.prefix6 = addr->ipv6; + break; + default: + zlog_warn ("%s: unknown address family %d", __func__, af); + break; + } +} + +void +zebra_register_rnh_pseudowire (vrf_id_t vrf_id, struct zebra_pw *pw) +{ + struct prefix nh; + struct rnh *rnh; + + addr2hostprefix (pw->af, &pw->nexthop, &nh); + rnh = zebra_add_rnh (&nh, vrf_id, RNH_NEXTHOP_TYPE); + if (rnh && !listnode_lookup (rnh->zebra_pseudowire_list, pw)) + { + listnode_add (rnh->zebra_pseudowire_list, pw); + pw->rnh = rnh; + zebra_evaluate_rnh (vrf_id, pw->af, 1, RNH_NEXTHOP_TYPE, &nh); + } +} + +void +zebra_deregister_rnh_pseudowire (vrf_id_t vrf_id, struct zebra_pw *pw) +{ + struct rnh *rnh; + + rnh = pw->rnh; + if (!rnh) + return; + + listnode_delete (rnh->zebra_pseudowire_list, pw); + pw->rnh = NULL; + + if (list_isempty (rnh->client_list) && + list_isempty (rnh->zebra_static_route_list) && + list_isempty (rnh->zebra_pseudowire_list)) + zebra_delete_rnh (rnh, RNH_NEXTHOP_TYPE); +} + /* Apply the NHT route-map for a client to the route (and nexthops) * resolving a NH. */ @@ -611,6 +671,16 @@ zebra_rnh_process_static_routes (vrf_id_t vrfid, int family, } } +static void +zebra_rnh_process_pseudowires (vrf_id_t vrfid, struct rnh *rnh) +{ + struct zebra_pw *pw; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO (rnh->zebra_pseudowire_list, node, pw)) + zebra_pw_update (pw); +} + /* * See if a tracked nexthop entry has undergone any change, and if so, * take appropriate action; this involves notifying any clients and/or @@ -655,6 +725,9 @@ zebra_rnh_eval_nexthop_entry (vrf_id_t vrfid, int family, int force, /* Process static routes attached to this nexthop */ zebra_rnh_process_static_routes (vrfid, family, nrn, rnh, prn, rnh->state); + + /* Process pseudowires attached to this nexthop */ + zebra_rnh_process_pseudowires (vrfid, rnh); } } @@ -717,7 +790,10 @@ zebra_rnh_clear_nhc_flag (vrf_id_t vrfid, int family, rnh_type_t type, rib = zebra_rnh_resolve_entry (vrfid, family, type, nrn, rnh, &prn); if (rib) - UNSET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED); + { + UNSET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED); + UNSET_FLAG (rib->status, RIB_ENTRY_LABELS_CHANGED); + } } /* Evaluate all tracked entries (nexthops or routes for import into BGP) @@ -868,7 +944,8 @@ compare_state (struct rib *r1, struct rib *r2) if (r1->nexthop_num != r2->nexthop_num) return 1; - if (CHECK_FLAG(r1->status, RIB_ENTRY_NEXTHOPS_CHANGED)) + if (CHECK_FLAG(r1->status, RIB_ENTRY_NEXTHOPS_CHANGED) || + CHECK_FLAG(r1->status, RIB_ENTRY_LABELS_CHANGED)) return 1; return 0; @@ -1030,6 +1107,8 @@ print_rnh (struct route_node *rn, struct vty *vty) 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, " zebra[static routes]%s", rnh->filtered[ZEBRA_ROUTE_STATIC] ? "(filtered)" : ""); + if (!list_isempty(rnh->zebra_pseudowire_list)) + vty_out(vty, " zebra[pseudowires]"); vty_out(vty, "%s", VTY_NEWLINE); } |
