]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_rd.c
bgpd: Use %pRD for prefix_rd2str()
[mirror_frr.git] / bgpd / bgp_rd.c
CommitLineData
8557760c 1/* BGP RD definitions for BGP-based VPNs (IP/EVPN)
2 * -- brought over from bgpd/bgp_mplsvpn.c
3 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
4 *
5 * This file is part of FRR.
6 *
7 * FRR is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * FRR is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with FRR; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24#include "command.h"
25#include "log.h"
26#include "prefix.h"
27#include "memory.h"
28#include "stream.h"
29#include "filter.h"
5d5ba018 30#include "frrstr.h"
8557760c 31
23d0a753
DA
32#include "lib/printfrr.h"
33
8557760c 34#include "bgpd/bgpd.h"
35#include "bgpd/bgp_rd.h"
36#include "bgpd/bgp_attr.h"
37
49e5a4a0 38#ifdef ENABLE_BGP_VNC
8557760c 39#include "bgpd/rfapi/rfapi_backend.h"
40#endif
41
1be1693e 42uint16_t decode_rd_type(const uint8_t *pnt)
8557760c 43{
d7c0a89a 44 uint16_t v;
8557760c 45
d7c0a89a 46 v = ((uint16_t)*pnt++ << 8);
49e5a4a0 47#ifdef ENABLE_BGP_VNC
d62a17ae 48 /*
49 * VNC L2 stores LHI in lower byte, so omit it
50 */
51 if (v != RD_TYPE_VNC_ETH)
d7c0a89a 52 v |= (uint16_t)*pnt;
d62a17ae 53#else /* duplicate code for clarity */
d7c0a89a 54 v |= (uint16_t)*pnt;
8557760c 55#endif
d62a17ae 56 return v;
8557760c 57}
58
d7c0a89a 59void encode_rd_type(uint16_t v, uint8_t *pnt)
8557760c 60{
d7c0a89a 61 *((uint16_t *)pnt) = htons(v);
8557760c 62}
63
64/* type == RD_TYPE_AS */
1be1693e 65void decode_rd_as(const uint8_t *pnt, struct rd_as *rd_as)
8557760c 66{
d7c0a89a
QY
67 rd_as->as = (uint16_t)*pnt++ << 8;
68 rd_as->as |= (uint16_t)*pnt++;
937652c6 69 ptr_get_be32(pnt, &rd_as->val);
8557760c 70}
71
72/* type == RD_TYPE_AS4 */
1be1693e 73void decode_rd_as4(const uint8_t *pnt, struct rd_as *rd_as)
8557760c 74{
937652c6 75 pnt = ptr_get_be32(pnt, &rd_as->as);
d7c0a89a
QY
76 rd_as->val = ((uint16_t)*pnt++ << 8);
77 rd_as->val |= (uint16_t)*pnt;
8557760c 78}
79
80/* type == RD_TYPE_IP */
5a1ae2c2 81void decode_rd_ip(const uint8_t *pnt, struct rd_ip *rd_ip)
8557760c 82{
d62a17ae 83 memcpy(&rd_ip->ip, pnt, 4);
84 pnt += 4;
8557760c 85
d7c0a89a
QY
86 rd_ip->val = ((uint16_t)*pnt++ << 8);
87 rd_ip->val |= (uint16_t)*pnt;
8557760c 88}
89
49e5a4a0 90#ifdef ENABLE_BGP_VNC
8557760c 91/* type == RD_TYPE_VNC_ETH */
5f040085 92void decode_rd_vnc_eth(const uint8_t *pnt, struct rd_vnc_eth *rd_vnc_eth)
8557760c 93{
d62a17ae 94 rd_vnc_eth->type = RD_TYPE_VNC_ETH;
95 rd_vnc_eth->local_nve_id = pnt[1];
28328ea9 96 memcpy(rd_vnc_eth->macaddr.octet, pnt + 2, ETH_ALEN);
8557760c 97}
98#endif
99
d62a17ae 100int str2prefix_rd(const char *str, struct prefix_rd *prd)
8557760c 101{
af785cf2 102 int ret = 0;
d62a17ae 103 char *p;
104 char *p2;
105 struct stream *s = NULL;
106 char *half = NULL;
107 struct in_addr addr;
108
d62a17ae 109 prd->family = AF_UNSPEC;
110 prd->prefixlen = 64;
111
d62a17ae 112 p = strchr(str, ':');
113 if (!p)
114 goto out;
115
116 if (!all_digit(p + 1))
117 goto out;
118
af785cf2 119 s = stream_new(RD_BYTES);
120
d62a17ae 121 half = XMALLOC(MTYPE_TMP, (p - str) + 1);
122 memcpy(half, str, (p - str));
123 half[p - str] = '\0';
124
125 p2 = strchr(str, '.');
126
127 if (!p2) {
128 unsigned long as_val;
129
130 if (!all_digit(half))
131 goto out;
132
133 as_val = atol(half);
134 if (as_val > 0xffff) {
135 stream_putw(s, RD_TYPE_AS4);
136 stream_putl(s, as_val);
137 stream_putw(s, atol(p + 1));
138 } else {
139 stream_putw(s, RD_TYPE_AS);
140 stream_putw(s, as_val);
141 stream_putl(s, atol(p + 1));
142 }
143 } else {
af785cf2 144 if (!inet_aton(half, &addr))
d62a17ae 145 goto out;
146
147 stream_putw(s, RD_TYPE_IP);
148 stream_put_in_addr(s, &addr);
149 stream_putw(s, atol(p + 1));
150 }
151 memcpy(prd->val, s->data, 8);
af785cf2 152 ret = 1;
8557760c 153
154out:
d62a17ae 155 if (s)
156 stream_free(s);
0a22ddfb 157 XFREE(MTYPE_TMP, half);
af785cf2 158 return ret;
8557760c 159}
160
5f040085 161char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size)
8557760c 162{
5f040085 163 const uint8_t *pnt;
d7c0a89a 164 uint16_t type;
d62a17ae 165 struct rd_as rd_as;
166 struct rd_ip rd_ip;
167
02d32439 168 assert(size >= RD_ADDRSTRLEN);
d62a17ae 169
170 pnt = prd->val;
171
172 type = decode_rd_type(pnt);
173
174 if (type == RD_TYPE_AS) {
175 decode_rd_as(pnt + 2, &rd_as);
6cde4b45 176 snprintf(buf, size, "%u:%u", rd_as.as, rd_as.val);
d62a17ae 177 return buf;
178 } else if (type == RD_TYPE_AS4) {
179 decode_rd_as4(pnt + 2, &rd_as);
6cde4b45 180 snprintf(buf, size, "%u:%u", rd_as.as, rd_as.val);
d62a17ae 181 return buf;
182 } else if (type == RD_TYPE_IP) {
183 decode_rd_ip(pnt + 2, &rd_ip);
23d0a753 184 snprintfrr(buf, size, "%pI4:%hu", &rd_ip.ip, rd_ip.val);
d62a17ae 185 return buf;
186 }
49e5a4a0 187#ifdef ENABLE_BGP_VNC
d62a17ae 188 else if (type == RD_TYPE_VNC_ETH) {
189 snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x",
190 *(pnt + 1), /* LHI */
191 *(pnt + 2), /* MAC[0] */
192 *(pnt + 3), *(pnt + 4), *(pnt + 5), *(pnt + 6),
193 *(pnt + 7));
194
195 return buf;
196 }
8557760c 197#endif
02d32439
DS
198
199 snprintf(buf, size, "Unknown Type: %d", type);
200 return buf;
8557760c 201}
92708db6 202
203void form_auto_rd(struct in_addr router_id,
204 uint16_t rd_id,
205 struct prefix_rd *prd)
206{
207 char buf[100];
208
209 prd->family = AF_UNSPEC;
210 prd->prefixlen = 64;
23d0a753 211 snprintfrr(buf, sizeof(buf), "%pI4:%hu", &router_id, rd_id);
24f8bd87 212 (void)str2prefix_rd(buf, prd);
92708db6 213}
c4f64ea9
DA
214
215printfrr_ext_autoreg_p("RD", printfrr_prd);
216static ssize_t printfrr_prd(struct fbuf *buf, struct printfrr_eargs *ea,
217 const void *ptr)
218{
219 char rd_buf[RD_ADDRSTRLEN];
220
221 if (!ptr)
222 return bputs(buf, "(null)");
223
224 prefix_rd2str(ptr, rd_buf, sizeof(rd_buf));
225
226 return bputs(buf, rd_buf);
227}