summaryrefslogtreecommitdiff
path: root/zebra/zebra_rnh.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_rnh.c')
-rw-r--r--zebra/zebra_rnh.c89
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);
}