1 /*
2  * Copyright 2015-2016, LabN Consulting, L.L.C.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; see the file COPYING; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "lib/zebra.h"
20 
21 #include "lib/memory.h"
22 #include "lib/prefix.h"
23 #include "lib/table.h"
24 #include "lib/vty.h"
25 
26 #include "bgpd/bgpd.h"
27 #include "bgpd/bgp_attr.h"
28 
29 #include "bgpd/bgp_encap_types.h"
30 #include "bgpd/bgp_encap_tlv.h"
31 
32 #include "bgpd/rfapi/rfapi.h"
33 #include "bgpd/rfapi/rfapi_encap_tlv.h"
34 #include "bgpd/rfapi/rfapi_private.h"
35 #include "bgpd/rfapi/rfapi_monitor.h"
36 #include "bgpd/rfapi/rfapi_vty.h"
37 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
38 #include "bgpd/rfapi/vnc_debug.h"
39 
rfapi_add_endpoint_address_to_subtlv(struct bgp * bgp,struct rfapi_ip_addr * ea,struct bgp_tea_subtlv_remote_endpoint * subtlv)40 static void rfapi_add_endpoint_address_to_subtlv(
41 	struct bgp *bgp, struct rfapi_ip_addr *ea,
42 	struct bgp_tea_subtlv_remote_endpoint *subtlv)
43 {
44 	subtlv->family = ea->addr_family;
45 	if (subtlv->family == AF_INET)
46 		subtlv->ip_address.v4 = ea->addr.v4;
47 	else
48 		subtlv->ip_address.v6 = ea->addr.v6;
49 	subtlv->as4 = htonl(bgp->as);
50 }
51 
52 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)53 rfapi_tunneltype_option_to_tlv(struct bgp *bgp, struct rfapi_ip_addr *ea,
54 			       struct rfapi_tunneltype_option *tto,
55 			       struct attr *attr, int always_add)
56 {
57 
58 #define _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ttype)                                \
59 	if ((always_add                                                        \
60 	     || (bgp->rfapi_cfg                                                \
61 		 && !CHECK_FLAG(bgp->rfapi_cfg->flags,                         \
62 				BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP)))          \
63 	    && ea                                                              \
64 	    && !CHECK_SUBTLV_FLAG(&tto->bgpinfo.ttype,                         \
65 				  BGP_TEA_SUBTLV_REMOTE_ENDPOINT)) {           \
66 		rfapi_add_endpoint_address_to_subtlv(                          \
67 			bgp, ea, &tto->bgpinfo.ttype.st_endpoint);             \
68 		SET_SUBTLV_FLAG(&tto->bgpinfo.ttype,                           \
69 				BGP_TEA_SUBTLV_REMOTE_ENDPOINT);               \
70 	}
71 
72 	struct rfapi_tunneltype_option dto;
73 	if (tto == NULL) { /* create default type */
74 		tto = &dto;
75 		memset(tto, 0, sizeof(dto));
76 		tto->type = RFAPI_BGP_ENCAP_TYPE_DEFAULT;
77 	}
78 	switch (tto->type) {
79 	case BGP_ENCAP_TYPE_L2TPV3_OVER_IP:
80 		_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(l2tpv3_ip);
81 		bgp_encap_type_l2tpv3overip_to_tlv(&tto->bgpinfo.l2tpv3_ip,
82 						   attr);
83 		break;
84 
85 	case BGP_ENCAP_TYPE_GRE:
86 		_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(gre);
87 		bgp_encap_type_gre_to_tlv(&tto->bgpinfo.gre, attr);
88 		break;
89 
90 	case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT:
91 		_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(transmit_tunnel_endpoint);
92 		bgp_encap_type_transmit_tunnel_endpoint(
93 			&tto->bgpinfo.transmit_tunnel_endpoint, attr);
94 		break;
95 
96 	case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE:
97 		_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ipsec_tunnel);
98 		bgp_encap_type_ipsec_in_tunnel_mode_to_tlv(
99 			&tto->bgpinfo.ipsec_tunnel, attr);
100 		break;
101 
102 	case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
103 		_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ip_ipsec);
104 		bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
105 			&tto->bgpinfo.ip_ipsec, attr);
106 		break;
107 
108 	case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
109 		_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(mpls_ipsec);
110 		bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
111 			&tto->bgpinfo.mpls_ipsec, attr);
112 		break;
113 
114 	case BGP_ENCAP_TYPE_IP_IN_IP:
115 		_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ip_ip);
116 		bgp_encap_type_ip_in_ip_to_tlv(&tto->bgpinfo.ip_ip, attr);
117 		break;
118 
119 	case BGP_ENCAP_TYPE_VXLAN:
120 		_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(vxlan);
121 		bgp_encap_type_vxlan_to_tlv(&tto->bgpinfo.vxlan, attr);
122 		break;
123 
124 	case BGP_ENCAP_TYPE_NVGRE:
125 		_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(nvgre);
126 		bgp_encap_type_nvgre_to_tlv(&tto->bgpinfo.nvgre, attr);
127 		break;
128 
129 	case BGP_ENCAP_TYPE_MPLS:
130 		/* nothing to do for MPLS */
131 		break;
132 
133 	case BGP_ENCAP_TYPE_MPLS_IN_GRE:
134 		_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(mpls_gre);
135 		bgp_encap_type_mpls_in_gre_to_tlv(&tto->bgpinfo.mpls_gre, attr);
136 		break;
137 
138 	case BGP_ENCAP_TYPE_VXLAN_GPE:
139 		_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(vxlan_gpe);
140 		bgp_encap_type_vxlan_gpe_to_tlv(&tto->bgpinfo.vxlan_gpe, attr);
141 		break;
142 
143 	case BGP_ENCAP_TYPE_MPLS_IN_UDP:
144 		_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(mpls_udp);
145 		bgp_encap_type_mpls_in_udp_to_tlv(&tto->bgpinfo.mpls_udp, attr);
146 		break;
147 
148 	case BGP_ENCAP_TYPE_PBB:
149 		_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(pbb);
150 		bgp_encap_type_pbb_to_tlv(&tto->bgpinfo.pbb, attr);
151 		break;
152 
153 	default:
154 		assert(0);
155 	}
156 	return tto->type;
157 }
158 
rfapi_encap_tlv_to_un_option(struct attr * attr)159 struct rfapi_un_option *rfapi_encap_tlv_to_un_option(struct attr *attr)
160 {
161 	struct rfapi_un_option *uo = NULL;
162 	struct rfapi_tunneltype_option *tto;
163 	int rc;
164 	struct bgp_attr_encap_subtlv *stlv;
165 
166 	/* no tunnel encap attr stored */
167 	if (!attr->encap_tunneltype)
168 		return NULL;
169 
170 	stlv = attr->encap_subtlvs;
171 
172 	uo = XCALLOC(MTYPE_RFAPI_UN_OPTION, sizeof(struct rfapi_un_option));
173 	assert(uo);
174 	uo->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE;
175 	uo->v.tunnel.type = attr->encap_tunneltype;
176 	tto = &uo->v.tunnel;
177 
178 	switch (attr->encap_tunneltype) {
179 	case BGP_ENCAP_TYPE_L2TPV3_OVER_IP:
180 		rc = tlv_to_bgp_encap_type_l2tpv3overip(
181 			stlv, &tto->bgpinfo.l2tpv3_ip);
182 		break;
183 
184 	case BGP_ENCAP_TYPE_GRE:
185 		rc = tlv_to_bgp_encap_type_gre(stlv, &tto->bgpinfo.gre);
186 		break;
187 
188 	case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT:
189 		rc = tlv_to_bgp_encap_type_transmit_tunnel_endpoint(
190 			stlv, &tto->bgpinfo.transmit_tunnel_endpoint);
191 		break;
192 
193 	case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE:
194 		rc = tlv_to_bgp_encap_type_ipsec_in_tunnel_mode(
195 			stlv, &tto->bgpinfo.ipsec_tunnel);
196 		break;
197 
198 	case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
199 		rc = tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
200 			stlv, &tto->bgpinfo.ip_ipsec);
201 		break;
202 
203 	case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
204 		rc = tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
205 			stlv, &tto->bgpinfo.mpls_ipsec);
206 		break;
207 
208 	case BGP_ENCAP_TYPE_IP_IN_IP:
209 		rc = tlv_to_bgp_encap_type_ip_in_ip(stlv, &tto->bgpinfo.ip_ip);
210 		break;
211 
212 	case BGP_ENCAP_TYPE_VXLAN:
213 		rc = tlv_to_bgp_encap_type_vxlan(stlv, &tto->bgpinfo.vxlan);
214 		break;
215 
216 	case BGP_ENCAP_TYPE_NVGRE:
217 		rc = tlv_to_bgp_encap_type_nvgre(stlv, &tto->bgpinfo.nvgre);
218 		break;
219 
220 	case BGP_ENCAP_TYPE_MPLS:
221 		rc = tlv_to_bgp_encap_type_mpls(stlv, &tto->bgpinfo.mpls);
222 		break;
223 
224 	case BGP_ENCAP_TYPE_MPLS_IN_GRE:
225 		rc = tlv_to_bgp_encap_type_mpls_in_gre(stlv,
226 						       &tto->bgpinfo.mpls_gre);
227 		break;
228 
229 	case BGP_ENCAP_TYPE_VXLAN_GPE:
230 		rc = tlv_to_bgp_encap_type_vxlan_gpe(stlv,
231 						     &tto->bgpinfo.vxlan_gpe);
232 		break;
233 
234 	case BGP_ENCAP_TYPE_MPLS_IN_UDP:
235 		rc = tlv_to_bgp_encap_type_mpls_in_udp(stlv,
236 						       &tto->bgpinfo.mpls_udp);
237 		break;
238 
239 	case BGP_ENCAP_TYPE_PBB:
240 		rc = tlv_to_bgp_encap_type_pbb(stlv, &tto->bgpinfo.pbb);
241 		break;
242 
243 	default:
244 		vnc_zlog_debug_verbose("%s: unknown tunnel type %d", __func__,
245 				       attr->encap_tunneltype);
246 		rc = -1;
247 		break;
248 	}
249 	if (rc) {
250 		XFREE(MTYPE_RFAPI_UN_OPTION, uo);
251 	}
252 	return uo;
253 }
254 
255 /***********************************************************************
256  *			SUBTLV PRINT
257  ***********************************************************************/
258 
subtlv_print_encap_l2tpv3_over_ip(void * stream,int column_offset,struct bgp_tea_subtlv_encap_l2tpv3_over_ip * st)259 static void subtlv_print_encap_l2tpv3_over_ip(
260 	void *stream, int column_offset,
261 	struct bgp_tea_subtlv_encap_l2tpv3_over_ip *st)
262 {
263 	int (*fp)(void *, const char *, ...);
264 	struct vty *vty;
265 	void *out;
266 	const char *vty_newline;
267 
268 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
269 		return;
270 	if (!st)
271 		return;
272 
273 	fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(L2TPv3 over IP)",
274 	   vty_newline);
275 	fp(out, "%*s  SessionID: %d%s", column_offset, "", st->sessionid,
276 	   vty_newline);
277 	fp(out, "%*s  Cookie: (length %d)%s", column_offset, "",
278 	   st->cookie_length, vty_newline);
279 }
280 
subtlv_print_encap_gre(void * stream,int column_offset,struct bgp_tea_subtlv_encap_gre_key * st)281 static void subtlv_print_encap_gre(void *stream, int column_offset,
282 				   struct bgp_tea_subtlv_encap_gre_key *st)
283 {
284 	int (*fp)(void *, const char *, ...);
285 	struct vty *vty;
286 	void *out;
287 	const char *vty_newline;
288 
289 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
290 		return;
291 	if (!st)
292 		return;
293 
294 	fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(GRE)",
295 	   vty_newline);
296 	fp(out, "%*s  GRE key: %d (0x%x)%s", column_offset, "", st->gre_key,
297 	   st->gre_key, vty_newline);
298 }
299 
subtlv_print_encap_pbb(void * stream,int column_offset,struct bgp_tea_subtlv_encap_pbb * st)300 static void subtlv_print_encap_pbb(void *stream, int column_offset,
301 				   struct bgp_tea_subtlv_encap_pbb *st)
302 {
303 	int (*fp)(void *, const char *, ...);
304 	struct vty *vty;
305 	void *out;
306 	const char *vty_newline;
307 
308 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
309 		return;
310 	if (!st)
311 		return;
312 
313 	fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(PBB)",
314 	   vty_newline);
315 	if (st->flag_isid) {
316 		fp(out, "%*s  ISID: %d (0x%x)%s", column_offset, "", st->isid,
317 		   st->isid, vty_newline);
318 	}
319 	if (st->flag_vid) {
320 		fp(out, "%*s  VID: %d (0x%x)%s", column_offset, "", st->vid,
321 		   st->vid, vty_newline);
322 	}
323 	fp(out, "%*s  MACADDR %02x:%02x:%02x:%02x:%02x:%02x%s", column_offset,
324 	   "", st->macaddr[0], st->macaddr[1], st->macaddr[2], st->macaddr[3],
325 	   st->macaddr[4], st->macaddr[5], vty_newline);
326 }
327 
subtlv_print_proto_type(void * stream,int column_offset,struct bgp_tea_subtlv_proto_type * st)328 static void subtlv_print_proto_type(void *stream, int column_offset,
329 				    struct bgp_tea_subtlv_proto_type *st)
330 {
331 	int (*fp)(void *, const char *, ...);
332 	struct vty *vty;
333 	void *out;
334 	const char *vty_newline;
335 
336 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
337 		return;
338 	if (!st)
339 		return;
340 
341 	fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(Proto Type)",
342 	   vty_newline);
343 	fp(out, "%*s  Proto %d (0x%x)%s", column_offset, "", st->proto,
344 	   st->proto, vty_newline);
345 }
346 
subtlv_print_color(void * stream,int column_offset,struct bgp_tea_subtlv_color * st)347 static void subtlv_print_color(void *stream, int column_offset,
348 			       struct bgp_tea_subtlv_color *st)
349 {
350 	int (*fp)(void *, const char *, ...);
351 	struct vty *vty;
352 	void *out;
353 	const char *vty_newline;
354 
355 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
356 		return;
357 	if (!st)
358 		return;
359 
360 	fp(out, "%*s%s%s", column_offset, "", "SubTLV: Color", vty_newline);
361 	fp(out, "%*s  Color: %d (0x%x)", column_offset, "", st->color,
362 	   st->color, vty_newline);
363 }
364 
subtlv_print_ipsec_ta(void * stream,int column_offset,struct bgp_tea_subtlv_ipsec_ta * st)365 static void subtlv_print_ipsec_ta(void *stream, int column_offset,
366 				  struct bgp_tea_subtlv_ipsec_ta *st)
367 {
368 	int (*fp)(void *, const char *, ...);
369 	struct vty *vty;
370 	void *out;
371 	const char *vty_newline;
372 
373 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
374 		return;
375 	if (!st)
376 		return;
377 
378 	fp(out, "%*s%s%s", column_offset, "", "SubTLV: IPSEC TA", vty_newline);
379 	fp(out, "%*s  Authenticator Type: %d (0x%x)", column_offset, "",
380 	   st->authenticator_type, st->authenticator_type, vty_newline);
381 	fp(out, "%*s  Authenticator: (length %d)", column_offset, "",
382 	   st->authenticator_length, vty_newline);
383 }
384 
385 /***********************************************************************
386  *			TLV PRINT
387  ***********************************************************************/
388 
389 static void
print_encap_type_l2tpv3overip(void * stream,int column_offset,struct bgp_encap_type_l2tpv3_over_ip * bet)390 print_encap_type_l2tpv3overip(void *stream, int column_offset,
391 			      struct bgp_encap_type_l2tpv3_over_ip *bet)
392 {
393 	const char *type = "L2TPv3 over IP";
394 	int (*fp)(void *, const char *, ...);
395 	struct vty *vty;
396 	void *out;
397 	const char *vty_newline;
398 
399 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
400 		return;
401 	if (!bet)
402 		return;
403 
404 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
405 
406 	subtlv_print_encap_l2tpv3_over_ip(stream, column_offset + 2,
407 					  &bet->st_encap);
408 	subtlv_print_proto_type(stream, column_offset + 2, &bet->st_proto);
409 	subtlv_print_color(stream, column_offset + 2, &bet->st_color);
410 }
411 
print_encap_type_gre(void * stream,int column_offset,struct bgp_encap_type_gre * bet)412 static void print_encap_type_gre(void *stream, int column_offset,
413 				 struct bgp_encap_type_gre *bet)
414 {
415 	const char *type = "GRE";
416 	int (*fp)(void *, const char *, ...);
417 	struct vty *vty;
418 	void *out;
419 	const char *vty_newline;
420 
421 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
422 		return;
423 	if (!bet)
424 		return;
425 
426 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
427 
428 	subtlv_print_encap_gre(stream, column_offset + 2, &bet->st_encap);
429 	subtlv_print_proto_type(stream, column_offset + 2, &bet->st_proto);
430 	subtlv_print_color(stream, column_offset + 2, &bet->st_color);
431 }
432 
print_encap_type_ip_in_ip(void * stream,int column_offset,struct bgp_encap_type_ip_in_ip * bet)433 static void print_encap_type_ip_in_ip(void *stream, int column_offset,
434 				      struct bgp_encap_type_ip_in_ip *bet)
435 {
436 	const char *type = "IP in IP";
437 	int (*fp)(void *, const char *, ...);
438 	struct vty *vty;
439 	void *out;
440 	const char *vty_newline;
441 
442 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
443 		return;
444 	if (!bet)
445 		return;
446 
447 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
448 
449 	subtlv_print_proto_type(stream, column_offset + 2, &bet->st_proto);
450 	subtlv_print_color(stream, column_offset + 2, &bet->st_color);
451 }
452 
print_encap_type_transmit_tunnel_endpoint(void * stream,int column_offset,struct bgp_encap_type_transmit_tunnel_endpoint * bet)453 static void print_encap_type_transmit_tunnel_endpoint(
454 	void *stream, int column_offset,
455 	struct bgp_encap_type_transmit_tunnel_endpoint *bet)
456 {
457 	const char *type = "Transmit Tunnel Endpoint";
458 	int (*fp)(void *, const char *, ...);
459 	struct vty *vty;
460 	void *out;
461 	const char *vty_newline;
462 
463 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
464 		return;
465 	if (!bet)
466 		return;
467 
468 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
469 
470 	/* no subtlvs for this type */
471 }
472 
print_encap_type_ipsec_in_tunnel_mode(void * stream,int column_offset,struct bgp_encap_type_ipsec_in_tunnel_mode * bet)473 static void print_encap_type_ipsec_in_tunnel_mode(
474 	void *stream, int column_offset,
475 	struct bgp_encap_type_ipsec_in_tunnel_mode *bet)
476 {
477 	const char *type = "IPSEC in Tunnel mode";
478 	int (*fp)(void *, const char *, ...);
479 	struct vty *vty;
480 	void *out;
481 	const char *vty_newline;
482 
483 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
484 		return;
485 	if (!bet)
486 		return;
487 
488 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
489 	subtlv_print_ipsec_ta(stream, column_offset + 2, &bet->st_ipsec_ta);
490 }
491 
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)492 static void print_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
493 	void *stream, int column_offset,
494 	struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet)
495 {
496 	const char *type = "IP in IP Tunnel with IPSEC transport mode";
497 	int (*fp)(void *, const char *, ...);
498 	struct vty *vty;
499 	void *out;
500 	const char *vty_newline;
501 
502 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
503 		return;
504 	if (!bet)
505 		return;
506 
507 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
508 
509 	subtlv_print_ipsec_ta(stream, column_offset + 2, &bet->st_ipsec_ta);
510 }
511 
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)512 static void print_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
513 	void *stream, int column_offset,
514 	struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet)
515 {
516 	const char *type = "MPLS in IP Tunnel with IPSEC transport mode";
517 	int (*fp)(void *, const char *, ...);
518 	struct vty *vty;
519 	void *out;
520 	const char *vty_newline;
521 
522 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
523 		return;
524 	if (!bet)
525 		return;
526 
527 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
528 
529 	subtlv_print_ipsec_ta(stream, column_offset + 2, &bet->st_ipsec_ta);
530 }
531 
532 
print_encap_type_pbb(void * stream,int column_offset,struct bgp_encap_type_pbb * bet)533 static void print_encap_type_pbb(void *stream, int column_offset,
534 				 struct bgp_encap_type_pbb *bet)
535 {
536 	const char *type = "PBB";
537 	int (*fp)(void *, const char *, ...);
538 	struct vty *vty;
539 	void *out;
540 	const char *vty_newline;
541 
542 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
543 		return;
544 	if (!bet)
545 		return;
546 
547 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
548 
549 	subtlv_print_encap_pbb(stream, column_offset + 2, &bet->st_encap);
550 }
551 
552 
print_encap_type_vxlan(void * stream,int column_offset,struct bgp_encap_type_vxlan * bet)553 static void print_encap_type_vxlan(void *stream, int column_offset,
554 				   struct bgp_encap_type_vxlan *bet)
555 {
556 	const char *type = "VXLAN";
557 	int (*fp)(void *, const char *, ...);
558 	struct vty *vty;
559 	void *out;
560 	const char *vty_newline;
561 
562 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
563 		return;
564 	if (!bet)
565 		return;
566 
567 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
568 
569 	/* no subtlvs for this type */
570 }
571 
572 
print_encap_type_nvgre(void * stream,int column_offset,struct bgp_encap_type_nvgre * bet)573 static void print_encap_type_nvgre(void *stream, int column_offset,
574 				   struct bgp_encap_type_nvgre *bet)
575 {
576 	const char *type = "NVGRE";
577 	int (*fp)(void *, const char *, ...);
578 	struct vty *vty;
579 	void *out;
580 	const char *vty_newline;
581 
582 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
583 		return;
584 	if (!bet)
585 		return;
586 
587 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
588 
589 	/* no subtlvs for this type */
590 }
591 
print_encap_type_mpls(void * stream,int column_offset,struct bgp_encap_type_mpls * bet)592 static void print_encap_type_mpls(void *stream, int column_offset,
593 				  struct bgp_encap_type_mpls *bet)
594 {
595 	const char *type = "MPLS";
596 	int (*fp)(void *, const char *, ...);
597 	struct vty *vty;
598 	void *out;
599 	const char *vty_newline;
600 
601 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
602 		return;
603 	if (!bet)
604 		return;
605 
606 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
607 
608 	/* no subtlvs for this type */
609 }
610 
print_encap_type_mpls_in_gre(void * stream,int column_offset,struct bgp_encap_type_mpls_in_gre * bet)611 static void print_encap_type_mpls_in_gre(void *stream, int column_offset,
612 					 struct bgp_encap_type_mpls_in_gre *bet)
613 {
614 	const char *type = "MPLS in GRE";
615 	int (*fp)(void *, const char *, ...);
616 	struct vty *vty;
617 	void *out;
618 	const char *vty_newline;
619 
620 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
621 		return;
622 	if (!bet)
623 		return;
624 
625 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
626 
627 	/* no subtlvs for this type */
628 }
629 
print_encap_type_vxlan_gpe(void * stream,int column_offset,struct bgp_encap_type_vxlan_gpe * bet)630 static void print_encap_type_vxlan_gpe(void *stream, int column_offset,
631 				       struct bgp_encap_type_vxlan_gpe *bet)
632 {
633 	const char *type = "VXLAN GPE";
634 	int (*fp)(void *, const char *, ...);
635 	struct vty *vty;
636 	void *out;
637 	const char *vty_newline;
638 
639 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
640 		return;
641 	if (!bet)
642 		return;
643 
644 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
645 
646 	/* no subtlvs for this type */
647 }
648 
print_encap_type_mpls_in_udp(void * stream,int column_offset,struct bgp_encap_type_mpls_in_udp * bet)649 static void print_encap_type_mpls_in_udp(void *stream, int column_offset,
650 					 struct bgp_encap_type_mpls_in_udp *bet)
651 {
652 	const char *type = "MPLS in UDP";
653 	int (*fp)(void *, const char *, ...);
654 	struct vty *vty;
655 	void *out;
656 	const char *vty_newline;
657 
658 	if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
659 		return;
660 	if (!bet)
661 		return;
662 
663 	fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
664 
665 	/* no subtlvs for this type */
666 }
667 
rfapi_print_tunneltype_option(void * stream,int column_offset,struct rfapi_tunneltype_option * tto)668 void rfapi_print_tunneltype_option(void *stream, int column_offset,
669 				   struct rfapi_tunneltype_option *tto)
670 {
671 	switch (tto->type) {
672 	case BGP_ENCAP_TYPE_L2TPV3_OVER_IP:
673 		print_encap_type_l2tpv3overip(stream, column_offset,
674 					      &tto->bgpinfo.l2tpv3_ip);
675 		break;
676 
677 	case BGP_ENCAP_TYPE_GRE:
678 		print_encap_type_gre(stream, column_offset, &tto->bgpinfo.gre);
679 		break;
680 
681 	case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT:
682 		print_encap_type_transmit_tunnel_endpoint(
683 			stream, column_offset,
684 			&tto->bgpinfo.transmit_tunnel_endpoint);
685 		break;
686 
687 	case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE:
688 		print_encap_type_ipsec_in_tunnel_mode(
689 			stream, column_offset, &tto->bgpinfo.ipsec_tunnel);
690 		break;
691 
692 	case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
693 		print_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
694 			stream, column_offset, &tto->bgpinfo.ip_ipsec);
695 		break;
696 
697 	case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
698 		print_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
699 			stream, column_offset, &tto->bgpinfo.mpls_ipsec);
700 		break;
701 
702 	case BGP_ENCAP_TYPE_IP_IN_IP:
703 		print_encap_type_ip_in_ip(stream, column_offset,
704 					  &tto->bgpinfo.ip_ip);
705 		break;
706 
707 	case BGP_ENCAP_TYPE_VXLAN:
708 		print_encap_type_vxlan(stream, column_offset,
709 				       &tto->bgpinfo.vxlan);
710 		break;
711 
712 	case BGP_ENCAP_TYPE_NVGRE:
713 		print_encap_type_nvgre(stream, column_offset,
714 				       &tto->bgpinfo.nvgre);
715 		break;
716 
717 	case BGP_ENCAP_TYPE_MPLS:
718 		print_encap_type_mpls(stream, column_offset,
719 				      &tto->bgpinfo.mpls);
720 		break;
721 
722 	case BGP_ENCAP_TYPE_MPLS_IN_GRE:
723 		print_encap_type_mpls_in_gre(stream, column_offset,
724 					     &tto->bgpinfo.mpls_gre);
725 		break;
726 
727 	case BGP_ENCAP_TYPE_VXLAN_GPE:
728 		print_encap_type_vxlan_gpe(stream, column_offset,
729 					   &tto->bgpinfo.vxlan_gpe);
730 		break;
731 
732 	case BGP_ENCAP_TYPE_MPLS_IN_UDP:
733 		print_encap_type_mpls_in_udp(stream, column_offset,
734 					     &tto->bgpinfo.mpls_udp);
735 		break;
736 
737 	case BGP_ENCAP_TYPE_PBB:
738 		print_encap_type_pbb(stream, column_offset, &tto->bgpinfo.pbb);
739 		break;
740 
741 	default:
742 		assert(0);
743 	}
744 }
745