2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.protocol.bgp.evpn.impl.nlri;
10 import static org.opendaylight.bgp.concepts.RouteDistinguisherUtil.parseRouteDistinguisher;
11 import static org.opendaylight.bgp.concepts.RouteDistinguisherUtil.serializeRouteDistinquisher;
12 import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.extractRouteDistinguisher;
14 import io.netty.buffer.ByteBuf;
15 import io.netty.buffer.Unpooled;
16 import java.util.ArrayList;
17 import java.util.List;
18 import javax.annotation.Nullable;
19 import org.opendaylight.protocol.bgp.evpn.spi.EvpnRegistry;
20 import org.opendaylight.protocol.bgp.evpn.spi.pojo.SimpleEvpnNlriRegistry;
21 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
22 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
23 import org.opendaylight.protocol.bgp.parser.spi.MultiPathSupportUtil;
24 import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
25 import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
26 import org.opendaylight.protocol.bgp.parser.spi.PathIdUtil;
27 import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329.NlriType;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329.evpn.EvpnChoice;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329.evpn.destination.EvpnDestination;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329.evpn.destination.EvpnDestinationBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationEvpnCase;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationEvpnCaseBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.evpn._case.DestinationEvpnBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes1;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes2;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpReachNlri;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpReachNlriBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpUnreachNlri;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpUnreachNlriBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.reach.nlri.AdvertizedRoutes;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.unreach.nlri.WithdrawnRoutes;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.AddressFamily;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.SubsequentAddressFamily;
48 import org.opendaylight.yangtools.yang.common.QName;
49 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
50 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
51 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
52 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
56 public final class EvpnNlriParser implements NlriParser, NlriSerializer {
57 private static final Logger LOG = LoggerFactory.getLogger(EvpnNlriParser.class);
58 private static final NodeIdentifier EVPN_CHOICE_NID = new NodeIdentifier(EvpnChoice.QNAME);
59 private static final NodeIdentifier PATH_ID_NID =
60 new NodeIdentifier(QName.create(EvpnChoice.QNAME, "path-id").intern());
63 private interface ExtractionInterface {
64 EvpnChoice check(EvpnRegistry reg, ChoiceNode cont);
67 public static EvpnDestination extractEvpnDestination(final DataContainerNode<? extends PathArgument> route) {
68 return extractDestination(route, EvpnRegistry::serializeEvpnModel);
71 private static EvpnDestination extractDestination(final DataContainerNode<? extends PathArgument> route,
72 final ExtractionInterface extract) {
73 final EvpnRegistry reg = SimpleEvpnNlriRegistry.getInstance();
74 final ChoiceNode cont = (ChoiceNode) route.getChild(EVPN_CHOICE_NID).get();
75 final EvpnChoice evpnValue = extract.check(reg, cont);
76 if (evpnValue == null) {
77 LOG.warn("Unrecognized Nlri {}", cont);
80 return new EvpnDestinationBuilder()
81 .setRouteDistinguisher(extractRouteDistinguisher(route))
82 .setPathId(PathIdUtil.buildPathId(route, PATH_ID_NID))
83 .setEvpnChoice(evpnValue).build();
86 public static EvpnDestination extractRouteKeyDestination(
87 final DataContainerNode<? extends PathArgument> evpnChoice) {
88 return extractDestination(evpnChoice, EvpnRegistry::serializeEvpnRouteKey);
92 public void parseNlri(final ByteBuf nlri, final MpUnreachNlriBuilder builder,
93 final PeerSpecificParserConstraint constraint) throws BGPParsingException {
94 if (!nlri.isReadable()) {
97 final List<EvpnDestination> dst = parseNlri(nlri, constraint, builder.getAfi(), builder.getSafi());
99 builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
100 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329.update.attributes
101 .mp.unreach.nlri.withdrawn.routes.destination.type.DestinationEvpnCaseBuilder()
102 .setDestinationEvpn(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn
103 .rev180329.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination
104 .evpn._case.DestinationEvpnBuilder().setEvpnDestination(dst).build()).build()).build());
108 public void parseNlri(final ByteBuf nlri, final MpReachNlriBuilder builder,
109 final PeerSpecificParserConstraint constraint) throws BGPParsingException {
110 if (!nlri.isReadable()) {
113 final List<EvpnDestination> dst = parseNlri(nlri, constraint, builder.getAfi(), builder.getSafi());
115 builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
116 new DestinationEvpnCaseBuilder().setDestinationEvpn(new DestinationEvpnBuilder()
117 .setEvpnDestination(dst).build()).build()).build());
121 private static List<EvpnDestination> parseNlri(final ByteBuf nlri, final PeerSpecificParserConstraint constraints,
122 final Class<? extends AddressFamily> afi, final Class<? extends SubsequentAddressFamily> safi) {
123 if (!nlri.isReadable()) {
126 final List<EvpnDestination> dests = new ArrayList<>();
128 while (nlri.isReadable()) {
129 final EvpnDestinationBuilder builder = new EvpnDestinationBuilder();
130 if (MultiPathSupportUtil.isTableTypeSupported(constraints, new BgpTableTypeImpl(afi, safi))) {
131 builder.setPathId(PathIdUtil.readPathId(nlri));
133 final NlriType type = NlriType.forValue(nlri.readUnsignedByte());
134 final int length = nlri.readUnsignedByte();
135 final ByteBuf nlriBuf = nlri.readSlice(length);
136 builder.setRouteDistinguisher(parseRouteDistinguisher(nlriBuf));
137 builder.setEvpnChoice(SimpleEvpnNlriRegistry.getInstance().parseEvpn(type, nlriBuf));
138 dests.add(builder.build());
144 public void serializeAttribute(final Attributes pathAttributes, final ByteBuf byteAggregator) {
145 final Attributes1 pathAttributes1 = pathAttributes.augmentation(Attributes1.class);
146 final Attributes2 pathAttributes2 = pathAttributes.augmentation(Attributes2.class);
147 if (pathAttributes1 != null) {
148 final AdvertizedRoutes routes = pathAttributes1.getMpReachNlri().getAdvertizedRoutes();
149 if (routes != null && routes.getDestinationType() instanceof DestinationEvpnCase) {
150 final DestinationEvpnCase evpnCase = (DestinationEvpnCase) routes.getDestinationType();
151 serializeNlri(evpnCase.getDestinationEvpn().getEvpnDestination(), byteAggregator);
153 } else if (pathAttributes2 != null) {
154 final MpUnreachNlri mpUnreachNlri = pathAttributes2.getMpUnreachNlri();
155 final WithdrawnRoutes withdrawnRoutes = mpUnreachNlri.getWithdrawnRoutes();
156 if (withdrawnRoutes != null && withdrawnRoutes.getDestinationType()
157 instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329
158 .update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationEvpnCase) {
159 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329.update
160 .attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationEvpnCase evpnCase =
161 (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329.update
162 .attributes.mp.unreach.nlri.withdrawn.routes.destination.type
163 .DestinationEvpnCase) mpUnreachNlri.getWithdrawnRoutes().getDestinationType();
164 serializeNlri(evpnCase.getDestinationEvpn().getEvpnDestination(), byteAggregator);
169 public static void serializeNlri(final List<EvpnDestination> destinationList, final ByteBuf output) {
170 ByteBuf nlriOutput = null;
171 for (final EvpnDestination dest : destinationList) {
172 final ByteBuf nlriCommon = Unpooled.buffer();
173 serializeRouteDistinquisher(dest.getRouteDistinguisher(), nlriCommon);
174 nlriOutput = SimpleEvpnNlriRegistry.getInstance().serializeEvpn(dest.getEvpnChoice(), nlriCommon);
176 output.writeBytes(nlriOutput);
180 public boolean convertMpReachToMpUnReach(final MpReachNlri mpReachNlri, final MpUnreachNlriBuilder builder) {
181 final WithdrawnRoutesBuilder withdrawnRoutes = new WithdrawnRoutesBuilder(builder.getWithdrawnRoutes());
182 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329.update.attributes.mp
183 .unreach.nlri.withdrawn.routes.destination.type.DestinationEvpnCaseBuilder destinationType =
184 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329.update
185 .attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationEvpnCaseBuilder(
186 (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329
187 .update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type
188 .DestinationEvpnCase) withdrawnRoutes.getDestinationType());
189 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev180329.update.attributes.mp
190 .unreach.nlri.withdrawn.routes.destination.type.destination.evpn._case.DestinationEvpnBuilder
191 destinationEvpn = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn
192 .rev180329.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.evpn._case
193 .DestinationEvpnBuilder(destinationType.getDestinationEvpn());
194 List<EvpnDestination> evpnDestination = destinationEvpn.getEvpnDestination();
195 if (evpnDestination == null) {
196 evpnDestination = new ArrayList<>();
198 evpnDestination.addAll(((DestinationEvpnCase) mpReachNlri.getAdvertizedRoutes().getDestinationType())
199 .getDestinationEvpn().getEvpnDestination());
200 builder.setWithdrawnRoutes(withdrawnRoutes
201 .setDestinationType(destinationType
202 .setDestinationEvpn(destinationEvpn
203 .setEvpnDestination(evpnDestination)