/* VPN Related functions * Copyright (C) 2017 6WIND * * This file is part of FRRouting * * FRRouting 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, or (at your option) any * later version. * * FRRouting 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 #include "command.h" #include "prefix.h" #include "lib/json.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_route.h" #include "bgpd/bgp_table.h" #include "bgpd/bgp_attr.h" #include "bgpd/bgp_mplsvpn.h" #include "bgpd/bgp_vpn.h" int show_adj_route_vpn(struct vty *vty, struct peer *peer, struct prefix_rd *prd, afi_t afi, safi_t safi, uint8_t use_json) { struct bgp *bgp; struct bgp_table *table; struct bgp_node *rn; struct bgp_node *rm; struct attr *attr; int rd_header; int header = 1; json_object *json = NULL; json_object *json_scode = NULL; json_object *json_ocode = NULL; json_object *json_routes = NULL; json_object *json_array = NULL; bgp = bgp_get_default(); if (bgp == NULL) { if (!use_json) vty_out(vty, "No BGP process is configured\n"); else vty_out(vty, "{}\n"); return CMD_WARNING; } if (use_json) { json_scode = json_object_new_object(); json_ocode = json_object_new_object(); json_routes = json_object_new_object(); json = json_object_new_object(); json_object_string_add(json_scode, "suppressed", "s"); json_object_string_add(json_scode, "damped", "d"); json_object_string_add(json_scode, "history", "h"); json_object_string_add(json_scode, "valid", "*"); json_object_string_add(json_scode, "best", ">"); json_object_string_add(json_scode, "internal", "i"); json_object_string_add(json_ocode, "igp", "i"); json_object_string_add(json_ocode, "egp", "e"); json_object_string_add(json_ocode, "incomplete", "?"); } for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn; rn = bgp_route_next(rn)) { if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) continue; if ((table = rn->info) != NULL) { if (use_json) json_array = json_object_new_array(); else json_array = NULL; rd_header = 1; for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) { if ((attr = rm->info) != NULL) { if (header) { if (use_json) { json_object_int_add( json, "bgpTableVersion", 0); json_object_string_add( json, "bgpLocalRouterId", inet_ntoa( bgp->router_id)); json_object_object_add( json, "bgpStatusCodes", json_scode); json_object_object_add( json, "bgpOriginCodes", json_ocode); } else { vty_out(vty, "BGP table version is 0, local router ID is %s\n", inet_ntoa( bgp->router_id)); vty_out(vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n"); vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"); vty_out(vty, V4_HEADER); } header = 0; } if (rd_header) { uint16_t type; struct rd_as rd_as; struct rd_ip rd_ip = {0}; #if ENABLE_BGP_VNC struct rd_vnc_eth rd_vnc_eth = { 0}; #endif uint8_t *pnt; pnt = rn->p.u.val; /* Decode RD type. */ type = decode_rd_type(pnt); /* Decode RD value. */ if (type == RD_TYPE_AS) decode_rd_as(pnt + 2, &rd_as); else if (type == RD_TYPE_AS4) decode_rd_as4(pnt + 2, &rd_as); else if (type == RD_TYPE_IP) decode_rd_ip(pnt + 2, &rd_ip); #if ENABLE_BGP_VNC else if (type == RD_TYPE_VNC_ETH) decode_rd_vnc_eth( pnt, &rd_vnc_eth); #endif if (use_json) { char buffer[BUFSIZ]; if (type == RD_TYPE_AS || type == RD_TYPE_AS4) sprintf(buffer, "%u:%d", rd_as.as, rd_as.val); else if (type == RD_TYPE_IP) sprintf(buffer, "%s:%d", inet_ntoa( rd_ip.ip), rd_ip.val); json_object_string_add( json_routes, "routeDistinguisher", buffer); } else { vty_out(vty, "Route Distinguisher: "); if (type == RD_TYPE_AS || type == RD_TYPE_AS4) vty_out(vty, "%u:%d", rd_as.as, rd_as.val); else if (type == RD_TYPE_IP) vty_out(vty, "%s:%d", inet_ntoa( rd_ip.ip), rd_ip.val); #if ENABLE_BGP_VNC else if ( type == RD_TYPE_VNC_ETH) vty_out(vty, "%u:%02x:%02x:%02x:%02x:%02x:%02x", rd_vnc_eth .local_nve_id, rd_vnc_eth .macaddr .octet[0], rd_vnc_eth .macaddr .octet[1], rd_vnc_eth .macaddr .octet[2], rd_vnc_eth .macaddr .octet[3], rd_vnc_eth .macaddr .octet[4], rd_vnc_eth .macaddr .octet[5]); #endif vty_out(vty, "\n"); } rd_header = 0; } route_vty_out_tmp(vty, &rm->p, attr, SAFI_MPLS_VPN, use_json, json_array); } } if (use_json) { struct prefix *p; char buf_a[BUFSIZ]; char buf_b[BUFSIZ]; p = &rm->p; sprintf(buf_a, "%s/%d", inet_ntop(p->family, &p->u.prefix, buf_b, BUFSIZ), p->prefixlen); json_object_object_add(json_routes, buf_a, json_array); } } } if (use_json) { json_object_object_add(json, "routes", json_routes); vty_out(vty, "%s\n", json_object_to_json_string_ext( json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); } return CMD_SUCCESS; }