]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_rd.c
bgpd: Refactor subgroup_announce_table() to reuse an existing helpers
[mirror_frr.git] / bgpd / bgp_rd.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
8557760c 2/* BGP RD definitions for BGP-based VPNs (IP/EVPN)
3 * -- brought over from bgpd/bgp_mplsvpn.c
4 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
8557760c 5 */
6
7#include <zebra.h>
8#include "command.h"
9#include "log.h"
10#include "prefix.h"
11#include "memory.h"
12#include "stream.h"
13#include "filter.h"
5d5ba018 14#include "frrstr.h"
8557760c 15
23d0a753
DA
16#include "lib/printfrr.h"
17
8557760c 18#include "bgpd/bgpd.h"
19#include "bgpd/bgp_rd.h"
20#include "bgpd/bgp_attr.h"
21
49e5a4a0 22#ifdef ENABLE_BGP_VNC
8557760c 23#include "bgpd/rfapi/rfapi_backend.h"
24#endif
25
1be1693e 26uint16_t decode_rd_type(const uint8_t *pnt)
8557760c 27{
d7c0a89a 28 uint16_t v;
8557760c 29
d7c0a89a 30 v = ((uint16_t)*pnt++ << 8);
49e5a4a0 31#ifdef ENABLE_BGP_VNC
d62a17ae 32 /*
33 * VNC L2 stores LHI in lower byte, so omit it
34 */
35 if (v != RD_TYPE_VNC_ETH)
d7c0a89a 36 v |= (uint16_t)*pnt;
d62a17ae 37#else /* duplicate code for clarity */
d7c0a89a 38 v |= (uint16_t)*pnt;
8557760c 39#endif
d62a17ae 40 return v;
8557760c 41}
42
d7c0a89a 43void encode_rd_type(uint16_t v, uint8_t *pnt)
8557760c 44{
d7c0a89a 45 *((uint16_t *)pnt) = htons(v);
8557760c 46}
47
48/* type == RD_TYPE_AS */
1be1693e 49void decode_rd_as(const uint8_t *pnt, struct rd_as *rd_as)
8557760c 50{
d7c0a89a
QY
51 rd_as->as = (uint16_t)*pnt++ << 8;
52 rd_as->as |= (uint16_t)*pnt++;
937652c6 53 ptr_get_be32(pnt, &rd_as->val);
8557760c 54}
55
56/* type == RD_TYPE_AS4 */
1be1693e 57void decode_rd_as4(const uint8_t *pnt, struct rd_as *rd_as)
8557760c 58{
937652c6 59 pnt = ptr_get_be32(pnt, &rd_as->as);
d7c0a89a
QY
60 rd_as->val = ((uint16_t)*pnt++ << 8);
61 rd_as->val |= (uint16_t)*pnt;
8557760c 62}
63
64/* type == RD_TYPE_IP */
5a1ae2c2 65void decode_rd_ip(const uint8_t *pnt, struct rd_ip *rd_ip)
8557760c 66{
d62a17ae 67 memcpy(&rd_ip->ip, pnt, 4);
68 pnt += 4;
8557760c 69
d7c0a89a
QY
70 rd_ip->val = ((uint16_t)*pnt++ << 8);
71 rd_ip->val |= (uint16_t)*pnt;
8557760c 72}
73
49e5a4a0 74#ifdef ENABLE_BGP_VNC
8557760c 75/* type == RD_TYPE_VNC_ETH */
5f040085 76void decode_rd_vnc_eth(const uint8_t *pnt, struct rd_vnc_eth *rd_vnc_eth)
8557760c 77{
d62a17ae 78 rd_vnc_eth->type = RD_TYPE_VNC_ETH;
79 rd_vnc_eth->local_nve_id = pnt[1];
28328ea9 80 memcpy(rd_vnc_eth->macaddr.octet, pnt + 2, ETH_ALEN);
8557760c 81}
82#endif
83
d62a17ae 84int str2prefix_rd(const char *str, struct prefix_rd *prd)
8557760c 85{
6f167d23
PG
86 int ret = 0, type = RD_TYPE_UNDEFINED;
87 char *p, *p2;
d62a17ae 88 struct stream *s = NULL;
89 char *half = NULL;
90 struct in_addr addr;
4a8cd6ad 91 as_t as_val;
d62a17ae 92
d62a17ae 93 prd->family = AF_UNSPEC;
94 prd->prefixlen = 64;
95
d62a17ae 96 p = strchr(str, ':');
97 if (!p)
98 goto out;
99
6f167d23
PG
100 /* a second ':' is accepted */
101 p2 = strchr(p + 1, ':');
102 if (p2) {
103 /* type is in first part */
104 half = XMALLOC(MTYPE_TMP, (p - str) + 1);
105 memcpy(half, str, (p - str));
106 half[p - str] = '\0';
107 type = atoi(half);
108 if (type != RD_TYPE_AS && type != RD_TYPE_IP &&
109 type != RD_TYPE_AS4)
110 goto out;
111 XFREE(MTYPE_TMP, half);
112 half = XMALLOC(MTYPE_TMP, (p2 - p));
113 memcpy(half, p + 1, (p2 - p - 1));
114 half[p2 - p - 1] = '\0';
115 p = p2 + 1;
116 } else {
117 half = XMALLOC(MTYPE_TMP, (p - str) + 1);
118 memcpy(half, str, (p - str));
119 half[p - str] = '\0';
120 }
d62a17ae 121 if (!all_digit(p + 1))
122 goto out;
123
af785cf2 124 s = stream_new(RD_BYTES);
125
4a8cd6ad
PG
126 /* if it is an AS format or an IP */
127 if (asn_str2asn(half, &as_val)) {
128 if (as_val > UINT16_MAX) {
d62a17ae 129 stream_putw(s, RD_TYPE_AS4);
130 stream_putl(s, as_val);
131 stream_putw(s, atol(p + 1));
6f167d23
PG
132 if (type != RD_TYPE_UNDEFINED && type != RD_TYPE_AS4)
133 goto out;
d62a17ae 134 } else {
135 stream_putw(s, RD_TYPE_AS);
136 stream_putw(s, as_val);
137 stream_putl(s, atol(p + 1));
6f167d23
PG
138 if (type != RD_TYPE_UNDEFINED && type != RD_TYPE_AS)
139 goto out;
d62a17ae 140 }
4a8cd6ad 141 } else if (inet_aton(half, &addr)) {
d62a17ae 142 stream_putw(s, RD_TYPE_IP);
143 stream_put_in_addr(s, &addr);
144 stream_putw(s, atol(p + 1));
6f167d23
PG
145 if (type != RD_TYPE_UNDEFINED && type != RD_TYPE_IP)
146 goto out;
4a8cd6ad
PG
147 } else
148 goto out;
d62a17ae 149 memcpy(prd->val, s->data, 8);
af785cf2 150 ret = 1;
8557760c 151
152out:
d62a17ae 153 if (s)
154 stream_free(s);
0a22ddfb 155 XFREE(MTYPE_TMP, half);
af785cf2 156 return ret;
8557760c 157}
158
4a8cd6ad
PG
159char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size,
160 enum asnotation_mode asnotation)
8557760c 161{
5f040085 162 const uint8_t *pnt;
d7c0a89a 163 uint16_t type;
d62a17ae 164 struct rd_as rd_as;
165 struct rd_ip rd_ip;
4a8cd6ad 166 int len = 0;
d62a17ae 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);
4a8cd6ad
PG
176 len += snprintfrr(buf + len, size - len, ASN_FORMAT(asnotation),
177 &rd_as.as);
178 snprintfrr(buf + len, size - len, ":%u", rd_as.val);
d62a17ae 179 return buf;
180 } else if (type == RD_TYPE_AS4) {
181 decode_rd_as4(pnt + 2, &rd_as);
4a8cd6ad
PG
182 len += snprintfrr(buf + len, size - len, ASN_FORMAT(asnotation),
183 &rd_as.as);
184 snprintfrr(buf + len, size - len, ":%u", rd_as.val);
d62a17ae 185 return buf;
186 } else if (type == RD_TYPE_IP) {
187 decode_rd_ip(pnt + 2, &rd_ip);
23d0a753 188 snprintfrr(buf, size, "%pI4:%hu", &rd_ip.ip, rd_ip.val);
d62a17ae 189 return buf;
190 }
49e5a4a0 191#ifdef ENABLE_BGP_VNC
d62a17ae 192 else if (type == RD_TYPE_VNC_ETH) {
193 snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x",
194 *(pnt + 1), /* LHI */
195 *(pnt + 2), /* MAC[0] */
196 *(pnt + 3), *(pnt + 4), *(pnt + 5), *(pnt + 6),
197 *(pnt + 7));
198
199 return buf;
200 }
8557760c 201#endif
02d32439
DS
202
203 snprintf(buf, size, "Unknown Type: %d", type);
204 return buf;
8557760c 205}
92708db6 206
207void form_auto_rd(struct in_addr router_id,
208 uint16_t rd_id,
209 struct prefix_rd *prd)
210{
211 char buf[100];
212
213 prd->family = AF_UNSPEC;
214 prd->prefixlen = 64;
23d0a753 215 snprintfrr(buf, sizeof(buf), "%pI4:%hu", &router_id, rd_id);
24f8bd87 216 (void)str2prefix_rd(buf, prd);
92708db6 217}
c4f64ea9 218
4a8cd6ad
PG
219static ssize_t printfrr_prd_asnotation(struct fbuf *buf,
220 struct printfrr_eargs *ea,
221 const void *ptr,
222 enum asnotation_mode asnotation)
c4f64ea9
DA
223{
224 char rd_buf[RD_ADDRSTRLEN];
225
226 if (!ptr)
227 return bputs(buf, "(null)");
228
4a8cd6ad 229 prefix_rd2str(ptr, rd_buf, sizeof(rd_buf), asnotation);
c4f64ea9
DA
230
231 return bputs(buf, rd_buf);
232}
4a8cd6ad
PG
233
234printfrr_ext_autoreg_p("RDP", printfrr_prd);
235static ssize_t printfrr_prd(struct fbuf *buf, struct printfrr_eargs *ea,
236 const void *ptr)
237{
238 return printfrr_prd_asnotation(buf, ea, ptr, ASNOTATION_PLAIN);
239}
240
241printfrr_ext_autoreg_p("RDD", printfrr_prd_dot);
242static ssize_t printfrr_prd_dot(struct fbuf *buf, struct printfrr_eargs *ea,
243 const void *ptr)
244{
245 return printfrr_prd_asnotation(buf, ea, ptr, ASNOTATION_DOT);
246}
247
248printfrr_ext_autoreg_p("RDE", printfrr_prd_dotplus);
249static ssize_t printfrr_prd_dotplus(struct fbuf *buf, struct printfrr_eargs *ea,
250 const void *ptr)
251{
252 return printfrr_prd_asnotation(buf, ea, ptr, ASNOTATION_DOTPLUS);
253}