From bad6b0e72ea5730031b7851ee6c8e422cbb1f270 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Wed, 7 Aug 2019 21:06:03 -0300 Subject: [PATCH] lib: introduce encode/decode functions for the MPLS zapi messages Do this for the following reasons: * Improve modularity of the code by separating the decoding of the ZAPI messages from their processing; * Create an API that is easier to use by the client daemons. Signed-off-by: Renato Westphal --- ldpd/ldp_zebra.c | 43 ++++++++++-------------- lib/zclient.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/zclient.h | 16 +++++++++ ospfd/ospf_sr.c | 33 +++++++------------ zebra/zapi_msg.c | 70 ++++++++++----------------------------- 5 files changed, 148 insertions(+), 99 deletions(-) diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index 35a7d944d3..04e21e8026 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -37,7 +37,7 @@ static void ifp2kif(struct interface *, struct kif *); static void ifc2kaddr(struct interface *, struct connected *, struct kaddr *); -static int zebra_send_mpls_labels(int, struct kroute *); +static int ldp_zebra_send_mpls_labels(int, struct kroute *); static int ldp_router_id_update(ZAPI_CALLBACK_ARGS); static int ldp_interface_add(ZAPI_CALLBACK_ARGS); static int ldp_interface_delete(ZAPI_CALLBACK_ARGS); @@ -106,9 +106,9 @@ pw2zpw(struct l2vpn_pw *pw, struct zapi_pw *zpw) } static int -zebra_send_mpls_labels(int cmd, struct kroute *kr) +ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr) { - struct stream *s; + struct zapi_labels zl = {}; if (kr->local_label < MPLS_LABEL_RESERVED_MAX || kr->remote_label == NO_LABEL) @@ -120,48 +120,39 @@ zebra_send_mpls_labels(int cmd, struct kroute *kr) log_label(kr->local_label), log_label(kr->remote_label), (cmd == ZEBRA_MPLS_LABELS_ADD) ? "add" : "delete"); - /* Reset stream. */ - s = zclient->obuf; - stream_reset(s); - - zclient_create_header(s, cmd, VRF_DEFAULT); - stream_putc(s, ZEBRA_LSP_LDP); - stream_putl(s, kr->af); + zl.type = ZEBRA_LSP_LDP; + zl.prefix.family = kr->af; + zl.prefix.prefixlen = kr->prefixlen; switch (kr->af) { case AF_INET: - stream_put_in_addr(s, &kr->prefix.v4); - stream_putc(s, kr->prefixlen); - stream_put_in_addr(s, &kr->nexthop.v4); + zl.prefix.u.prefix4 = kr->prefix.v4; + zl.nexthop.ipv4 = kr->nexthop.v4; break; case AF_INET6: - stream_write(s, (uint8_t *)&kr->prefix.v6, 16); - stream_putc(s, kr->prefixlen); - stream_write(s, (uint8_t *)&kr->nexthop.v6, 16); + zl.prefix.u.prefix6 = kr->prefix.v6; + zl.nexthop.ipv6 = kr->nexthop.v6; break; default: fatalx("kr_change: unknown af"); } - stream_putl(s, kr->ifindex); - stream_putc(s, kr->priority); - stream_putl(s, kr->local_label); - stream_putl(s, kr->remote_label); - - /* Put length at the first point of the stream. */ - stream_putw_at(s, 0, stream_get_endp(s)); + zl.ifindex = kr->ifindex; + zl.distance = kr->priority; + zl.local_label = kr->local_label; + zl.remote_label = kr->remote_label; - return (zclient_send_message(zclient)); + return zebra_send_mpls_labels(zclient, cmd, &zl); } int kr_change(struct kroute *kr) { - return (zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_ADD, kr)); + return (ldp_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_ADD, kr)); } int kr_delete(struct kroute *kr) { - return (zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_DELETE, kr)); + return (ldp_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_DELETE, kr)); } int diff --git a/lib/zclient.c b/lib/zclient.c index f809704f86..81f0b81f62 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -2451,6 +2451,91 @@ int tm_release_table_chunk(struct zclient *zclient, uint32_t start, return zclient_send_message(zclient); } +int zebra_send_mpls_labels(struct zclient *zclient, int cmd, + struct zapi_labels *zl) +{ + if (zapi_labels_encode(zclient->obuf, cmd, zl) < 0) + return -1; + return zclient_send_message(zclient); +} + +int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl) +{ + stream_reset(s); + + zclient_create_header(s, cmd, VRF_DEFAULT); + stream_putc(s, zl->type); + stream_putw(s, zl->prefix.family); + stream_put_prefix(s, &zl->prefix); + switch (zl->prefix.family) { + case AF_INET: + stream_put_in_addr(s, &zl->nexthop.ipv4); + break; + case AF_INET6: + stream_write(s, (uint8_t *)&zl->nexthop.ipv6, 16); + break; + default: + flog_err(EC_LIB_ZAPI_ENCODE, "%s: unknown af", __func__); + return -1; + } + stream_putl(s, zl->ifindex); + stream_putc(s, zl->distance); + stream_putl(s, zl->local_label); + stream_putl(s, zl->remote_label); + + /* Put length at the first point of the stream. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + return 0; +} + +int zapi_labels_decode(struct stream *s, struct zapi_labels *zl) +{ + size_t psize; + + memset(zl, 0, sizeof(*zl)); + + /* Get data. */ + STREAM_GETC(s, zl->type); + STREAM_GETW(s, zl->prefix.family); + STREAM_GETC(s, zl->prefix.prefixlen); + psize = PSIZE(zl->prefix.prefixlen); + + switch (zl->prefix.family) { + case AF_INET: + if (zl->prefix.prefixlen > IPV4_MAX_BITLEN) { + zlog_debug( + "%s: Specified prefix length %d is greater than a v4 address can support", + __PRETTY_FUNCTION__, zl->prefix.prefixlen); + return -1; + } + STREAM_GET(&zl->prefix.u.prefix4.s_addr, s, psize); + STREAM_GET(&zl->nexthop.ipv4.s_addr, s, IPV4_MAX_BYTELEN); + break; + case AF_INET6: + if (zl->prefix.prefixlen > IPV6_MAX_BITLEN) { + zlog_debug( + "%s: Specified prefix length %d is greater than a v6 address can support", + __PRETTY_FUNCTION__, zl->prefix.prefixlen); + return -1; + } + STREAM_GET(&zl->prefix.u.prefix6, s, psize); + STREAM_GET(&zl->nexthop.ipv6, s, 16); + break; + default: + zlog_debug("%s: Specified AF %d is not supported for this call", + __PRETTY_FUNCTION__, zl->prefix.family); + return -1; + } + STREAM_GETL(s, zl->ifindex); + STREAM_GETC(s, zl->distance); + STREAM_GETL(s, zl->local_label); + STREAM_GETL(s, zl->remote_label); + + return 0; +stream_failure: + return -1; +} int zebra_send_pw(struct zclient *zclient, int command, struct zapi_pw *pw) { diff --git a/lib/zclient.h b/lib/zclient.h index 81e454d192..e665635a8a 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -395,6 +395,16 @@ struct zapi_route { uint32_t tableid; }; +struct zapi_labels { + enum lsp_types_t type; + struct prefix prefix; + union g_addr nexthop; + ifindex_t ifindex; + uint8_t distance; + mpls_label_t local_label; + mpls_label_t remote_label; +}; + struct zapi_pw { char ifname[IF_NAMESIZE]; ifindex_t ifindex; @@ -625,6 +635,12 @@ extern int tm_get_table_chunk(struct zclient *zclient, uint32_t chunk_size, extern int tm_release_table_chunk(struct zclient *zclient, uint32_t start, uint32_t end); +extern int zebra_send_mpls_labels(struct zclient *zclient, int cmd, + struct zapi_labels *zl); +extern int zapi_labels_encode(struct stream *s, int cmd, + struct zapi_labels *zl); +extern int zapi_labels_decode(struct stream *s, struct zapi_labels *zl); + extern int zebra_send_pw(struct zclient *zclient, int command, struct zapi_pw *pw); extern void zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS, struct zapi_pw_status *pw); diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c index 6947393a60..a361d17817 100644 --- a/ospfd/ospf_sr.c +++ b/ospfd/ospf_sr.c @@ -608,26 +608,7 @@ static int compute_prefix_nhlfe(struct sr_prefix *srp) /* Send MPLS Label entry to Zebra for installation or deletion */ static int ospf_zebra_send_mpls_labels(int cmd, struct sr_nhlfe nhlfe) { - struct stream *s; - - /* Reset stream. */ - s = zclient->obuf; - stream_reset(s); - - zclient_create_header(s, cmd, VRF_DEFAULT); - stream_putc(s, ZEBRA_LSP_SR); - /* OSPF Segment Routing currently support only IPv4 */ - stream_putl(s, nhlfe.prefv4.family); - stream_put_in_addr(s, &nhlfe.prefv4.prefix); - stream_putc(s, nhlfe.prefv4.prefixlen); - stream_put_in_addr(s, &nhlfe.nexthop); - stream_putl(s, nhlfe.ifindex); - stream_putc(s, OSPF_SR_PRIORITY_DEFAULT); - stream_putl(s, nhlfe.label_in); - stream_putl(s, nhlfe.label_out); - - /* Put length at the first point of the stream. */ - stream_putw_at(s, 0, stream_get_endp(s)); + struct zapi_labels zl = {}; if (IS_DEBUG_OSPF_SR) zlog_debug(" |- %s LSP %u/%u for %s/%u via %u", @@ -636,7 +617,17 @@ static int ospf_zebra_send_mpls_labels(int cmd, struct sr_nhlfe nhlfe) inet_ntoa(nhlfe.prefv4.prefix), nhlfe.prefv4.prefixlen, nhlfe.ifindex); - return zclient_send_message(zclient); + zl.type = ZEBRA_LSP_SR; + zl.prefix.family = nhlfe.prefv4.family; + zl.prefix.prefixlen = nhlfe.prefv4.prefixlen; + zl.prefix.u.prefix4 = nhlfe.prefv4.prefix; + zl.nexthop.ipv4 = nhlfe.nexthop; + zl.ifindex = nhlfe.ifindex; + zl.distance = OSPF_SR_PRIORITY_DEFAULT; + zl.local_label = nhlfe.label_in; + zl.remote_label = nhlfe.label_out; + + return zebra_send_mpls_labels(zclient, cmd, &zl); } /* Request zebra to install/remove FEC in FIB */ diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index fa6a2f62ec..6915d84c0d 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1752,62 +1752,27 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS) static void zread_mpls_labels(ZAPI_HANDLER_ARGS) { struct stream *s; - enum lsp_types_t type; - struct prefix prefix; + struct zapi_labels zl; enum nexthop_types_t gtype; - union g_addr gate; - ifindex_t ifindex; - mpls_label_t in_label, out_label; - uint8_t distance; /* Get input stream. */ s = msg; - - /* Get data. */ - STREAM_GETC(s, type); - STREAM_GETL(s, prefix.family); - switch (prefix.family) { - case AF_INET: - STREAM_GET(&prefix.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); - STREAM_GETC(s, prefix.prefixlen); - if (prefix.prefixlen > IPV4_MAX_BITLEN) { - zlog_debug( - "%s: Specified prefix length %d is greater than a v4 address can support", - __PRETTY_FUNCTION__, prefix.prefixlen); - return; - } - STREAM_GET(&gate.ipv4.s_addr, s, IPV4_MAX_BYTELEN); - break; - case AF_INET6: - STREAM_GET(&prefix.u.prefix6, s, 16); - STREAM_GETC(s, prefix.prefixlen); - if (prefix.prefixlen > IPV6_MAX_BITLEN) { - zlog_debug( - "%s: Specified prefix length %d is greater than a v6 address can support", - __PRETTY_FUNCTION__, prefix.prefixlen); - return; - } - STREAM_GET(&gate.ipv6, s, 16); - break; - default: - zlog_debug("%s: Specified AF %d is not supported for this call", - __PRETTY_FUNCTION__, prefix.family); + if (zapi_labels_decode(s, &zl) < 0) { + if (IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: Unable to decode zapi_labels sent", + __PRETTY_FUNCTION__); return; } - STREAM_GETL(s, ifindex); - STREAM_GETC(s, distance); - STREAM_GETL(s, in_label); - STREAM_GETL(s, out_label); - switch (prefix.family) { + switch (zl.prefix.family) { case AF_INET: - if (ifindex) + if (zl.ifindex) gtype = NEXTHOP_TYPE_IPV4_IFINDEX; else gtype = NEXTHOP_TYPE_IPV4; break; case AF_INET6: - if (ifindex) + if (zl.ifindex) gtype = NEXTHOP_TYPE_IPV6_IFINDEX; else gtype = NEXTHOP_TYPE_IPV6; @@ -1820,17 +1785,18 @@ static void zread_mpls_labels(ZAPI_HANDLER_ARGS) return; if (hdr->command == ZEBRA_MPLS_LABELS_ADD) { - mpls_lsp_install(zvrf, type, in_label, out_label, gtype, &gate, - ifindex); - mpls_ftn_update(1, zvrf, type, &prefix, gtype, &gate, ifindex, - distance, out_label); + mpls_lsp_install(zvrf, zl.type, zl.local_label, zl.remote_label, + gtype, &zl.nexthop, zl.ifindex); + mpls_ftn_update(1, zvrf, zl.type, &zl.prefix, gtype, + &zl.nexthop, zl.ifindex, zl.distance, + zl.remote_label); } else if (hdr->command == ZEBRA_MPLS_LABELS_DELETE) { - mpls_lsp_uninstall(zvrf, type, in_label, gtype, &gate, ifindex); - mpls_ftn_update(0, zvrf, type, &prefix, gtype, &gate, ifindex, - distance, out_label); + mpls_lsp_uninstall(zvrf, zl.type, zl.local_label, gtype, + &zl.nexthop, zl.ifindex); + mpls_ftn_update(0, zvrf, zl.type, &zl.prefix, gtype, + &zl.nexthop, zl.ifindex, zl.distance, + zl.remote_label); } -stream_failure: - return; } /* Send response to a table manager connect request to client */ -- 2.39.5