summaryrefslogtreecommitdiffstats
path: root/bgpd/rfapi/rfapi_encap_tlv.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/rfapi/rfapi_encap_tlv.c')
-rw-r--r--bgpd/rfapi/rfapi_encap_tlv.c743
1 files changed, 743 insertions, 0 deletions
diff --git a/bgpd/rfapi/rfapi_encap_tlv.c b/bgpd/rfapi/rfapi_encap_tlv.c
new file mode 100644
index 0000000..d4e875d
--- /dev/null
+++ b/bgpd/rfapi/rfapi_encap_tlv.c
@@ -0,0 +1,743 @@
+/*
+ * Copyright 2015-2016, LabN Consulting, L.L.C.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "lib/zebra.h"
+
+#include "lib/memory.h"
+#include "lib/prefix.h"
+#include "lib/table.h"
+#include "lib/vty.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_attr.h"
+
+#include "bgpd/bgp_encap_types.h"
+#include "bgpd/bgp_encap_tlv.h"
+
+#include "bgpd/rfapi/rfapi.h"
+#include "bgpd/rfapi/rfapi_encap_tlv.h"
+#include "bgpd/rfapi/rfapi_private.h"
+#include "bgpd/rfapi/rfapi_monitor.h"
+#include "bgpd/rfapi/rfapi_vty.h"
+#include "bgpd/rfapi/bgp_rfapi_cfg.h"
+#include "bgpd/rfapi/vnc_debug.h"
+
+static void rfapi_add_endpoint_address_to_subtlv(
+ struct bgp *bgp, struct rfapi_ip_addr *ea,
+ struct bgp_tea_subtlv_remote_endpoint *subtlv)
+{
+ subtlv->family = ea->addr_family;
+ if (subtlv->family == AF_INET)
+ subtlv->ip_address.v4 = ea->addr.v4;
+ else
+ subtlv->ip_address.v6 = ea->addr.v6;
+ subtlv->as4 = htonl(bgp->as);
+}
+
+bgp_encap_types
+rfapi_tunneltype_option_to_tlv(struct bgp *bgp, struct rfapi_ip_addr *ea,
+ struct rfapi_tunneltype_option *tto,
+ struct attr *attr, int always_add)
+{
+
+#define _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ttype) \
+ if ((always_add \
+ || (bgp->rfapi_cfg \
+ && !CHECK_FLAG(bgp->rfapi_cfg->flags, \
+ BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP))) \
+ && ea \
+ && !CHECK_SUBTLV_FLAG(&tto->bgpinfo.ttype, \
+ BGP_TEA_SUBTLV_REMOTE_ENDPOINT)) { \
+ rfapi_add_endpoint_address_to_subtlv( \
+ bgp, ea, &tto->bgpinfo.ttype.st_endpoint); \
+ SET_SUBTLV_FLAG(&tto->bgpinfo.ttype, \
+ BGP_TEA_SUBTLV_REMOTE_ENDPOINT); \
+ }
+
+ struct rfapi_tunneltype_option dto;
+ if (tto == NULL) { /* create default type */
+ tto = &dto;
+ memset(tto, 0, sizeof(dto));
+ tto->type = RFAPI_BGP_ENCAP_TYPE_DEFAULT;
+ }
+ switch (tto->type) {
+ case BGP_ENCAP_TYPE_L2TPV3_OVER_IP:
+ _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(l2tpv3_ip);
+ bgp_encap_type_l2tpv3overip_to_tlv(&tto->bgpinfo.l2tpv3_ip,
+ attr);
+ break;
+
+ case BGP_ENCAP_TYPE_GRE:
+ _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(gre);
+ bgp_encap_type_gre_to_tlv(&tto->bgpinfo.gre, attr);
+ break;
+
+ case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT:
+ _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(transmit_tunnel_endpoint);
+ bgp_encap_type_transmit_tunnel_endpoint(
+ &tto->bgpinfo.transmit_tunnel_endpoint, attr);
+ break;
+
+ case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE:
+ _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ipsec_tunnel);
+ bgp_encap_type_ipsec_in_tunnel_mode_to_tlv(
+ &tto->bgpinfo.ipsec_tunnel, attr);
+ break;
+
+ case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
+ _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ip_ipsec);
+ bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
+ &tto->bgpinfo.ip_ipsec, attr);
+ break;
+
+ case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
+ _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(mpls_ipsec);
+ bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
+ &tto->bgpinfo.mpls_ipsec, attr);
+ break;
+
+ case BGP_ENCAP_TYPE_IP_IN_IP:
+ _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ip_ip);
+ bgp_encap_type_ip_in_ip_to_tlv(&tto->bgpinfo.ip_ip, attr);
+ break;
+
+ case BGP_ENCAP_TYPE_VXLAN:
+ _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(vxlan);
+ bgp_encap_type_vxlan_to_tlv(&tto->bgpinfo.vxlan, attr);
+ break;
+
+ case BGP_ENCAP_TYPE_NVGRE:
+ _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(nvgre);
+ bgp_encap_type_nvgre_to_tlv(&tto->bgpinfo.nvgre, attr);
+ break;
+
+ case BGP_ENCAP_TYPE_MPLS:
+ /* nothing to do for MPLS */
+ break;
+
+ case BGP_ENCAP_TYPE_MPLS_IN_GRE:
+ _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(mpls_gre);
+ bgp_encap_type_mpls_in_gre_to_tlv(&tto->bgpinfo.mpls_gre, attr);
+ break;
+
+ case BGP_ENCAP_TYPE_VXLAN_GPE:
+ _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(vxlan_gpe);
+ bgp_encap_type_vxlan_gpe_to_tlv(&tto->bgpinfo.vxlan_gpe, attr);
+ break;
+
+ case BGP_ENCAP_TYPE_MPLS_IN_UDP:
+ _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(mpls_udp);
+ bgp_encap_type_mpls_in_udp_to_tlv(&tto->bgpinfo.mpls_udp, attr);
+ break;
+
+ case BGP_ENCAP_TYPE_PBB:
+ _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(pbb);
+ bgp_encap_type_pbb_to_tlv(&tto->bgpinfo.pbb, attr);
+ break;
+
+ default:
+ assert(0);
+ }
+ return tto->type;
+}
+
+struct rfapi_un_option *rfapi_encap_tlv_to_un_option(struct attr *attr)
+{
+ struct rfapi_un_option *uo = NULL;
+ struct rfapi_tunneltype_option *tto;
+ int rc;
+ struct bgp_attr_encap_subtlv *stlv;
+
+ /* no tunnel encap attr stored */
+ if (!attr->encap_tunneltype)
+ return NULL;
+
+ stlv = attr->encap_subtlvs;
+
+ uo = XCALLOC(MTYPE_RFAPI_UN_OPTION, sizeof(struct rfapi_un_option));
+ uo->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE;
+ uo->v.tunnel.type = attr->encap_tunneltype;
+ tto = &uo->v.tunnel;
+
+ switch (attr->encap_tunneltype) {
+ case BGP_ENCAP_TYPE_L2TPV3_OVER_IP:
+ rc = tlv_to_bgp_encap_type_l2tpv3overip(
+ stlv, &tto->bgpinfo.l2tpv3_ip);
+ break;
+
+ case BGP_ENCAP_TYPE_GRE:
+ rc = tlv_to_bgp_encap_type_gre(stlv, &tto->bgpinfo.gre);
+ break;
+
+ case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT:
+ rc = tlv_to_bgp_encap_type_transmit_tunnel_endpoint(
+ stlv, &tto->bgpinfo.transmit_tunnel_endpoint);
+ break;
+
+ case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE:
+ rc = tlv_to_bgp_encap_type_ipsec_in_tunnel_mode(
+ stlv, &tto->bgpinfo.ipsec_tunnel);
+ break;
+
+ case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
+ rc = tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
+ stlv, &tto->bgpinfo.ip_ipsec);
+ break;
+
+ case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
+ rc = tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
+ stlv, &tto->bgpinfo.mpls_ipsec);
+ break;
+
+ case BGP_ENCAP_TYPE_IP_IN_IP:
+ rc = tlv_to_bgp_encap_type_ip_in_ip(stlv, &tto->bgpinfo.ip_ip);
+ break;
+
+ case BGP_ENCAP_TYPE_VXLAN:
+ rc = tlv_to_bgp_encap_type_vxlan(stlv, &tto->bgpinfo.vxlan);
+ break;
+
+ case BGP_ENCAP_TYPE_NVGRE:
+ rc = tlv_to_bgp_encap_type_nvgre(stlv, &tto->bgpinfo.nvgre);
+ break;
+
+ case BGP_ENCAP_TYPE_MPLS:
+ rc = tlv_to_bgp_encap_type_mpls(stlv, &tto->bgpinfo.mpls);
+ break;
+
+ case BGP_ENCAP_TYPE_MPLS_IN_GRE:
+ rc = tlv_to_bgp_encap_type_mpls_in_gre(stlv,
+ &tto->bgpinfo.mpls_gre);
+ break;
+
+ case BGP_ENCAP_TYPE_VXLAN_GPE:
+ rc = tlv_to_bgp_encap_type_vxlan_gpe(stlv,
+ &tto->bgpinfo.vxlan_gpe);
+ break;
+
+ case BGP_ENCAP_TYPE_MPLS_IN_UDP:
+ rc = tlv_to_bgp_encap_type_mpls_in_udp(stlv,
+ &tto->bgpinfo.mpls_udp);
+ break;
+
+ case BGP_ENCAP_TYPE_PBB:
+ rc = tlv_to_bgp_encap_type_pbb(stlv, &tto->bgpinfo.pbb);
+ break;
+
+ default:
+ vnc_zlog_debug_verbose("%s: unknown tunnel type %d", __func__,
+ attr->encap_tunneltype);
+ rc = -1;
+ break;
+ }
+ if (rc) {
+ XFREE(MTYPE_RFAPI_UN_OPTION, uo);
+ }
+ return uo;
+}
+
+/***********************************************************************
+ * SUBTLV PRINT
+ ***********************************************************************/
+
+static void subtlv_print_encap_l2tpv3_over_ip(
+ void *stream, int column_offset,
+ struct bgp_tea_subtlv_encap_l2tpv3_over_ip *st)
+{
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!st)
+ return;
+
+ fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(L2TPv3 over IP)",
+ vty_newline);
+ fp(out, "%*s SessionID: %d%s", column_offset, "", st->sessionid,
+ vty_newline);
+ fp(out, "%*s Cookie: (length %d)%s", column_offset, "",
+ st->cookie_length, vty_newline);
+}
+
+static void subtlv_print_encap_gre(void *stream, int column_offset,
+ struct bgp_tea_subtlv_encap_gre_key *st)
+{
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!st)
+ return;
+
+ fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(GRE)",
+ vty_newline);
+ fp(out, "%*s GRE key: %d (0x%x)%s", column_offset, "", st->gre_key,
+ st->gre_key, vty_newline);
+}
+
+static void subtlv_print_encap_pbb(void *stream, int column_offset,
+ struct bgp_tea_subtlv_encap_pbb *st)
+{
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!st)
+ return;
+
+ fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(PBB)",
+ vty_newline);
+ if (st->flag_isid) {
+ fp(out, "%*s ISID: %d (0x%x)%s", column_offset, "", st->isid,
+ st->isid, vty_newline);
+ }
+ if (st->flag_vid) {
+ fp(out, "%*s VID: %d (0x%x)%s", column_offset, "", st->vid,
+ st->vid, vty_newline);
+ }
+ fp(out, "%*s MACADDR %02x:%02x:%02x:%02x:%02x:%02x%s", column_offset,
+ "", st->macaddr[0], st->macaddr[1], st->macaddr[2], st->macaddr[3],
+ st->macaddr[4], st->macaddr[5], vty_newline);
+}
+
+static void subtlv_print_proto_type(void *stream, int column_offset,
+ struct bgp_tea_subtlv_proto_type *st)
+{
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!st)
+ return;
+
+ fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(Proto Type)",
+ vty_newline);
+ fp(out, "%*s Proto %d (0x%x)%s", column_offset, "", st->proto,
+ st->proto, vty_newline);
+}
+
+static void subtlv_print_color(void *stream, int column_offset,
+ struct bgp_tea_subtlv_color *st)
+{
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!st)
+ return;
+
+ fp(out, "%*s%s%s", column_offset, "", "SubTLV: Color", vty_newline);
+ fp(out, "%*s Color: %d (0x%x)", column_offset, "", st->color,
+ st->color, vty_newline);
+}
+
+static void subtlv_print_ipsec_ta(void *stream, int column_offset,
+ struct bgp_tea_subtlv_ipsec_ta *st)
+{
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!st)
+ return;
+
+ fp(out, "%*s%s%s", column_offset, "", "SubTLV: IPSEC TA", vty_newline);
+ fp(out, "%*s Authenticator Type: %d (0x%x)", column_offset, "",
+ st->authenticator_type, st->authenticator_type, vty_newline);
+ fp(out, "%*s Authenticator: (length %d)", column_offset, "",
+ st->authenticator_length, vty_newline);
+}
+
+/***********************************************************************
+ * TLV PRINT
+ ***********************************************************************/
+
+static void
+print_encap_type_l2tpv3overip(void *stream, int column_offset,
+ struct bgp_encap_type_l2tpv3_over_ip *bet)
+{
+ const char *type = "L2TPv3 over IP";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+
+ subtlv_print_encap_l2tpv3_over_ip(stream, column_offset + 2,
+ &bet->st_encap);
+ subtlv_print_proto_type(stream, column_offset + 2, &bet->st_proto);
+ subtlv_print_color(stream, column_offset + 2, &bet->st_color);
+}
+
+static void print_encap_type_gre(void *stream, int column_offset,
+ struct bgp_encap_type_gre *bet)
+{
+ const char *type = "GRE";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+
+ subtlv_print_encap_gre(stream, column_offset + 2, &bet->st_encap);
+ subtlv_print_proto_type(stream, column_offset + 2, &bet->st_proto);
+ subtlv_print_color(stream, column_offset + 2, &bet->st_color);
+}
+
+static void print_encap_type_ip_in_ip(void *stream, int column_offset,
+ struct bgp_encap_type_ip_in_ip *bet)
+{
+ const char *type = "IP in IP";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+
+ subtlv_print_proto_type(stream, column_offset + 2, &bet->st_proto);
+ subtlv_print_color(stream, column_offset + 2, &bet->st_color);
+}
+
+static void print_encap_type_transmit_tunnel_endpoint(
+ void *stream, int column_offset,
+ struct bgp_encap_type_transmit_tunnel_endpoint *bet)
+{
+ const char *type = "Transmit Tunnel Endpoint";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+
+ /* no subtlvs for this type */
+}
+
+static void print_encap_type_ipsec_in_tunnel_mode(
+ void *stream, int column_offset,
+ struct bgp_encap_type_ipsec_in_tunnel_mode *bet)
+{
+ const char *type = "IPSEC in Tunnel mode";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+ subtlv_print_ipsec_ta(stream, column_offset + 2, &bet->st_ipsec_ta);
+}
+
+static void print_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
+ void *stream, int column_offset,
+ struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet)
+{
+ const char *type = "IP in IP Tunnel with IPSEC transport mode";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+
+ subtlv_print_ipsec_ta(stream, column_offset + 2, &bet->st_ipsec_ta);
+}
+
+static void print_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
+ void *stream, int column_offset,
+ struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet)
+{
+ const char *type = "MPLS in IP Tunnel with IPSEC transport mode";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+
+ subtlv_print_ipsec_ta(stream, column_offset + 2, &bet->st_ipsec_ta);
+}
+
+
+static void print_encap_type_pbb(void *stream, int column_offset,
+ struct bgp_encap_type_pbb *bet)
+{
+ const char *type = "PBB";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+
+ subtlv_print_encap_pbb(stream, column_offset + 2, &bet->st_encap);
+}
+
+
+static void print_encap_type_vxlan(void *stream, int column_offset,
+ struct bgp_encap_type_vxlan *bet)
+{
+ const char *type = "VXLAN";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+
+ /* no subtlvs for this type */
+}
+
+
+static void print_encap_type_nvgre(void *stream, int column_offset,
+ struct bgp_encap_type_nvgre *bet)
+{
+ const char *type = "NVGRE";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+
+ /* no subtlvs for this type */
+}
+
+static void print_encap_type_mpls(void *stream, int column_offset,
+ struct bgp_encap_type_mpls *bet)
+{
+ const char *type = "MPLS";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+
+ /* no subtlvs for this type */
+}
+
+static void print_encap_type_mpls_in_gre(void *stream, int column_offset,
+ struct bgp_encap_type_mpls_in_gre *bet)
+{
+ const char *type = "MPLS in GRE";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+
+ /* no subtlvs for this type */
+}
+
+static void print_encap_type_vxlan_gpe(void *stream, int column_offset,
+ struct bgp_encap_type_vxlan_gpe *bet)
+{
+ const char *type = "VXLAN GPE";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+
+ /* no subtlvs for this type */
+}
+
+static void print_encap_type_mpls_in_udp(void *stream, int column_offset,
+ struct bgp_encap_type_mpls_in_udp *bet)
+{
+ const char *type = "MPLS in UDP";
+ int (*fp)(void *, const char *, ...);
+ struct vty *vty;
+ void *out;
+ const char *vty_newline;
+
+ if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
+ return;
+ if (!bet)
+ return;
+
+ fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
+
+ /* no subtlvs for this type */
+}
+
+void rfapi_print_tunneltype_option(void *stream, int column_offset,
+ struct rfapi_tunneltype_option *tto)
+{
+ switch (tto->type) {
+ case BGP_ENCAP_TYPE_L2TPV3_OVER_IP:
+ print_encap_type_l2tpv3overip(stream, column_offset,
+ &tto->bgpinfo.l2tpv3_ip);
+ break;
+
+ case BGP_ENCAP_TYPE_GRE:
+ print_encap_type_gre(stream, column_offset, &tto->bgpinfo.gre);
+ break;
+
+ case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT:
+ print_encap_type_transmit_tunnel_endpoint(
+ stream, column_offset,
+ &tto->bgpinfo.transmit_tunnel_endpoint);
+ break;
+
+ case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE:
+ print_encap_type_ipsec_in_tunnel_mode(
+ stream, column_offset, &tto->bgpinfo.ipsec_tunnel);
+ break;
+
+ case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
+ print_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
+ stream, column_offset, &tto->bgpinfo.ip_ipsec);
+ break;
+
+ case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
+ print_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
+ stream, column_offset, &tto->bgpinfo.mpls_ipsec);
+ break;
+
+ case BGP_ENCAP_TYPE_IP_IN_IP:
+ print_encap_type_ip_in_ip(stream, column_offset,
+ &tto->bgpinfo.ip_ip);
+ break;
+
+ case BGP_ENCAP_TYPE_VXLAN:
+ print_encap_type_vxlan(stream, column_offset,
+ &tto->bgpinfo.vxlan);
+ break;
+
+ case BGP_ENCAP_TYPE_NVGRE:
+ print_encap_type_nvgre(stream, column_offset,
+ &tto->bgpinfo.nvgre);
+ break;
+
+ case BGP_ENCAP_TYPE_MPLS:
+ print_encap_type_mpls(stream, column_offset,
+ &tto->bgpinfo.mpls);
+ break;
+
+ case BGP_ENCAP_TYPE_MPLS_IN_GRE:
+ print_encap_type_mpls_in_gre(stream, column_offset,
+ &tto->bgpinfo.mpls_gre);
+ break;
+
+ case BGP_ENCAP_TYPE_VXLAN_GPE:
+ print_encap_type_vxlan_gpe(stream, column_offset,
+ &tto->bgpinfo.vxlan_gpe);
+ break;
+
+ case BGP_ENCAP_TYPE_MPLS_IN_UDP:
+ print_encap_type_mpls_in_udp(stream, column_offset,
+ &tto->bgpinfo.mpls_udp);
+ break;
+
+ case BGP_ENCAP_TYPE_PBB:
+ print_encap_type_pbb(stream, column_offset, &tto->bgpinfo.pbb);
+ break;
+
+ default:
+ assert(0);
+ }
+}