]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_evpn.c
bgpd: handling EVPN Route Type 5 NLRI message
[mirror_frr.git] / bgpd / bgp_evpn.c
CommitLineData
7ef5a232
PG
1/* Ethernet-VPN Packet and vty Processing File
2 Copyright (C) 2016 6WIND
3
4This file is part of Free Range Routing.
5
6Free Range Routing is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11Free Range Routing is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with Free Range Routing; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21
22#include <zebra.h>
23
24#include "command.h"
25#include "filter.h"
26#include "prefix.h"
27#include "log.h"
28#include "memory.h"
29#include "stream.h"
30
31#include "bgpd/bgp_attr_evpn.h"
32#include "bgpd/bgpd.h"
33#include "bgpd/bgp_table.h"
34#include "bgpd/bgp_route.h"
35#include "bgpd/bgp_attr.h"
36#include "bgpd/bgp_mplsvpn.h"
37#include "bgpd/bgp_evpn.h"
38
39int
40bgp_nlri_parse_evpn (struct peer *peer, struct attr *attr,
41 struct bgp_nlri *packet, int withdraw)
42{
43 u_char *pnt;
44 u_char *lim;
45 struct prefix p;
46 struct prefix_rd prd;
47 struct evpn_addr *p_evpn_p;
48 struct bgp_route_evpn evpn;
49 uint8_t route_type, route_length;
50 u_char *pnt_label;
51 u_int32_t addpath_id = 0;
52
53 /* Check peer status. */
54 if (peer->status != Established)
55 return 0;
56
57 /* Make prefix_rd */
58 prd.family = AF_UNSPEC;
59 prd.prefixlen = 64;
60
61#if !defined(HAVE_EVPN)
62 return -1;
63#endif /* HAVE_EVPN */
64
65 p_evpn_p = &p.u.prefix_evpn;
66 pnt = packet->nlri;
67 lim = pnt + packet->length;
68 while (pnt < lim)
69 {
70 /* clear evpn structure */
71 memset (&evpn, 0, sizeof (evpn));
72
73 /* Clear prefix structure. */
74 memset (&p, 0, sizeof (struct prefix));
75 memset(&evpn.gw_ip, 0, sizeof(union gw_addr));
76 memset(&evpn.eth_s_id, 0, sizeof(struct eth_segment_id));
77
78 /* Fetch Route Type */
79 route_type = *pnt++;
80 route_length = *pnt++;
81 /* simply ignore. goto next route type if any */
82 if(route_type != EVPN_IP_PREFIX)
83 {
84 if (pnt + route_length > lim)
85 {
86 zlog_err ("not enough bytes for New Route Type left in NLRI?");
87 return -1;
88 }
89 pnt += route_length;
90 continue;
91 }
92
93 /* Fetch RD */
94 if (pnt + 8 > lim)
95 {
96 zlog_err ("not enough bytes for RD left in NLRI?");
97 return -1;
98 }
99
100 /* Copy routing distinguisher to rd. */
101 memcpy (&prd.val, pnt, 8);
102 pnt += 8;
103
104 /* Fetch ESI */
105 if (pnt + 10 > lim)
106 {
107 zlog_err ("not enough bytes for ESI left in NLRI?");
108 return -1;
109 }
110 memcpy(&evpn.eth_s_id.val, pnt, 10);
111 pnt += 10;
112
113 /* Fetch Ethernet Tag */
114 if (pnt + 4 > lim)
115 {
116 zlog_err ("not enough bytes for Eth Tag left in NLRI?");
117 return -1;
118 }
119
120 if (route_type == EVPN_IP_PREFIX)
121 {
122 p_evpn_p->route_type = route_type;
123 memcpy (&(p_evpn_p->eth_tag), pnt, 4);
124 p_evpn_p->eth_tag = ntohl(p_evpn_p->eth_tag);
125 pnt += 4;
126
127 /* Fetch IP prefix length. */
128 p_evpn_p->ip_prefix_length = *pnt++;
129
130 if (p_evpn_p->ip_prefix_length > 128)
131 {
132 zlog_err ("invalid prefixlen %d in EVPN NLRI?", p.prefixlen);
133 return -1;
134 }
135 /* determine IPv4 or IPv6 prefix */
136 if(route_length - 4 - 10 - 8 - 3 /* label to be read */ >= 32)
137 {
138 p_evpn_p->flags = IP_PREFIX_V6;
139 memcpy (&(p_evpn_p->ip.v4_addr), pnt, 16);
140 pnt += 16;
141 memcpy(&evpn.gw_ip.ipv6, pnt, 16);
142 pnt += 16;
143 }
144 else
145 {
146 p_evpn_p->flags = IP_PREFIX_V4;
147 memcpy (&(p_evpn_p->ip.v4_addr), pnt, 4);
148 pnt += 4;
149 memcpy(&evpn.gw_ip.ipv4, pnt, 4);
150 pnt += 4;
151 }
152 p.family = AFI_L2VPN;
153 if (p_evpn_p->flags == IP_PREFIX_V4)
154 p.prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
155 else
156 p.prefixlen = PREFIX_LEN_ROUTE_TYPE_5_IPV6;
157 p.family = AF_ETHERNET;
158 }
159
160 /* Fetch Label */
161 if (pnt + 3 > lim)
162 {
163 zlog_err ("not enough bytes for Label left in NLRI?");
164 return -1;
165 }
166 pnt_label = pnt;
167
168 pnt += 3;
169
170 if (!withdraw)
171 {
172 bgp_update (peer, &p, addpath_id, attr, AFI_L2VPN, SAFI_EVPN,
173 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
174 pnt_label, 0, &evpn);
175 }
176 else
177 {
178 bgp_withdraw (peer, &p, addpath_id, attr, AFI_L2VPN, SAFI_EVPN,
179 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
180 &prd, pnt_label, &evpn);
181 }
182 }
183
184 /* Packet length consistency check. */
185 if (pnt != lim)
186 return -1;
187
188 return 0;
189}