From 9ebbb5c41620066d45915020569db9e4316450a5 Mon Sep 17 00:00:00 2001 From: John Lo Date: Thu, 11 Jun 2020 00:20:45 -0400 Subject: gtpu: support separate rx-decap and encap-tx teid values Support separate local and remote TEIDs, with local (or RX) one used for GTPU tunnel RX/decap and remote (or TX) one used encap/TX. Updated current gtpu API to support seperate RX/TX TEIDs and added new gtpu_tunnel_update_tteid API to allow changing TX-TEID of an existing GTPU tunnel. The current tunnel field "teid" is used for RX-TEID and a new field "tteid" is used for TX-TEID. Type: improvement Signed-off-by: John Lo Change-Id: I549d79750a34bb965036da298c0ca894d15c2c20 --- src/plugins/gtpu/gtpu.api | 33 ++++++++++++--- src/plugins/gtpu/gtpu.c | 95 +++++++++++++++++++++++++++--------------- src/plugins/gtpu/gtpu.h | 19 +++++---- src/plugins/gtpu/gtpu_api.c | 55 +++++++++++++++++++------ src/plugins/gtpu/gtpu_encap.c | 10 ++--- src/plugins/gtpu/gtpu_test.c | 96 ++++++++++++++++++++++++++++++++++++------- 6 files changed, 232 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/plugins/gtpu/gtpu.api b/src/plugins/gtpu/gtpu.api index f084cc84e19..ec4933af197 100644 --- a/src/plugins/gtpu/gtpu.api +++ b/src/plugins/gtpu/gtpu.api @@ -13,11 +13,11 @@ * limitations under the License. */ -option version = "2.0.0"; +option version = "2.0.1"; import "vnet/interface_types.api"; import "vnet/ip/ip_types.api"; -/** \brief Set or delete an GTPU tunnel +/** \brief Create or delete a GTPU tunnel @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param is_add - add address if non-zero, else delete @@ -26,7 +26,8 @@ import "vnet/ip/ip_types.api"; @param mcast_sw_if_index - version, O-bit and C-bit (see nsh_packet.h) @param encap_vrf_id - fib identifier used for outgoing encapsulated packets @param decap_next_index - the index of the next node if success - @param teid - Local Tunnel Endpoint Identifier + @param teid - Local (rx) Tunnel Endpoint Identifier + @param tteid - Remote (tx) Tunnel Endpoint Identifier */ define gtpu_add_del_tunnel { @@ -39,7 +40,8 @@ define gtpu_add_del_tunnel u32 encap_vrf_id; u32 decap_next_index; u32 teid; - option vat_help = "src { dst | group { | mcast_sw_if_index } } teid [encap-vrf-id ] [decap-next ] [del]"; + u32 tteid; + option vat_help = "src {dst | group { | mcast_sw_if_index }} teid [tteid ] [encap-vrf-id ] [decap-next ] [del]"; }; /** \brief reply for set or delete an GTPU tunnel @@ -54,6 +56,25 @@ define gtpu_add_del_tunnel_reply vl_api_interface_index_t sw_if_index; }; +/** \brief Update GTPU tunnel TX TEID + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param dst_address - GTPU tunnel's destination address. + @param encap_vrf_id - fib identifier used for outgoing encapsulated packets + @param teid - Local (rx) Tunnel Endpoint Identifier + @param tteid - remote (tx) Tunnel Endpoint Identifier +*/ +autoreply define gtpu_tunnel_update_tteid +{ + u32 client_index; + u32 context; + vl_api_address_t dst_address; + u32 encap_vrf_id; + u32 teid; + u32 tteid; + option vat_help = "dst teid tteid [encap-vrf-id ]"; +}; + /** \brief Dump GTPU tunnel @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @@ -75,7 +96,8 @@ define gtpu_tunnel_dump @param mcast_sw_if_index - version, O-bit and C-bit (see nsh_packet.h) @param encap_vrf_id - fib identifier used for outgoing encapsulated packets @param decap_next_index - the index of the next node if success - @param teid - Local Tunnel Endpoint Identifier + @param teid - Local (rx) Tunnel Endpoint Identifier + @param tteid - Remote (tx) Tunnel Endpoint Identifier */ define gtpu_tunnel_details { @@ -87,6 +109,7 @@ define gtpu_tunnel_details u32 encap_vrf_id; u32 decap_next_index; u32 teid; + u32 tteid; }; /** \brief Interface set gtpu-bypass request diff --git a/src/plugins/gtpu/gtpu.c b/src/plugins/gtpu/gtpu.c index 386721b6b39..ab221f1f562 100644 --- a/src/plugins/gtpu/gtpu.c +++ b/src/plugins/gtpu/gtpu.c @@ -56,8 +56,8 @@ u8 * format_gtpu_encap_trace (u8 * s, va_list * args) gtpu_encap_trace_t * t = va_arg (*args, gtpu_encap_trace_t *); - s = format (s, "GTPU encap to gtpu_tunnel%d teid %d", - t->tunnel_index, t->teid); + s = format (s, "GTPU encap to gtpu_tunnel%d tteid %d", + t->tunnel_index, t->tteid); return s; } @@ -95,11 +95,12 @@ format_gtpu_tunnel (u8 * s, va_list * args) is_ipv6 ? im6->fibs[t->encap_fib_index].ft_table_id : im4->fibs[t->encap_fib_index].ft_table_id; - s = format (s, "[%d] src %U dst %U teid %d encap-vrf-id %d sw-if-idx %d ", + s = format (s, "[%d] src %U dst %U teid %d tteid %d " + "encap-vrf-id %d sw-if-idx %d ", t - ngm->tunnels, format_ip46_address, &t->src, IP46_TYPE_ANY, format_ip46_address, &t->dst, IP46_TYPE_ANY, - t->teid, encap_vrf_id, t->sw_if_index); + t->teid, t->tteid, encap_vrf_id, t->sw_if_index); s = format (s, "encap-dpo-idx %d ", t->next_dpo.dpoi_index); s = format (s, "decap-next-%U ", format_decap_next, t->decap_next_index); @@ -225,7 +226,8 @@ const static fib_node_vft_t gtpu_vft = { #define foreach_copy_field \ -_(teid) \ +_(teid) \ +_(tteid) \ _(mcast_sw_if_index) \ _(encap_fib_index) \ _(decap_next_index) \ @@ -286,7 +288,7 @@ ip_udp_gtpu_rewrite (gtpu_tunnel_t * t, bool is_ip6) /* GTPU header */ gtpu->ver_flags = GTPU_V1_VER | GTPU_PT_GTP; gtpu->type = GTPU_TYPE_GTPU; - gtpu->teid = clib_host_to_net_u32 (t->teid); + gtpu->teid = clib_host_to_net_u32 (t->tteid); t->rewrite = r.rw; /* Now only support 8-byte gtpu header. TBD */ @@ -347,8 +349,8 @@ mcast_shared_remove (ip46_address_t * dst) hash_unset_mem_free (>pu_main.mcast_shared, dst); } -int vnet_gtpu_add_del_tunnel - (vnet_gtpu_add_del_tunnel_args_t * a, u32 * sw_if_indexp) +int vnet_gtpu_add_mod_del_tunnel + (vnet_gtpu_add_mod_del_tunnel_args_t * a, u32 * sw_if_indexp) { gtpu_main_t *gtm = >pu_main; gtpu_tunnel_t *t = 0; @@ -373,7 +375,7 @@ int vnet_gtpu_add_del_tunnel p = hash_get_mem (gtm->gtpu6_tunnel_by_key, &key6); } - if (a->is_add) + if (a->opn == GTPU_ADD_TUNNEL) { l2input_main_t *l2im = &l2input_main; @@ -395,6 +397,10 @@ int vnet_gtpu_add_del_tunnel foreach_copy_field; #undef _ + /* default to same as local rx teid */ + if (t->tteid == 0) + t->tteid = t->teid; + ip_udp_gtpu_rewrite (t, is_ip6); /* clear the flow index */ @@ -559,13 +565,23 @@ int vnet_gtpu_add_del_tunnel } else { - /* deleting a tunnel: tunnel must exist */ + /* mod-tteid or deleting a tunnel: tunnel must exist */ if (!p) return VNET_API_ERROR_NO_SUCH_ENTRY; t = pool_elt_at_index (gtm->tunnels, p[0]); sw_if_index = t->sw_if_index; + if (a->opn == GTPU_UPD_TTEID) + { + if (a->tteid == 0) + return VNET_API_ERROR_INVALID_VALUE; + t->tteid = a->tteid; + ip_udp_gtpu_rewrite (t, is_ip6); + return 0; + } + + /* delete tunnel */ vnet_sw_interface_set_flags (vnm, t->sw_if_index, 0 /* down */ ); vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, t->sw_if_index); si->flags |= VNET_SW_INTERFACE_FLAG_HIDDEN; @@ -604,7 +620,7 @@ int vnet_gtpu_add_del_tunnel if (sw_if_indexp) *sw_if_indexp = sw_if_index; - if (a->is_add) + if (a->opn == GTPU_ADD_TUNNEL) { /* register udp ports */ if (!is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_GTPU, 1)) @@ -662,7 +678,7 @@ gtpu_add_del_tunnel_command_fn (vlib_main_t * vm, { unformat_input_t _line_input, *line_input = &_line_input; ip46_address_t src, dst; - u8 is_add = 1; + u8 opn = GTPU_ADD_TUNNEL; u8 src_set = 0; u8 dst_set = 0; u8 grp_set = 0; @@ -671,10 +687,10 @@ gtpu_add_del_tunnel_command_fn (vlib_main_t * vm, u32 encap_fib_index = 0; u32 mcast_sw_if_index = ~0; u32 decap_next_index = GTPU_INPUT_NEXT_L2_INPUT; - u32 teid = 0; + u32 teid = 0, tteid = 0; u32 tmp; int rv; - vnet_gtpu_add_del_tunnel_args_t _a, *a = &_a; + vnet_gtpu_add_mod_del_tunnel_args_t _a, *a = &_a; u32 tunnel_sw_if_index; clib_error_t *error = NULL; @@ -690,7 +706,7 @@ gtpu_add_del_tunnel_command_fn (vlib_main_t * vm, { if (unformat (line_input, "del")) { - is_add = 0; + opn = GTPU_DEL_TUNNEL; } else if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4)) @@ -747,6 +763,10 @@ gtpu_add_del_tunnel_command_fn (vlib_main_t * vm, ; else if (unformat (line_input, "teid %d", &teid)) ; + else if (unformat (line_input, "tteid %d", &tteid)) + ; + else if (unformat (line_input, "upd-tteid %d", &tteid)) + opn = GTPU_UPD_TTEID; else { error = clib_error_return (0, "parse error: '%U'", @@ -755,7 +775,13 @@ gtpu_add_del_tunnel_command_fn (vlib_main_t * vm, } } - if (src_set == 0) + if (teid == 0) + { + error = clib_error_return (0, "tunnel teid specified"); + goto done; + } + + if (src_set == 0 && opn == GTPU_ADD_TUNNEL) { error = clib_error_return (0, "tunnel src address not specified"); goto done; @@ -805,18 +831,18 @@ gtpu_add_del_tunnel_command_fn (vlib_main_t * vm, clib_memset (a, 0, sizeof (*a)); - a->is_add = is_add; + a->opn = opn; #define _(x) a->x = x; foreach_copy_field; #undef _ - rv = vnet_gtpu_add_del_tunnel (a, &tunnel_sw_if_index); + rv = vnet_gtpu_add_mod_del_tunnel (a, &tunnel_sw_if_index); switch (rv) { case 0: - if (is_add) + if (opn == GTPU_ADD_TUNNEL) vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (), tunnel_sw_if_index); break; @@ -829,6 +855,10 @@ gtpu_add_del_tunnel_command_fn (vlib_main_t * vm, error = clib_error_return (0, "tunnel does not exist..."); goto done; + case VNET_API_ERROR_INVALID_VALUE: + error = clib_error_return (0, "tx teid not specified..."); + goto done; + default: error = clib_error_return (0, "vnet_gtpu_add_del_tunnel returned %d", rv); @@ -844,30 +874,31 @@ done: /*? * Add or delete a GTPU Tunnel. * - * GTPU provides the features needed to allow L2 bridge domains (BDs) + * GTPU can be used to transport Ethernet packets as its PDU type to + * provides allow L2 network or bridge domains (BDs) * to span multiple servers. This is done by building an L2 overlay on * top of an L3 network underlay using GTPU tunnels. * - * This makes it possible for servers to be co-located in the same data - * center or be separated geographically as long as they are reachable - * through the underlay L3 network. - * - * You can refer to this kind of L2 overlay bridge domain as a GTPU - * (Virtual eXtensible VLAN) segment. + * GTPU can also be used to transport IP packetes as its PDU type to + * allow IP forwarding over underlay network, e.g. between RAN and UPF + * for mobility deplyments. * * @cliexpar * Example of how to create a GTPU Tunnel: - * @cliexcmd{create gtpu tunnel src 10.0.3.1 dst 10.0.3.3 teid 13 encap-vrf-id 7} + * @cliexcmd{create gtpu tunnel src 10.0.3.1 dst 10.0.3.3 teid 13 tteid 55 encap-vrf-id 7} * Example of how to delete a GTPU Tunnel: - * @cliexcmd{create gtpu tunnel src 10.0.3.1 dst 10.0.3.3 teid 13 del} + * @cliexcmd{create gtpu tunnel src 10.0.3.1 dst 10.0.3.3 teid 13 encap-vrf-id 7 del} + * Example of how to update tx TEID of a GTPU Tunnel: + * @cliexcmd{create gtpu tunnel src 10.0.3.1 dst 10.0.3.3 encap-vrf-id 7 upd-tteid 55} ?*/ /* *INDENT-OFF* */ VLIB_CLI_COMMAND (create_gtpu_tunnel_command, static) = { .path = "create gtpu tunnel", .short_help = - "create gtpu tunnel src " - " {dst |group } teid " - " [encap-vrf-id ] [decap-next [l2|ip4|ip6|node ]] [del]", + "create gtpu tunnel src " + " {dst |group }" + " teid [tteid ] [encap-vrf-id ]" + " [decap-next [l2|ip4|ip6|node ]] [del | upd-tteid ]", .function = gtpu_add_del_tunnel_command_fn, }; /* *INDENT-ON* */ @@ -899,7 +930,7 @@ show_gtpu_tunnel_command_fn (vlib_main_t * vm, * @cliexpar * Example of how to display the GTPU Tunnel entries: * @cliexstart{show gtpu tunnel} - * [0] src 10.0.3.1 dst 10.0.3.3 teid 13 encap_fib_index 0 sw_if_index 5 decap_next l2 + * [0] src 10.0.3.1 dst 10.0.3.3 teid 13 tx-teid 55 encap_fib_index 0 sw_if_index 5 decap_next l2 * @cliexend ?*/ /* *INDENT-OFF* */ diff --git a/src/plugins/gtpu/gtpu.h b/src/plugins/gtpu/gtpu.h index 6a758ee6847..07616419070 100644 --- a/src/plugins/gtpu/gtpu.h +++ b/src/plugins/gtpu/gtpu.h @@ -135,8 +135,9 @@ typedef struct /* FIB DPO for IP forwarding of gtpu encap packet */ dpo_id_t next_dpo; - /* gtpu teid in HOST byte order */ + /* gtpu local(rx) and remote(tx) TEIDs in HOST byte order */ u32 teid; + u32 tteid; /* tunnel src and dst addresses */ ip46_address_t src; @@ -248,21 +249,25 @@ u8 *format_gtpu_encap_trace (u8 * s, va_list * args); typedef struct { - u8 is_add; + u8 opn; +#define GTPU_DEL_TUNNEL 0 +#define GTPU_ADD_TUNNEL 1 +#define GTPU_UPD_TTEID 2 ip46_address_t src, dst; u32 mcast_sw_if_index; u32 encap_fib_index; u32 decap_next_index; - u32 teid; -} vnet_gtpu_add_del_tunnel_args_t; + u32 teid; /* local or rx teid */ + u32 tteid; /* remote or tx teid */ +} vnet_gtpu_add_mod_del_tunnel_args_t; -int vnet_gtpu_add_del_tunnel - (vnet_gtpu_add_del_tunnel_args_t * a, u32 * sw_if_indexp); +int vnet_gtpu_add_mod_del_tunnel + (vnet_gtpu_add_mod_del_tunnel_args_t * a, u32 * sw_if_indexp); typedef struct { u32 tunnel_index; - u32 teid; + u32 tteid; } gtpu_encap_trace_t; void vnet_int_gtpu_bypass_mode (u32 sw_if_index, u8 is_ip6, u8 is_enable); diff --git a/src/plugins/gtpu/gtpu_api.c b/src/plugins/gtpu/gtpu_api.c index 24fb8e2eae2..1100a7f90c1 100644 --- a/src/plugins/gtpu/gtpu_api.c +++ b/src/plugins/gtpu/gtpu_api.c @@ -116,26 +116,27 @@ static void vl_api_gtpu_add_del_tunnel_t_handler { vl_api_gtpu_add_del_tunnel_reply_t *rmp; int rv = 0; - ip4_main_t *im = &ip4_main; gtpu_main_t *gtm = >pu_main; - uword *p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id)); - if (!p) - { - rv = VNET_API_ERROR_NO_SUCH_FIB; - goto out; - } - - vnet_gtpu_add_del_tunnel_args_t a = { - .is_add = mp->is_add, + vnet_gtpu_add_mod_del_tunnel_args_t a = { + .opn = mp->is_add ? GTPU_ADD_TUNNEL : GTPU_DEL_TUNNEL, .mcast_sw_if_index = ntohl (mp->mcast_sw_if_index), - .encap_fib_index = p[0], .decap_next_index = ntohl (mp->decap_next_index), .teid = ntohl (mp->teid), + .tteid = ntohl (mp->tteid), }; ip_address_decode (&mp->dst_address, &a.dst); ip_address_decode (&mp->src_address, &a.src); + u8 is_ipv6 = !ip46_address_is_ip4 (&a.dst); + a.encap_fib_index = fib_table_find (fib_ip_proto (is_ipv6), + ntohl (mp->encap_vrf_id)); + if (a.encap_fib_index == ~0) + { + rv = VNET_API_ERROR_NO_SUCH_FIB; + goto out; + } + /* Check src & dst are different */ if (ip46_address_cmp (&a.dst, &a.src) == 0) { @@ -150,7 +151,7 @@ static void vl_api_gtpu_add_del_tunnel_t_handler } u32 sw_if_index = ~0; - rv = vnet_gtpu_add_del_tunnel (&a, &sw_if_index); + rv = vnet_gtpu_add_mod_del_tunnel (&a, &sw_if_index); out: /* *INDENT-OFF* */ @@ -161,6 +162,35 @@ out: /* *INDENT-ON* */ } +static void vl_api_gtpu_tunnel_update_tteid_t_handler + (vl_api_gtpu_tunnel_update_tteid_t * mp) +{ + vl_api_gtpu_tunnel_update_tteid_reply_t *rmp; + int rv = 0; + gtpu_main_t *gtm = >pu_main; + + vnet_gtpu_add_mod_del_tunnel_args_t a = { + .opn = GTPU_UPD_TTEID, + .teid = ntohl (mp->teid), + .tteid = ntohl (mp->tteid), + }; + ip_address_decode (&mp->dst_address, &a.dst); + + u8 is_ipv6 = !ip46_address_is_ip4 (&a.dst); + a.encap_fib_index = fib_table_find (fib_ip_proto (is_ipv6), + ntohl (mp->encap_vrf_id)); + if (a.encap_fib_index == ~0) + { + rv = VNET_API_ERROR_NO_SUCH_FIB; + goto out; + } + + rv = vnet_gtpu_add_mod_del_tunnel (&a, 0); + +out: + REPLY_MACRO (VL_API_GTPU_TUNNEL_UPDATE_TTEID_REPLY); +} + static void send_gtpu_tunnel_details (gtpu_tunnel_t * t, vl_api_registration_t * reg, u32 context) { @@ -184,6 +214,7 @@ static void send_gtpu_tunnel_details htonl (im4->fibs[t->encap_fib_index].ft_table_id); rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index); rmp->teid = htonl (t->teid); + rmp->tteid = htonl (t->tteid); rmp->decap_next_index = htonl (t->decap_next_index); rmp->sw_if_index = htonl (t->sw_if_index); rmp->context = context; diff --git a/src/plugins/gtpu/gtpu_encap.c b/src/plugins/gtpu/gtpu_encap.c index e6b2ce589d0..4b7d98786f4 100644 --- a/src/plugins/gtpu/gtpu_encap.c +++ b/src/plugins/gtpu/gtpu_encap.c @@ -465,7 +465,7 @@ gtpu_encap_inline (vlib_main_t * vm, gtpu_encap_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); tr->tunnel_index = t0 - gtm->tunnels; - tr->teid = t0->teid; + tr->tteid = t0->tteid; } if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED)) @@ -473,7 +473,7 @@ gtpu_encap_inline (vlib_main_t * vm, gtpu_encap_trace_t *tr = vlib_add_trace (vm, node, b1, sizeof (*tr)); tr->tunnel_index = t1 - gtm->tunnels; - tr->teid = t1->teid; + tr->tteid = t1->tteid; } if (PREDICT_FALSE(b2->flags & VLIB_BUFFER_IS_TRACED)) @@ -481,7 +481,7 @@ gtpu_encap_inline (vlib_main_t * vm, gtpu_encap_trace_t *tr = vlib_add_trace (vm, node, b2, sizeof (*tr)); tr->tunnel_index = t2 - gtm->tunnels; - tr->teid = t2->teid; + tr->tteid = t2->tteid; } if (PREDICT_FALSE(b3->flags & VLIB_BUFFER_IS_TRACED)) @@ -489,7 +489,7 @@ gtpu_encap_inline (vlib_main_t * vm, gtpu_encap_trace_t *tr = vlib_add_trace (vm, node, b3, sizeof (*tr)); tr->tunnel_index = t3 - gtm->tunnels; - tr->teid = t3->teid; + tr->tteid = t3->tteid; } vlib_validate_buffer_enqueue_x4 (vm, node, next_index, @@ -643,7 +643,7 @@ gtpu_encap_inline (vlib_main_t * vm, gtpu_encap_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); tr->tunnel_index = t0 - gtm->tunnels; - tr->teid = t0->teid; + tr->tteid = t0->tteid; } vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, diff --git a/src/plugins/gtpu/gtpu_test.c b/src/plugins/gtpu/gtpu_test.c index c780bd77d85..373e7888341 100644 --- a/src/plugins/gtpu/gtpu_test.c +++ b/src/plugins/gtpu/gtpu_test.c @@ -13,6 +13,7 @@ * limitations under the License. */ +#include #include #include #include @@ -245,7 +246,7 @@ api_gtpu_add_del_tunnel (vat_main_t * vam) u32 mcast_sw_if_index = ~0; u32 encap_vrf_id = 0; u32 decap_next_index = ~0; - u32 teid = 0; + u32 teid = 0, tteid = 0; int ret; /* Can't "universally zero init" (={0}) due to GCC bug 53119 */ @@ -316,6 +317,8 @@ api_gtpu_add_del_tunnel (vat_main_t * vam) ; else if (unformat (line_input, "teid %d", &teid)) ; + else if (unformat (line_input, "tteid %d", &tteid)) + ; else { errmsg ("parse error '%U'", format_unformat_error, line_input); @@ -323,7 +326,7 @@ api_gtpu_add_del_tunnel (vat_main_t * vam) } } - if (src_set == 0) + if (is_add && src_set == 0) { errmsg ("tunnel src address not specified"); return -99; @@ -367,6 +370,7 @@ api_gtpu_add_del_tunnel (vat_main_t * vam) mp->decap_next_index = ntohl (decap_next_index); mp->mcast_sw_if_index = ntohl (mcast_sw_if_index); mp->teid = ntohl (teid); + mp->tteid = ntohl (tteid); mp->is_add = is_add; S (mp); @@ -374,6 +378,64 @@ api_gtpu_add_del_tunnel (vat_main_t * vam) return ret; } +static int +api_gtpu_tunnel_update_tteid (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_gtpu_tunnel_update_tteid_t *mp; + ip46_address_t dst; + u8 ipv6_set = 0; + u8 dst_set = 0; + u32 encap_vrf_id = 0; + u32 teid = 0, tteid = 0; + int ret; + + /* Can't "universally zero init" (={0}) due to GCC bug 53119 */ + clib_memset (&dst, 0, sizeof dst); + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "dst %U", unformat_ip4_address, &dst.ip4)) + { + dst_set = 1; + } + else if (unformat (line_input, "dst %U", unformat_ip6_address, &dst.ip6)) + { + ipv6_set = 1; + dst_set = 1; + } + else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id)) + ; + else if (unformat (line_input, "teid %d", &teid)) + ; + else if (unformat (line_input, "tteid %d", &tteid)) + ; + else + { + errmsg ("parse error '%U'", format_unformat_error, line_input); + return -99; + } + } + + if (dst_set == 0) + { + errmsg ("tunnel dst address not specified"); + return -99; + } + + M (GTPU_TUNNEL_UPDATE_TTEID, mp); + + ip_address_encode(&dst, ipv6_set ? IP46_TYPE_IP6 : IP46_TYPE_IP4, + &mp->dst_address); + mp->encap_vrf_id = ntohl (encap_vrf_id); + mp->teid = ntohl (teid); + mp->tteid = ntohl (tteid); + + S (mp); + W (ret); + return ret; +} + static void vl_api_gtpu_tunnel_details_t_handler (vl_api_gtpu_tunnel_details_t * mp) { @@ -382,13 +444,14 @@ static void vl_api_gtpu_tunnel_details_t_handler ip46_address_t dst; ip_address_decode(&mp->dst_address, &dst); ip_address_decode(&mp->src_address, &src); - print (vam->ofp, "%11d%24U%24U%14d%18d%13d%19d", - ntohl (mp->sw_if_index), - format_ip46_address, &src, IP46_TYPE_ANY, - format_ip46_address, &dst, IP46_TYPE_ANY, - ntohl (mp->encap_vrf_id), - ntohl (mp->decap_next_index), ntohl (mp->teid), - ntohl (mp->mcast_sw_if_index)); + print (vam->ofp, "%11d%24U%24U%14d%18d%13d%13d%19d", + ntohl (mp->sw_if_index), + format_ip46_address, &src, IP46_TYPE_ANY, + format_ip46_address, &dst, IP46_TYPE_ANY, + ntohl (mp->encap_vrf_id), + ntohl (mp->decap_next_index), + ntohl (mp->teid), ntohl (mp->tteid), + ntohl (mp->mcast_sw_if_index)); } static int @@ -398,7 +461,6 @@ api_gtpu_tunnel_dump (vat_main_t * vam) vl_api_gtpu_tunnel_dump_t *mp; u32 sw_if_index; u8 sw_if_index_set = 0; - int ret; /* Parse args required to build the message */ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) @@ -416,9 +478,10 @@ api_gtpu_tunnel_dump (vat_main_t * vam) if (!vam->json_output) { - print (vam->ofp, "%11s%24s%24s%14s%18s%13s%19s", - "sw_if_index", "src_address", "dst_address", - "encap_vrf_id", "decap_next_index", "teid", "mcast_sw_if_index"); + print (vam->ofp, "%11s%24s%24s%14s%18s%13s%13s%19s", + "sw_if_index", "src_address", "dst_address", + "encap_vrf_id", "decap_next_index", "teid", "tteid", + "mcast_sw_if_index"); } /* Get list of gtpu-tunnel interfaces */ @@ -428,8 +491,11 @@ api_gtpu_tunnel_dump (vat_main_t * vam) S (mp); - W (ret); - return ret; + /* No status response for this API call. + * Wait 1 sec for any dump output before return to vat# */ + sleep (1); + + return 0; } #include -- cgit 1.2.3-korg