blob: 2059e563b396cd76eab22f8ed3f84b7f8419f2a3 [file] [log] [blame]
Mohammad Shahid30fedc52017-08-09 11:49:40 +05301/*
2 * Copyright 2017-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 * the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 * specific language governing permissions and limitations under the License.
12 */
13
14package org.onosproject.provider.bgp.route.impl;
15
Ray Milkeyd84f89b2018-08-17 14:54:17 -070016import org.osgi.service.component.annotations.Activate;
17import org.osgi.service.component.annotations.Component;
18import org.osgi.service.component.annotations.Deactivate;
19import org.osgi.service.component.annotations.Reference;
20import org.osgi.service.component.annotations.ReferenceCardinality;
Mohammad Shahid30fedc52017-08-09 11:49:40 +053021import org.onlab.packet.Ip4Address;
22import org.onlab.packet.IpAddress;
23import org.onlab.packet.IpPrefix;
24import org.onlab.packet.MacAddress;
25import org.onosproject.bgp.controller.BgpController;
26import org.onosproject.bgp.controller.BgpId;
27import org.onosproject.bgp.controller.BgpPeer.FlowSpecOperation;
28import org.onosproject.bgp.controller.BgpRouteListener;
29import org.onosproject.bgpio.protocol.BgpEvpnNlri;
30import org.onosproject.bgpio.protocol.BgpUpdateMsg;
31import org.onosproject.bgpio.protocol.evpn.BgpEvpnNlriImpl;
32import org.onosproject.bgpio.protocol.evpn.BgpEvpnRouteType;
33import org.onosproject.bgpio.protocol.evpn.BgpEvpnRouteType2Nlri;
34import org.onosproject.bgpio.types.BgpEvpnEsi;
35import org.onosproject.bgpio.types.BgpEvpnLabel;
36import org.onosproject.bgpio.types.BgpExtendedCommunity;
37import org.onosproject.bgpio.types.BgpNlriType;
38import org.onosproject.bgpio.types.BgpValueType;
39import org.onosproject.bgpio.types.MpReachNlri;
40import org.onosproject.bgpio.types.MpUnReachNlri;
41import org.onosproject.bgpio.types.RouteDistinguisher;
42import org.onosproject.bgpio.types.RouteTarget;
Ray Milkeya95193c2017-08-10 15:35:36 -070043import org.onosproject.evpnrouteservice.EvpnRoute;
44import org.onosproject.evpnrouteservice.EvpnRoute.Source;
45import org.onosproject.evpnrouteservice.EvpnRouteAdminService;
46import org.onosproject.evpnrouteservice.EvpnRouteEvent;
47import org.onosproject.evpnrouteservice.EvpnRouteListener;
48import org.onosproject.evpnrouteservice.VpnRouteTarget;
Mohammad Shahid30fedc52017-08-09 11:49:40 +053049import org.onosproject.net.provider.AbstractProvider;
50import org.onosproject.net.provider.ProviderId;
51import org.slf4j.Logger;
52import org.slf4j.LoggerFactory;
53
54import java.net.InetAddress;
55import java.util.ArrayList;
56import java.util.Collections;
57import java.util.Iterator;
58import java.util.LinkedList;
59import java.util.List;
60
61/**
62 * Provider which uses an BGP controller to update/delete route.
63 */
64@Component(immediate = true)
65public class BgpRouteProvider extends AbstractProvider {
66
67 /**
68 * Creates an instance of BGP route provider.
69 */
70 public BgpRouteProvider() {
71 super(new ProviderId("route",
72 "org.onosproject.provider.bgp.route.impl"));
73 }
74
75 private static final Logger log = LoggerFactory
76 .getLogger(BgpRouteProvider.class);
77
78
Ray Milkeyd84f89b2018-08-17 14:54:17 -070079 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Mohammad Shahid30fedc52017-08-09 11:49:40 +053080 protected BgpController controller;
81
Ray Milkeyd84f89b2018-08-17 14:54:17 -070082 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Mohammad Shahid30fedc52017-08-09 11:49:40 +053083 protected EvpnRouteAdminService evpnRouteAdminService;
84
85 private final InternalEvpnRouteListener routeListener = new
86 InternalEvpnRouteListener();
87 private final InternalBgpRouteListener bgpRouteListener = new
88 InternalBgpRouteListener();
89
90
91 @Activate
92 public void activate() {
93 controller.addRouteListener(bgpRouteListener);
94 evpnRouteAdminService.addListener(routeListener);
95 log.info("Started");
96 }
97
98 @Deactivate
99 public void deactivate() {
100 controller.removeRouteListener(bgpRouteListener);
101 evpnRouteAdminService.removeListener(routeListener);
102 log.info("Stopped");
103 }
104
105 /**
106 * Handles the bgp route update message.
107 *
108 * @param operationType operationType
109 * @param rdString rd
110 * @param exportRtList rt export
111 * @param nextHop next hop
112 * @param macAddress mac address
113 * @param ipAddress ip address
114 * @param labelInt label
115 */
116 private void sendUpdateMessage(FlowSpecOperation operationType,
117 String rdString,
118 List<VpnRouteTarget> exportRtList,
119 IpAddress nextHop,
120 MacAddress macAddress,
121 InetAddress ipAddress,
122 int labelInt) {
123 log.info("sendUpdateMessage 1");
124
125 List<BgpEvpnNlri> eVpnNlri = new ArrayList<BgpEvpnNlri>();
126 RouteDistinguisher rd = stringToRD(rdString);
127 BgpEvpnEsi esi = new BgpEvpnEsi(new byte[10]);
128 int ethernetTagID = 0;
129 BgpEvpnLabel mplsLabel1 = intToLabel(labelInt);
130 BgpEvpnLabel mplsLabel2 = null;
131
132 List<BgpValueType> extCom = new ArrayList<BgpValueType>();
133 if ((operationType == FlowSpecOperation.UPDATE)
134 && (!exportRtList.isEmpty())) {
135 for (VpnRouteTarget rt : exportRtList) {
136 RouteTarget rTarget = stringToRT(rt.getRouteTarget());
137 extCom.add(rTarget);
138 }
139 }
140 BgpEvpnRouteType2Nlri routeTypeSpec =
141 new BgpEvpnRouteType2Nlri(rd,
142 esi,
143 ethernetTagID,
144 macAddress,
145 ipAddress,
146 mplsLabel1,
147 mplsLabel2);
148 BgpEvpnNlri nlri = new BgpEvpnNlriImpl(BgpEvpnRouteType
149 .MAC_IP_ADVERTISEMENT
150 .getType(),
151 routeTypeSpec);
152 eVpnNlri.add(nlri);
153 log.info("sendUpdateMessage 2");
154 controller.getPeers().forEach(peer -> {
155 log.info("Send route update eVpnComponents {} to peer {}",
156 eVpnNlri, peer);
157 peer.updateEvpnNlri(operationType, nextHop, extCom, eVpnNlri);
158 });
159
160 }
161
162 private static RouteDistinguisher stringToRD(String rdString) {
163 if (rdString.contains(":")) {
164 if ((rdString.indexOf(":") != 0)
165 && (rdString.indexOf(":") != rdString.length() - 1)) {
166 String[] tem = rdString.split(":");
167 short as = (short) Integer.parseInt(tem[0]);
168 int assignednum = Integer.parseInt(tem[1]);
169 long rd = ((long) assignednum & 0xFFFFFFFFL)
170 | (((long) as << 32) & 0xFFFFFFFF00000000L);
171 return new RouteDistinguisher(rd);
172 }
173 }
174 return null;
175
176 }
177
178 private static String rdToString(RouteDistinguisher rd) {
179 long rdLong = rd.getRouteDistinguisher();
180 int as = (int) ((rdLong & 0xFFFFFFFF00000000L) >> 32);
181 int assignednum = (int) (rdLong & 0xFFFFFFFFL);
182 String result = as + ":" + assignednum;
183 return result;
184 }
185
186 private static RouteTarget stringToRT(String rdString) {
187 if (rdString.contains(":")) {
188 if ((rdString.indexOf(":") != 0)
189 && (rdString.indexOf(":") != rdString.length() - 1)) {
190 String[] tem = rdString.split(":");
191 short as = Short.parseShort(tem[0]);
192 int assignednum = Integer.parseInt(tem[1]);
193
194 byte[] rt = new byte[]{(byte) ((as >> 8) & 0xFF),
195 (byte) (as & 0xFF),
196 (byte) ((assignednum >> 24) & 0xFF),
197 (byte) ((assignednum >> 16) & 0xFF),
198 (byte) ((assignednum >> 8) & 0xFF),
199 (byte) (assignednum & 0xFF)};
200 short type = 0x02;
201 return new RouteTarget(type, rt);
202 }
203 }
204 return null;
205
206 }
207
208 private static String rtToString(RouteTarget rt) {
209 byte[] b = rt.getRouteTarget();
210
211 int assignednum = b[5] & 0xFF | (b[4] & 0xFF) << 8 | (b[3] & 0xFF) << 16
212 | (b[2] & 0xFF) << 24;
213 short as = (short) (b[1] & 0xFF | (b[0] & 0xFF) << 8);
214 String result = as + ":" + assignednum;
215 return result;
216 }
217
218 private static BgpEvpnLabel intToLabel(int labelInt) {
219 byte[] label = new byte[]{(byte) ((labelInt >> 16) & 0xFF),
220 (byte) ((labelInt >> 8) & 0xFF),
221 (byte) (labelInt & 0xFF)};
222
223 return new BgpEvpnLabel(label);
224 }
225
226 private static int labelToInt(BgpEvpnLabel label) {
227 byte[] b = label.getMplsLabel();
228 return b[2] & 0xFF | (b[1] & 0xFF) << 8 | (b[0] & 0xFF) << 16;
229
230 }
231
232 private class InternalBgpRouteListener implements BgpRouteListener {
233
234 @Override
235 public void processRoute(BgpId bgpId, BgpUpdateMsg updateMsg) {
236 log.info("Evpn route event received from BGP protocol");
237 List<BgpValueType> pathAttr = updateMsg.bgpPathAttributes()
238 .pathAttributes();
239 Iterator<BgpValueType> iterator = pathAttr.iterator();
240 RouteTarget rt = null;
241 List<VpnRouteTarget> exportRt = new LinkedList<>();
242 List<BgpEvpnNlri> evpnReachNlri = new LinkedList<>();
243 List<BgpEvpnNlri> evpnUnreachNlri = new LinkedList<>();
244
245 Ip4Address ipNextHop = null;
246 while (iterator.hasNext()) {
247 BgpValueType attr = iterator.next();
248 if (attr instanceof MpReachNlri) {
249 MpReachNlri mpReachNlri = (MpReachNlri) attr;
250 ipNextHop = mpReachNlri.nexthop4();
251 if (mpReachNlri
252 .getNlriDetailsType() == BgpNlriType.EVPN) {
253 evpnReachNlri.addAll(mpReachNlri.bgpEvpnNlri());
254 }
255
256 }
257 if (attr instanceof MpUnReachNlri) {
258 MpUnReachNlri mpUnReachNlri = (MpUnReachNlri) attr;
259 if (mpUnReachNlri
260 .getNlriDetailsType() == BgpNlriType.EVPN) {
261 evpnUnreachNlri.addAll(mpUnReachNlri.bgpEvpnNlri());
262 }
263 }
264
265 if (attr instanceof BgpExtendedCommunity) {
266 BgpExtendedCommunity extCom = (BgpExtendedCommunity) attr;
267 Iterator<BgpValueType> extIte = extCom.fsActionTlv()
268 .iterator();
269 while (extIte.hasNext()) {
270 BgpValueType extAttr = extIte.next();
271 if (extAttr instanceof RouteTarget) {
272 rt = (RouteTarget) extAttr;
273 exportRt.add(VpnRouteTarget
274 .routeTarget(rtToString(rt)));
275 break;
276 }
277 }
278 }
279 }
280
281 if ((!exportRt.isEmpty()) && (!evpnReachNlri.isEmpty())) {
282 for (BgpEvpnNlri nlri : evpnReachNlri) {
283 if (nlri.getRouteType() == BgpEvpnRouteType
284 .MAC_IP_ADVERTISEMENT) {
285 BgpEvpnRouteType2Nlri macIpAdvNlri
286 = (BgpEvpnRouteType2Nlri) nlri
287 .getNlri();
288 MacAddress macAddress = macIpAdvNlri.getMacAddress();
289 Ip4Address ipAddress = Ip4Address
290 .valueOf(macIpAdvNlri.getIpAddress());
291 RouteDistinguisher rd = macIpAdvNlri
292 .getRouteDistinguisher();
293 BgpEvpnLabel label = macIpAdvNlri.getMplsLable1();
294 log.info("Route Provider received bgp packet {} " +
295 "to route system.",
296 macIpAdvNlri.toString());
297 // Add route to route system
298 Source source = Source.REMOTE;
299 EvpnRoute evpnRoute = new EvpnRoute(source,
300 macAddress,
301 IpPrefix.valueOf(ipAddress, 32),
302 ipNextHop,
303 rdToString(rd),
304 null, //empty rt
305 exportRt,
306 labelToInt(label));
307
308 evpnRouteAdminService.update(Collections
309 .singleton(evpnRoute));
310 }
311 }
312 }
313
314 if (!evpnUnreachNlri.isEmpty()) {
315 for (BgpEvpnNlri nlri : evpnUnreachNlri) {
316 if (nlri.getRouteType() == BgpEvpnRouteType
317 .MAC_IP_ADVERTISEMENT) {
318 BgpEvpnRouteType2Nlri macIpAdvNlri
319 = (BgpEvpnRouteType2Nlri) nlri
320 .getNlri();
321 MacAddress macAddress = macIpAdvNlri.getMacAddress();
322 Ip4Address ipAddress = Ip4Address
323 .valueOf(macIpAdvNlri.getIpAddress());
324 RouteDistinguisher rd = macIpAdvNlri
325 .getRouteDistinguisher();
326 BgpEvpnLabel label = macIpAdvNlri.getMplsLable1();
327 log.info("Route Provider received bgp packet {} " +
328 "and remove from route system.",
329 macIpAdvNlri.toString());
330 // Delete route from route system
331 Source source = Source.REMOTE;
332 // For mpUnreachNlri, nexthop and rt is null
333 EvpnRoute evpnRoute = new EvpnRoute(source,
334 macAddress,
335 IpPrefix.valueOf(ipAddress, 32),
336 null,
337 rdToString(rd),
338 null,
339 null,
340 labelToInt(label));
341
342 evpnRouteAdminService.withdraw(Collections
343 .singleton(evpnRoute));
344 }
345 }
346 }
347 }
348 }
349
350 private class InternalEvpnRouteListener implements EvpnRouteListener {
351
352 @Override
353 public void event(EvpnRouteEvent event) {
354 log.info("evpnroute event is received from evpn route manager");
355 FlowSpecOperation operationType = null;
356 EvpnRoute route = event.subject();
357 EvpnRoute evpnRoute = route;
358 log.info("Event received for public route {}", evpnRoute);
359 if (evpnRoute.source().equals(Source.REMOTE)) {
360 return;
361 }
362 switch (event.type()) {
363 case ROUTE_ADDED:
364 case ROUTE_UPDATED:
365 log.info("route added");
366 operationType = FlowSpecOperation.UPDATE;
367 break;
368 case ROUTE_REMOVED:
369 log.info("route deleted");
370 operationType = FlowSpecOperation.DELETE;
371 break;
372 default:
373 break;
374 }
375
376 String rdString = evpnRoute.routeDistinguisher()
377 .getRouteDistinguisher();
378 MacAddress macAddress = evpnRoute.prefixMac();
379 InetAddress inetAddress = evpnRoute.prefixIp().address().toInetAddress();
380 IpAddress nextHop = evpnRoute.ipNextHop();
381 List<VpnRouteTarget> exportRtList = evpnRoute
382 .exportRouteTarget();
383 int labelInt = evpnRoute.label().getLabel();
384
385 sendUpdateMessage(operationType,
386 rdString,
387 exportRtList,
388 nextHop,
389 macAddress,
390 inetAddress,
391 labelInt);
392 }
393 }
Ray Milkeya95193c2017-08-10 15:35:36 -0700394}