diff options
author | vivek <vivek@cumulusnetworks.com> | 2017-05-15 21:33:59 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2017-07-12 18:34:32 +0200 |
commit | 8557760ca8d05af9864a02bc2f4a244d02adf10c (patch) | |
tree | 5afc01ed898477a1177d99acd732054cbe6006ea /bgpd/bgp_rd.c | |
parent | bgpd: Refine extended community handling (diff) | |
download | frr-8557760ca8d05af9864a02bc2f4a244d02adf10c.tar.xz frr-8557760ca8d05af9864a02bc2f4a244d02adf10c.zip |
bgpd: Separate out RD handling functions
BGP Route Distinguisher (RD) handling is common for different flavors
of BGP VPNs such as BGP/MPLS IP VPNs (RFC 4364) and BGP EVPNs (RFC 7432).
Separate out the RD handling functions into its own files.
Note: No functional change introduced with this commit.
Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'bgpd/bgp_rd.c')
-rw-r--r-- | bgpd/bgp_rd.c | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/bgpd/bgp_rd.c b/bgpd/bgp_rd.c new file mode 100644 index 000000000..03257a292 --- /dev/null +++ b/bgpd/bgp_rd.c @@ -0,0 +1,232 @@ +/* BGP RD definitions for BGP-based VPNs (IP/EVPN) + * -- brought over from bgpd/bgp_mplsvpn.c + * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org> + * + * This file is part of FRR. + * + * FRR 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. + * + * FRR 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 FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <zebra.h> +#include "command.h" +#include "log.h" +#include "prefix.h" +#include "memory.h" +#include "stream.h" +#include "filter.h" + +#include "bgpd/bgpd.h" +#include "bgpd/bgp_rd.h" +#include "bgpd/bgp_attr.h" + +#if ENABLE_BGP_VNC +#include "bgpd/rfapi/rfapi_backend.h" +#endif + +u_int16_t +decode_rd_type (u_char *pnt) +{ + u_int16_t v; + + v = ((u_int16_t) *pnt++ << 8); +#if ENABLE_BGP_VNC + /* + * VNC L2 stores LHI in lower byte, so omit it + */ + if (v != RD_TYPE_VNC_ETH) + v |= (u_int16_t) *pnt; +#else /* duplicate code for clarity */ + v |= (u_int16_t) *pnt; +#endif + return v; +} + +void +encode_rd_type (u_int16_t v, u_char *pnt) +{ + *((u_int16_t *)pnt) = htons(v); +} + +/* type == RD_TYPE_AS */ +void +decode_rd_as (u_char *pnt, struct rd_as *rd_as) +{ + rd_as->as = (u_int16_t) *pnt++ << 8; + rd_as->as |= (u_int16_t) *pnt++; + + rd_as->val = ((u_int32_t) *pnt++ << 24); + rd_as->val |= ((u_int32_t) *pnt++ << 16); + rd_as->val |= ((u_int32_t) *pnt++ << 8); + rd_as->val |= (u_int32_t) *pnt; +} + +/* type == RD_TYPE_AS4 */ +void +decode_rd_as4 (u_char *pnt, struct rd_as *rd_as) +{ + rd_as->as = (u_int32_t) *pnt++ << 24; + rd_as->as |= (u_int32_t) *pnt++ << 16; + rd_as->as |= (u_int32_t) *pnt++ << 8; + rd_as->as |= (u_int32_t) *pnt++; + + rd_as->val = ((u_int16_t) *pnt++ << 8); + rd_as->val |= (u_int16_t) *pnt; +} + +/* type == RD_TYPE_IP */ +void +decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip) +{ + memcpy (&rd_ip->ip, pnt, 4); + pnt += 4; + + rd_ip->val = ((u_int16_t) *pnt++ << 8); + rd_ip->val |= (u_int16_t) *pnt; +} + +#if ENABLE_BGP_VNC +/* type == RD_TYPE_VNC_ETH */ +void +decode_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth) +{ + rd_vnc_eth->type = RD_TYPE_VNC_ETH; + rd_vnc_eth->local_nve_id = pnt[1]; + memcpy (rd_vnc_eth->macaddr.octet, pnt + 2, ETHER_ADDR_LEN); +} +#endif + +int +str2prefix_rd (const char *str, struct prefix_rd *prd) +{ + int ret; /* ret of called functions */ + int lret; /* local ret, of this func */ + char *p; + char *p2; + struct stream *s = NULL; + char *half = NULL; + struct in_addr addr; + + s = stream_new (8); + + prd->family = AF_UNSPEC; + prd->prefixlen = 64; + + lret = 0; + p = strchr (str, ':'); + if (! p) + goto out; + + if (! all_digit (p + 1)) + goto out; + + half = XMALLOC (MTYPE_TMP, (p - str) + 1); + memcpy (half, str, (p - str)); + half[p - str] = '\0'; + + p2 = strchr (str, '.'); + + if (! p2) + { + unsigned long as_val; + + if (! all_digit (half)) + goto out; + + as_val = atol(half); + if (as_val > 0xffff) + { + stream_putw (s, RD_TYPE_AS4); + stream_putl (s, as_val); + stream_putw (s, atol (p + 1)); + } + else + { + stream_putw (s, RD_TYPE_AS); + stream_putw (s, as_val); + stream_putl (s, atol (p + 1)); + } + } + else + { + ret = inet_aton (half, &addr); + if (! ret) + goto out; + + stream_putw (s, RD_TYPE_IP); + stream_put_in_addr (s, &addr); + stream_putw (s, atol (p + 1)); + } + memcpy (prd->val, s->data, 8); + lret = 1; + +out: + if (s) + stream_free (s); + if (half) + XFREE(MTYPE_TMP, half); + return lret; +} + +char * +prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size) +{ + u_char *pnt; + u_int16_t type; + struct rd_as rd_as; + struct rd_ip rd_ip; + + if (size < RD_ADDRSTRLEN) + return NULL; + + pnt = prd->val; + + type = decode_rd_type (pnt); + + if (type == RD_TYPE_AS) + { + decode_rd_as (pnt + 2, &rd_as); + snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val); + return buf; + } + else if (type == RD_TYPE_AS4) + { + decode_rd_as4 (pnt + 2, &rd_as); + snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val); + return buf; + } + else if (type == RD_TYPE_IP) + { + decode_rd_ip (pnt + 2, &rd_ip); + snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); + return buf; + } +#if ENABLE_BGP_VNC + else if (type == RD_TYPE_VNC_ETH) + { + snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x", + *(pnt+1), /* LHI */ + *(pnt+2), /* MAC[0] */ + *(pnt+3), + *(pnt+4), + *(pnt+5), + *(pnt+6), + *(pnt+7)); + + return buf; + } +#endif + return NULL; +} |