/* * 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); } }