From c83c5e4482580351d20fb45dc643c368866e33d8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 30 Jan 2018 13:30:36 -0500 Subject: [PATCH] lib, zebra: Add new api to specify a label associated with the vrf For L3VPN's we need to create a label associated with the specified vrf to be installed into the kernel to allow a pop and lookup operation. The new api is: zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id, mpls_label_t label); For the specified vrf_id associate the specified label for a pop and lookup operation for forwarding. To setup a POP and Forward use MPLS_LABEL_IMPLICIT_NULL If the same label is passed in we ignore the call. If the label is different we update entry. If the label is MPLS_LABEL_NONE we remove the entry. This sets up the api. Future commits will have the functionality to actually install into the kernel. Signed-off-by: Donald Sharp --- lib/log.c | 1 + lib/zclient.c | 14 ++++++++++++++ lib/zclient.h | 12 ++++++++++++ zebra/zebra_vrf.h | 3 +++ zebra/zserv.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+) diff --git a/lib/log.c b/lib/log.c index 66be533e84..9fc19ff683 100644 --- a/lib/log.c +++ b/lib/log.c @@ -929,6 +929,7 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_VRF_UNREGISTER), DESC_ENTRY(ZEBRA_VRF_ADD), DESC_ENTRY(ZEBRA_VRF_DELETE), + DESC_ENTRY(ZEBRA_VRF_LABEL), DESC_ENTRY(ZEBRA_INTERFACE_VRF_UPDATE), DESC_ENTRY(ZEBRA_BFD_CLIENT_REGISTER), DESC_ENTRY(ZEBRA_INTERFACE_ENABLE_RADV), diff --git a/lib/zclient.c b/lib/zclient.c index 6882a7ecc5..9327201f73 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -363,6 +363,20 @@ static int zebra_hello_send(struct zclient *zclient) return 0; } +void zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id, + mpls_label_t label) +{ + struct stream *s; + + s = zclient->obuf; + stream_reset(s); + + zclient_create_header(s, ZEBRA_VRF_LABEL, vrf_id); + stream_putl(s, label); + stream_putw_at(s, 0, stream_get_endp(s)); + zclient_send_message(zclient); +} + /* Send register requests to zebra daemon for the information in a VRF. */ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id) { diff --git a/lib/zclient.h b/lib/zclient.h index 910d25aa2f..6b39a2713a 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -93,6 +93,7 @@ typedef enum { ZEBRA_VRF_UNREGISTER, ZEBRA_VRF_ADD, ZEBRA_VRF_DELETE, + ZEBRA_VRF_LABEL, ZEBRA_INTERFACE_VRF_UPDATE, ZEBRA_BFD_CLIENT_REGISTER, ZEBRA_INTERFACE_ENABLE_RADV, @@ -382,6 +383,17 @@ extern u_short *redist_check_instance(struct redist_proto *, u_short); extern void redist_add_instance(struct redist_proto *, u_short); extern void redist_del_instance(struct redist_proto *, u_short); +/* + * Send to zebra that the specified vrf is using label to resolve + * itself for L3VPN's. Repeated calls of this function with + * different labels will cause an effective update of the + * label for lookup. If you pass in MPLS_V4_EXP_NULL_LABEL + * we will cause a delete action and remove this label pop + * operation. + */ +extern void zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id, + mpls_label_t label); + extern void zclient_send_reg_requests(struct zclient *, vrf_id_t); extern void zclient_send_dereg_requests(struct zclient *, vrf_id_t); diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index fe7e77e8be..bfeb4b386c 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -79,6 +79,9 @@ struct zebra_vrf { */ struct zebra_ns *zns; + /* MPLS Label to handle L3VPN <-> vrf popping */ + mpls_label_t label; + /* MPLS static LSP config table */ struct hash *slsp_table; diff --git a/zebra/zserv.c b/zebra/zserv.c index 9da8d593e5..5f2757f52c 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -2486,6 +2486,51 @@ stream_failure: return 1; } +static void zread_vrf_label(struct zserv *client, + struct zebra_vrf *zvrf) +{ + struct interface *ifp; + mpls_label_t nlabel; + struct stream *s; + struct zebra_vrf *def_zvrf; + + s = client->ibuf; + STREAM_GETL(s, nlabel); + + if (nlabel == zvrf->label) { + /* + * Nothing to do here move along + */ + return; + } + + if (zvrf->vrf->vrf_id != VRF_DEFAULT) + ifp = if_lookup_by_name(zvrf->vrf->name, zvrf->vrf->vrf_id); + else + ifp = if_lookup_by_name("lo", VRF_DEFAULT); + + if (!ifp) { + zlog_debug("Unable to find specified Interface for %s", + zvrf->vrf->name); + return; + } + + def_zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); + + if (zvrf->label != MPLS_LABEL_IPV4NULL) + mpls_lsp_uninstall(def_zvrf, ZEBRA_LSP_STATIC, + zvrf->label, NEXTHOP_TYPE_IFINDEX, + NULL, ifp->ifindex); + + if (nlabel != MPLS_LABEL_IPV4NULL) + mpls_lsp_install(def_zvrf, ZEBRA_LSP_STATIC, nlabel, + MPLS_LABEL_IMPLICIT_NULL, NEXTHOP_TYPE_IFINDEX, NULL, ifp->ifindex); + + zvrf->label = nlabel; +stream_failure: + return; +} + static inline void zserv_handle_commands(struct zserv *client, uint16_t command, uint16_t length, @@ -2570,6 +2615,9 @@ static inline void zserv_handle_commands(struct zserv *client, case ZEBRA_VRF_UNREGISTER: zread_vrf_unregister(client, length, zvrf); break; + case ZEBRA_VRF_LABEL: + zread_vrf_label(client, zvrf); + break; case ZEBRA_BFD_CLIENT_REGISTER: zebra_ptm_bfd_client_register(client, length); break; -- 2.39.5