From 8f77d0ee6c42ab240bd4ef8880dbf7a8b25e5553 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 16 Mar 2018 10:46:28 -0400 Subject: [PATCH 1/3] zebra: Apply label to all nexthops when needed The application of a label to a route entry needs to look at all non-recursive nexthops to be attached to instead of just the first one. Signed-off-by: Donald Sharp --- zebra/zebra_mpls.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 1868b4676d..8375d45d2f 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -2254,6 +2254,19 @@ void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf, fec_print(rn->info, vty); } +static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop, + enum lsp_types_t type, mpls_label_t label) +{ + if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE) + nexthop_add_labels(nexthop, type, 1, &label); + else if (!add && nexthop->nh_label_type == type) + nexthop_del_labels(nexthop); + else + return false; + + return true; +} + /* * Install/uninstall a FEC-To-NHLFE (FTN) binding. */ @@ -2266,6 +2279,7 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, struct route_node *rn; struct route_entry *re; struct nexthop *nexthop; + bool found; /* Lookup table. */ table = zebra_vrf_table(family2afi(prefix->family), SAFI_UNICAST, @@ -2285,6 +2299,7 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, if (re == NULL) return -1; + found = false; for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) { switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: @@ -2297,7 +2312,11 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX && nexthop->ifindex != ifindex) continue; - goto found; + if (!mpls_ftn_update_nexthop(add, nexthop, type, + out_label)) + return 0; + found = true; + break; case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: if (gtype != NEXTHOP_TYPE_IPV6 @@ -2308,21 +2327,18 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX && nexthop->ifindex != ifindex) continue; - goto found; + if (!mpls_ftn_update_nexthop(add, nexthop, type, + out_label)) + return 0; + found = true; + break; 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; + if (!found) + return -1; SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED); From 0acf4df0953ce594eee793d51fa79e2d9d097b60 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 16 Mar 2018 10:53:58 -0400 Subject: [PATCH 2/3] lib, zebra: Signal the existence of labels on a nexthop for nht When we are signaling to a client from zebra that a nexthop has changed, include the labels on the nexthop as well. Upper level protocols need to know if the labels exist in order to make intelligent decisions about what to do. Signed-off-by: Donald Sharp --- lib/zclient.c | 10 ++++++++++ zebra/zebra_rnh.c | 38 +++++++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/lib/zclient.c b/lib/zclient.c index 777f6fcf9b..2cac71ac45 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1340,6 +1340,16 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr) case NEXTHOP_TYPE_BLACKHOLE: break; } + STREAM_GETC(s, nhr->nexthops[i].label_num); + if (nhr->nexthops[i].label_num > MPLS_MAX_LABELS) { + zlog_warn("%s: invalid number of MPLS labels (%u)", + __func__, nhr->nexthops[i].label_num); + return false; + } + if (nhr->nexthops[i].label_num) + STREAM_GET(&nhr->nexthops[i].labels[0], s, + nhr->nexthops[i].label_num + * sizeof(mpls_label_t)); } return true; diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index c9fb782ba6..48f9f4f366 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -986,7 +986,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, struct route_entry *re; unsigned long nump; u_char num; - struct nexthop *nexthop; + struct nexthop *nh; struct route_node *rn; int cmd = (type == RNH_IMPORT_CHECK_TYPE) ? ZEBRA_IMPORT_CHECK_UPDATE : ZEBRA_NEXTHOP_UPDATE; @@ -1022,32 +1022,40 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, num = 0; nump = stream_get_endp(s); stream_putc(s, 0); - for (nexthop = re->ng.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) { + for (nh = re->ng.nexthop; nh; nh = nh->next) + if ((CHECK_FLAG(nh->flags, NEXTHOP_FLAG_FIB) + || CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE)) + && CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE)) { + stream_putc(s, nh->type); + switch (nh->type) { case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: - stream_put_in_addr(s, - &nexthop->gate.ipv4); - stream_putl(s, nexthop->ifindex); + stream_put_in_addr(s, &nh->gate.ipv4); + stream_putl(s, nh->ifindex); break; case NEXTHOP_TYPE_IFINDEX: - stream_putl(s, nexthop->ifindex); + stream_putl(s, nh->ifindex); break; case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_put(s, &nexthop->gate.ipv6, 16); - stream_putl(s, nexthop->ifindex); + stream_put(s, &nh->gate.ipv6, 16); + stream_putl(s, nh->ifindex); break; default: /* do nothing */ break; } + if (nh->nh_label) { + stream_putc(s, + nh->nh_label->num_labels); + if (nh->nh_label->num_labels) + stream_put( + s, + &nh->nh_label->label[0], + nh->nh_label->num_labels + * sizeof(mpls_label_t)); + } else + stream_putc(s, 0); num++; } stream_putc_at(s, nump, num); From 0ae8130def2a715ba366128805315fe5212e06c3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 16 Mar 2018 12:26:26 -0400 Subject: [PATCH 3/3] sharpd: Add ability to register for nht Add code to sharpd to allow it to register for nexthop tracking and then to display when it receives information about the nexthop it is watching. Signed-off-by: Donald Sharp --- sharpd/sharp_vty.c | 42 +++++++++++++++++++++++++++++++ sharpd/sharp_zebra.c | 60 ++++++++++++++++++++++++++++++++++++++++++++ sharpd/sharp_zebra.h | 1 + 3 files changed, 103 insertions(+) diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 3065ad19c3..4d19484a64 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -39,6 +39,46 @@ extern uint32_t total_routes; extern uint32_t installed_routes; extern uint32_t removed_routes; +DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd, + "sharp watch nexthop X:X::X:X$nhop", + "Sharp routing Protocol\n" + "Watch for changes\n" + "Watch for nexthop changes\n" + "The v6 nexthop to signal for watching\n") +{ + struct prefix p; + + memset(&p, 0, sizeof(p)); + + p.prefixlen = 128; + memcpy(&p.u.prefix6, &nhop, 16); + p.family = AF_INET6; + + sharp_zebra_nexthop_watch(&p, true); + + return CMD_SUCCESS; +} + +DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd, + "sharp watch nexthop A.B.C.D$nhop", + "Sharp routing Protocol\n" + "Watch for changes\n" + "Watch for nexthop changes\n" + "The v4 nexthop to signal for watching\n") +{ + struct prefix p; + + memset(&p, 0, sizeof(p)); + + p.prefixlen = 32; + p.u.prefix4 = nhop; + p.family = AF_INET; + + sharp_zebra_nexthop_watch(&p, true); + + return CMD_SUCCESS; +} + DEFPY (install_routes, install_routes_cmd, "sharp install routes A.B.C.D$start nexthop A.B.C.D$nexthop (1-1000000)$routes", @@ -147,5 +187,7 @@ void sharp_vty_init(void) install_element(ENABLE_NODE, &install_routes_cmd); install_element(ENABLE_NODE, &remove_routes_cmd); install_element(ENABLE_NODE, &vrf_label_cmd); + install_element(ENABLE_NODE, &watch_nexthop_v6_cmd); + install_element(ENABLE_NODE, &watch_nexthop_v4_cmd); return; } diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 8915397c7e..999255e925 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -214,6 +214,65 @@ void route_delete(struct prefix *p) return; } +void sharp_zebra_nexthop_watch(struct prefix *p, bool watch) +{ + int command = ZEBRA_NEXTHOP_REGISTER; + + if (!watch) + command = ZEBRA_NEXTHOP_UNREGISTER; + + zclient_send_rnh(zclient, command, p, true, VRF_DEFAULT); +} + +static int sharp_nexthop_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) +{ + struct zapi_route nhr; + char buf[PREFIX_STRLEN]; + int i; + + if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) { + zlog_warn("%s: Decode of update failed", __PRETTY_FUNCTION__); + + return 0; + } + + zlog_debug("Received update for %s", + prefix2str(&nhr.prefix, buf, sizeof(buf))); + for (i = 0; i < nhr.nexthop_num; i++) { + struct zapi_nexthop *znh = &nhr.nexthops[i]; + + switch (znh->type) { + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + zlog_debug( + "\tNexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d", + inet_ntop(AF_INET, &znh->gate.ipv4.s_addr, buf, + sizeof(buf)), + znh->type, znh->ifindex, znh->vrf_id, + znh->label_num); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + case NEXTHOP_TYPE_IPV6: + zlog_debug( + "\tNexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d", + inet_ntop(AF_INET6, &znh->gate.ipv6, buf, + sizeof(buf)), + znh->type, znh->ifindex, znh->vrf_id, + znh->label_num); + break; + case NEXTHOP_TYPE_IFINDEX: + zlog_debug("\tNexthop IFINDEX: %d, ifindex: %d", + znh->type, znh->ifindex); + break; + case NEXTHOP_TYPE_BLACKHOLE: + zlog_debug("\tNexthop blackhole"); + break; + } + } + return 0; +} + extern struct zebra_privs_t sharp_privs; void sharp_zebra_init(void) @@ -231,4 +290,5 @@ void sharp_zebra_init(void) zclient->interface_address_add = interface_address_add; zclient->interface_address_delete = interface_address_delete; zclient->route_notify_owner = route_notify_owner; + zclient->nexthop_update = sharp_nexthop_update; } diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h index 0bba443bd4..0c906fc4ff 100644 --- a/sharpd/sharp_zebra.h +++ b/sharpd/sharp_zebra.h @@ -27,4 +27,5 @@ extern void sharp_zebra_init(void); extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label); extern void route_add(struct prefix *p, struct nexthop *nh); extern void route_delete(struct prefix *p); +extern void sharp_zebra_nexthop_watch(struct prefix *p, bool watch); #endif