diff options
Diffstat (limited to 'zebra/zserv.c')
| -rw-r--r-- | zebra/zserv.c | 172 |
1 files changed, 157 insertions, 15 deletions
diff --git a/zebra/zserv.c b/zebra/zserv.c index 3477dc36d2..416e5444ea 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -934,6 +934,109 @@ zserv_rnh_unregister (struct zserv *client, int sock, u_short length, return 0; } +#define ZEBRA_MIN_FEC_LENGTH 9 + +/* 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; + } + 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; +} + /* Modified version of zsend_ipv4_nexthop_lookup(): Query unicast rib if nexthop is not found on mrib. @@ -1075,13 +1178,15 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) struct rib *rib; struct prefix p; u_char message; - struct in_addr nexthop; + 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; @@ -1123,13 +1228,19 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) rib_nexthop_ifindex_add (rib, ifindex); break; case NEXTHOP_TYPE_IPV4: - nexthop.s_addr = stream_get_ipv4 (s); - rib_nexthop_ipv4_add (rib, &nexthop, NULL); + nhop_addr.s_addr = stream_get_ipv4 (s); + nexthop = rib_nexthop_ipv4_add (rib, &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: - nexthop.s_addr = stream_get_ipv4 (s); + nhop_addr.s_addr = stream_get_ipv4 (s); ifindex = stream_getl (s); - rib_nexthop_ipv4_ifindex_add (rib, &nexthop, NULL, ifindex); + rib_nexthop_ipv4_ifindex_add (rib, &nhop_addr, NULL, ifindex); break; case NEXTHOP_TYPE_IPV6: stream_forward_getp (s, IPV6_MAX_BYTELEN); @@ -1222,6 +1333,11 @@ zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) 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: @@ -1407,7 +1523,7 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) { unsigned int i; struct stream *s; - struct in6_addr nexthop; + struct in6_addr nhop_addr; struct rib *rib; u_char message; u_char nexthop_num; @@ -1418,11 +1534,14 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) 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 (&nexthop, 0, sizeof (struct in6_addr)); + memset (&nhop_addr, 0, sizeof (struct in6_addr)); /* Allocate new rib. */ rib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); @@ -1471,10 +1590,17 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) switch (nexthop_type) { case NEXTHOP_TYPE_IPV6: - stream_get (&nexthop, s, 16); - if (nh_count < multipath_num) { - nexthops[nh_count++] = nexthop; - } + 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) { @@ -1492,9 +1618,11 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) { if ((i < nh_count) && !IN6_IS_ADDR_UNSPECIFIED (&nexthops[i])) { if ((i < if_count) && ifindices[i]) - rib_nexthop_ipv6_ifindex_add (rib, &nexthops[i], ifindices[i]); + nexthop = rib_nexthop_ipv6_ifindex_add (rib, &nexthops[i], ifindices[i]); else - rib_nexthop_ipv6_add (rib, &nexthops[i]); + nexthop = rib_nexthop_ipv6_add (rib, &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]) @@ -1591,6 +1719,11 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) { 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: @@ -1761,14 +1894,14 @@ zread_mpls_labels (int command, struct zserv *client, u_short length, if (command == ZEBRA_MPLS_LABELS_ADD) { mpls_lsp_install (zvrf, type, in_label, out_label, gtype, &gate, - NULL, ifindex); + 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, NULL, ifindex); + 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); @@ -1975,6 +2108,9 @@ zebra_client_close (struct zserv *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) { @@ -2263,6 +2399,12 @@ zebra_client_read (struct thread *thread) 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; default: zlog_info ("Zebra received unknown command %d", command); break; |
