]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_ecommunity.h
Merge pull request #12780 from opensourcerouting/spdx-license-id
[mirror_frr.git] / bgpd / bgp_ecommunity.h
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/* BGP Extended Communities Attribute.
896014f4 3 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
896014f4 4 */
718e3744 5
00d252cb 6#ifndef _QUAGGA_BGP_ECOMMUNITY_H
7#define _QUAGGA_BGP_ECOMMUNITY_H
8
5b820d9e 9#include "bgpd/bgp_route.h"
7b27cf7b 10#include "bgpd/bgp_rpki.h"
f4bd90c5 11#include "bgpd/bgpd.h"
5b820d9e 12
7e3ebfd1 13/* Refer to rfc7153 for the IANA registry definitions. These are
14 * updated by other standards like rfc7674.
15 */
718e3744 16/* High-order octet of the Extended Communities type field. */
17#define ECOMMUNITY_ENCODE_AS 0x00
18#define ECOMMUNITY_ENCODE_IP 0x01
0b2aa3a0 19#define ECOMMUNITY_ENCODE_AS4 0x02
0014c301 20#define ECOMMUNITY_ENCODE_OPAQUE 0x03
e82202b7 21#define ECOMMUNITY_ENCODE_EVPN 0x06
b72220fc 22#define ECOMMUNITY_ENCODE_REDIRECT_IP_NH 0x08 /* Flow Spec */
7e3ebfd1 23/* Generic Transitive Experimental */
24#define ECOMMUNITY_ENCODE_TRANS_EXP 0x80
25
a8d72b61
PG
26/* RFC7674 */
27#define ECOMMUNITY_EXTENDED_COMMUNITY_PART_2 0x81
28#define ECOMMUNITY_EXTENDED_COMMUNITY_PART_3 0x82
718e3744 29
7e3ebfd1 30/* Non-transitive extended community types. */
31#define ECOMMUNITY_ENCODE_AS_NON_TRANS 0x40
32#define ECOMMUNITY_ENCODE_IP_NON_TRANS 0x41
33#define ECOMMUNITY_ENCODE_AS4_NON_TRANS 0x42
34#define ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS 0x43
35
0014c301 36/* Low-order octet of the Extended Communities type field. */
7e3ebfd1 37/* Note: This really depends on the high-order octet. This means that
38 * multiple definitions for the same value are possible.
39 */
7b27cf7b 40#define ECOMMUNITY_ORIGIN_VALIDATION_STATE 0x00
718e3744 41#define ECOMMUNITY_ROUTE_TARGET 0x02
42#define ECOMMUNITY_SITE_ORIGIN 0x03
650b0511 43#define ECOMMUNITY_LINK_BANDWIDTH 0x04
a8d72b61
PG
44#define ECOMMUNITY_TRAFFIC_RATE 0x06 /* Flow Spec */
45#define ECOMMUNITY_TRAFFIC_ACTION 0x07
46#define ECOMMUNITY_REDIRECT_VRF 0x08
47#define ECOMMUNITY_TRAFFIC_MARKING 0x09
48#define ECOMMUNITY_REDIRECT_IP_NH 0x00
2551b26e
PG
49/* from IANA: bgp-extended-communities/bgp-extended-communities.xhtml
50 * 0x0c Flow-spec Redirect to IPv4 - draft-ietf-idr-flowspec-redirect
51 */
52#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4 0x0c
9a659715
PG
53/* from draft-ietf-idr-flow-spec-v6-09
54 * 0x0b Flow-spec Redirect to IPv6
55 */
56#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0b
718e3744 57
128ea8ab 58/* Low-order octet of the Extended Communities type field for EVPN types */
1e27ef50
PG
59#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00
60#define ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL 0x01
61#define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02
62#define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03
74e2bd89 63#define ECOMMUNITY_EVPN_SUBTYPE_DF_ELECTION 0x06
1e27ef50 64#define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d
68e33151 65#define ECOMMUNITY_EVPN_SUBTYPE_ND 0x08
1e27ef50 66
128ea8ab 67#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY 0x01
7904e9fd 68
74e2bd89
AK
69/* DF alg bits - only lower 5 bits are applicable */
70#define ECOMMUNITY_EVPN_SUBTYPE_DF_ALG_BITS 0x1f
71
7904e9fd
AK
72#define ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG 0x01
73#define ECOMMUNITY_EVPN_SUBTYPE_ND_OVERRIDE_FLAG 0x02
74#define ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG 0x04
128ea8ab 75
4248407b
AK
76#define ECOMMUNITY_EVPN_SUBTYPE_ESI_SA_FLAG (1 << 0) /* single-active */
77
0014c301
LB
78/* Low-order octet of the Extended Communities type field for OPAQUE types */
79#define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c
80
718e3744 81/* Extended communities attribute string format. */
82#define ECOMMUNITY_FORMAT_ROUTE_MAP 0
83#define ECOMMUNITY_FORMAT_COMMUNITY_LIST 1
84#define ECOMMUNITY_FORMAT_DISPLAY 2
85
86/* Extended Communities value is eight octet long. */
87#define ECOMMUNITY_SIZE 8
c6423c31 88#define IPV6_ECOMMUNITY_SIZE 20
718e3744 89
7b27cf7b
DA
90/* Extended Community Origin Validation State */
91enum ecommunity_origin_validation_states {
7b27cf7b
DA
92 ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID,
93 ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND,
324e8b1f
DA
94 ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID,
95 ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED
7b27cf7b
DA
96};
97
4372df71 98/* Extended Communities type flag. */
7c40bf39 99#define ECOMMUNITY_FLAG_NON_TRANSITIVE 0x40
4372df71 100
f5e04c75
PR
101/* Extended Community readable string length */
102#define ECOMMUNITY_STRLEN 64
103
718e3744 104/* Extended Communities attribute. */
d62a17ae 105struct ecommunity {
106 /* Reference counter. */
107 unsigned long refcnt;
718e3744 108
9a659715
PG
109 /* Size of Each Unit of Extended Communities attribute.
110 * to differentiate between IPv6 ext comm and ext comm
111 */
c6423c31 112 uint8_t unit_size;
9a659715 113
d62a17ae 114 /* Size of Extended Communities attribute. */
f6e07e1b 115 uint32_t size;
718e3744 116
d62a17ae 117 /* Extended Communities value. */
d7c0a89a 118 uint8_t *val;
718e3744 119
d62a17ae 120 /* Human readable format string. */
121 char *str;
27aa23a4
DA
122
123 /* Disable IEEE floating-point encoding for extended community */
124 bool disable_ieee_floating;
718e3744 125};
126
5a0ccebf
QY
127struct ecommunity_as {
128 as_t as;
129 uint32_t val;
130};
131
132struct ecommunity_ip {
133 struct in_addr ip;
134 uint16_t val;
135};
136
9a659715
PG
137struct ecommunity_ip6 {
138 struct in6_addr ip;
139 uint16_t val;
140};
141
718e3744 142/* Extended community value is eight octet. */
d62a17ae 143struct ecommunity_val {
144 char val[ECOMMUNITY_SIZE];
718e3744 145};
146
9a659715
PG
147/* IPv6 Extended community value is eight octet. */
148struct ecommunity_val_ipv6 {
149 char val[IPV6_ECOMMUNITY_SIZE];
150};
151
152#define ecom_length_size(X, Y) ((X)->size * (Y))
153
c5900768 154/*
155 * Encode BGP Route Target AS:nn.
156 */
d7c0a89a 157static inline void encode_route_target_as(as_t as, uint32_t val,
d62a17ae 158 struct ecommunity_val *eval)
c5900768 159{
d62a17ae 160 eval->val[0] = ECOMMUNITY_ENCODE_AS;
161 eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
162 eval->val[2] = (as >> 8) & 0xff;
163 eval->val[3] = as & 0xff;
164 eval->val[4] = (val >> 24) & 0xff;
165 eval->val[5] = (val >> 16) & 0xff;
166 eval->val[6] = (val >> 8) & 0xff;
167 eval->val[7] = val & 0xff;
c5900768 168}
169
170/*
171 * Encode BGP Route Target IP:nn.
172 */
d7c0a89a 173static inline void encode_route_target_ip(struct in_addr ip, uint16_t val,
d62a17ae 174 struct ecommunity_val *eval)
c5900768 175{
d62a17ae 176 eval->val[0] = ECOMMUNITY_ENCODE_IP;
177 eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
178 memcpy(&eval->val[2], &ip, sizeof(struct in_addr));
179 eval->val[6] = (val >> 8) & 0xff;
180 eval->val[7] = val & 0xff;
c5900768 181}
182
183/*
184 * Encode BGP Route Target AS4:nn.
185 */
d7c0a89a 186static inline void encode_route_target_as4(as_t as, uint16_t val,
d62a17ae 187 struct ecommunity_val *eval)
c5900768 188{
d62a17ae 189 eval->val[0] = ECOMMUNITY_ENCODE_AS4;
190 eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
191 eval->val[2] = (as >> 24) & 0xff;
192 eval->val[3] = (as >> 16) & 0xff;
193 eval->val[4] = (as >> 8) & 0xff;
194 eval->val[5] = as & 0xff;
195 eval->val[6] = (val >> 8) & 0xff;
196 eval->val[7] = val & 0xff;
c5900768 197}
198
8bcaad3d
DA
199/* Helper function to convert uint32 to IEEE-754 Floating Point */
200static uint32_t uint32_to_ieee_float_uint32(uint32_t u)
201{
202 union {
203 float r;
204 uint32_t d;
205 } f = {.r = (float)u};
206
207 return f.d;
208}
209
ca9ac3ef 210/*
211 * Encode BGP Link Bandwidth extended community
212 * bandwidth (bw) is in bytes-per-sec
213 */
214static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
27aa23a4
DA
215 struct ecommunity_val *eval,
216 bool disable_ieee_floating)
ca9ac3ef 217{
27aa23a4
DA
218 uint32_t bandwidth =
219 disable_ieee_floating ? bw : uint32_to_ieee_float_uint32(bw);
8bcaad3d 220
ca9ac3ef 221 memset(eval, 0, sizeof(*eval));
222 eval->val[0] = ECOMMUNITY_ENCODE_AS;
223 if (non_trans)
224 eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE;
225 eval->val[1] = ECOMMUNITY_LINK_BANDWIDTH;
226 eval->val[2] = (as >> 8) & 0xff;
227 eval->val[3] = as & 0xff;
8bcaad3d
DA
228 eval->val[4] = (bandwidth >> 24) & 0xff;
229 eval->val[5] = (bandwidth >> 16) & 0xff;
230 eval->val[6] = (bandwidth >> 8) & 0xff;
231 eval->val[7] = bandwidth & 0xff;
ca9ac3ef 232}
233
7b27cf7b
DA
234static inline void encode_origin_validation_state(enum rpki_states state,
235 struct ecommunity_val *eval)
236{
237 enum ecommunity_origin_validation_states ovs_state =
238 ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED;
239
240 switch (state) {
241 case RPKI_VALID:
242 ovs_state = ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID;
243 break;
244 case RPKI_NOTFOUND:
245 ovs_state = ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND;
246 break;
247 case RPKI_INVALID:
248 ovs_state = ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID;
249 break;
250 case RPKI_NOT_BEING_USED:
251 break;
252 }
253
254 memset(eval, 0, sizeof(*eval));
255 eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS;
256 eval->val[1] = ECOMMUNITY_ORIGIN_VALIDATION_STATE;
257 eval->val[7] = ovs_state;
258}
259
d62a17ae 260extern void ecommunity_init(void);
261extern void ecommunity_finish(void);
262extern void ecommunity_free(struct ecommunity **);
27aa23a4
DA
263extern struct ecommunity *ecommunity_parse(uint8_t *, unsigned short,
264 bool disable_ieee_floating);
9a659715 265extern struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt,
27aa23a4
DA
266 unsigned short length,
267 bool disable_ieee_floating);
d62a17ae 268extern struct ecommunity *ecommunity_dup(struct ecommunity *);
269extern struct ecommunity *ecommunity_merge(struct ecommunity *,
270 struct ecommunity *);
271extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *);
272extern struct ecommunity *ecommunity_intern(struct ecommunity *);
74df8d6d 273extern bool ecommunity_cmp(const void *arg1, const void *arg2);
df7d4670 274extern void ecommunity_unintern(struct ecommunity **ecommunity);
d8b87afe 275extern unsigned int ecommunity_hash_make(const void *);
d62a17ae 276extern struct ecommunity *ecommunity_str2com(const char *, int, int);
9a659715
PG
277extern struct ecommunity *ecommunity_str2com_ipv6(const char *str, int type,
278 int keyword_included);
d62a17ae 279extern char *ecommunity_ecom2str(struct ecommunity *, int, int);
c7ee6c35 280extern void ecommunity_strfree(char **s);
2d7cdc5b 281extern bool ecommunity_include(struct ecommunity *e1, struct ecommunity *e2);
3dc339cd
DA
282extern bool ecommunity_match(const struct ecommunity *,
283 const struct ecommunity *);
d62a17ae 284extern char *ecommunity_str(struct ecommunity *);
285extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *,
286 uint8_t, uint8_t);
9a659715 287
3dc339cd 288extern bool ecommunity_add_val(struct ecommunity *ecom,
1207a5bc 289 struct ecommunity_val *eval,
290 bool unique, bool overwrite);
9a659715
PG
291extern bool ecommunity_add_val_ipv6(struct ecommunity *ecom,
292 struct ecommunity_val_ipv6 *eval,
293 bool unique, bool overwrite);
00d252cb 294
65efcfce 295/* for vpn */
d62a17ae 296extern struct ecommunity *ecommunity_new(void);
3dc339cd
DA
297extern bool ecommunity_strip(struct ecommunity *ecom, uint8_t type,
298 uint8_t subtype);
d62a17ae 299extern struct ecommunity *ecommunity_new(void);
3dc339cd
DA
300extern bool ecommunity_del_val(struct ecommunity *ecom,
301 struct ecommunity_val *eval);
dacf6ec1
PG
302struct bgp_pbr_entry_action;
303extern int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
f01e580f
PG
304 struct bgp_pbr_entry_action *api,
305 afi_t afi);
dacf6ec1 306
5b820d9e
NT
307extern void bgp_compute_aggregate_ecommunity(
308 struct bgp_aggregate *aggregate,
309 struct ecommunity *ecommunity);
4edd83f9 310
311extern void bgp_compute_aggregate_ecommunity_hash(
312 struct bgp_aggregate *aggregate,
313 struct ecommunity *ecommunity);
314extern void bgp_compute_aggregate_ecommunity_val(
315 struct bgp_aggregate *aggregate);
5b820d9e
NT
316extern void bgp_remove_ecommunity_from_aggregate(
317 struct bgp_aggregate *aggregate,
318 struct ecommunity *ecommunity);
4edd83f9 319extern void bgp_remove_ecomm_from_aggregate_hash(
320 struct bgp_aggregate *aggregate,
321 struct ecommunity *ecommunity);
5b820d9e 322extern void bgp_aggr_ecommunity_remove(void *arg);
d901dc13 323extern const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom,
324 uint32_t *bw);
7b651a32 325extern struct ecommunity *ecommunity_replace_linkbw(as_t as,
27aa23a4
DA
326 struct ecommunity *ecom,
327 uint64_t cum_bw,
328 bool disable_ieee_floating);
e8bfa90e 329
330static inline void ecommunity_strip_rts(struct ecommunity *ecom)
331{
332 uint8_t subtype = ECOMMUNITY_ROUTE_TARGET;
333
334 ecommunity_strip(ecom, ECOMMUNITY_ENCODE_AS, subtype);
335 ecommunity_strip(ecom, ECOMMUNITY_ENCODE_IP, subtype);
336 ecommunity_strip(ecom, ECOMMUNITY_ENCODE_AS4, subtype);
337}
7b27cf7b
DA
338extern struct ecommunity *
339ecommunity_add_origin_validation_state(enum rpki_states rpki_state,
340 struct ecommunity *ecom);
00d252cb 341#endif /* _QUAGGA_BGP_ECOMMUNITY_H */