BUG-4826: BGP Evpn Nlri's handlers
[bgpcep.git] / bgp / evpn / src / main / java / org / opendaylight / protocol / bgp / evpn / impl / nlri / EvpnNlriParser.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.protocol.bgp.evpn.impl.nlri;
9
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;
13
14 import com.google.common.base.Preconditions;
15 import io.netty.buffer.ByteBuf;
16 import io.netty.buffer.Unpooled;
17 import java.util.ArrayList;
18 import java.util.List;
19 import javax.annotation.Nullable;
20 import org.opendaylight.protocol.bgp.evpn.spi.EvpnRegistry;
21 import org.opendaylight.protocol.bgp.evpn.spi.pojo.SimpleEvpnNlriRegistry;
22 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
23 import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
24 import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.NlriType;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.EvpnChoice;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.destination.EvpnDestination;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.destination.EvpnDestinationBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationEvpnCaseBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.evpn._case.DestinationEvpnBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationEvpnCase;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlri;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutes;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.unreach.nlri.WithdrawnRoutes;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
42 import org.opendaylight.yangtools.yang.binding.DataObject;
43 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
44 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
45 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
46 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 public final class EvpnNlriParser implements NlriParser, NlriSerializer {
51     private static final Logger LOG = LoggerFactory.getLogger(EvpnNlriParser.class);
52     private static final NodeIdentifier EVPN_CHOICE_NID = new NodeIdentifier(EvpnChoice.QNAME);
53
54     public static EvpnDestination extractEvpnDestination(final DataContainerNode<? extends PathArgument> evpnChoice) {
55         final EvpnRegistry reg = SimpleEvpnNlriRegistry.getInstance();
56         final ChoiceNode choiceCont = (ChoiceNode) evpnChoice.getChild(EVPN_CHOICE_NID).get();
57         final EvpnChoice evpnValue = reg.serializeEvpnModel(choiceCont);
58         if (evpnValue == null) {
59             LOG.warn("Unrecognized Nlri {}", choiceCont);
60             return null;
61         }
62         return new EvpnDestinationBuilder().setRouteDistinguisher(extractRouteDistinguisher(evpnChoice)).setEvpnChoice(evpnValue).build();
63     }
64
65     public static EvpnDestination extractRouteKeyDestination(final DataContainerNode<? extends PathArgument> evpnChoice) {
66         final EvpnRegistry reg = SimpleEvpnNlriRegistry.getInstance();
67         final ChoiceNode choiceCont = (ChoiceNode) evpnChoice.getChild(EVPN_CHOICE_NID).get();
68         final EvpnChoice evpnValue = reg.serializeEvpnRouteKey(choiceCont);
69         if (evpnValue == null) {
70             LOG.warn("Unrecognized Nlri {}", choiceCont);
71             return null;
72         }
73         return new EvpnDestinationBuilder().setRouteDistinguisher(extractRouteDistinguisher(evpnChoice)).setEvpnChoice(evpnValue).build();
74     }
75
76     @Override
77     public void parseNlri(final ByteBuf nlri, final MpUnreachNlriBuilder builder) throws BGPParsingException {
78         if (!nlri.isReadable()) {
79             return;
80         }
81         final List<EvpnDestination> dst = parseNlri(nlri);
82
83         builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
84             new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.update.attributes.mp.unreach.nlri.withdrawn.
85                 routes.destination.type.DestinationEvpnCaseBuilder().setDestinationEvpn(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.
86                 yang.bgp.evpn.rev160321.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.evpn._case.DestinationEvpnBuilder()
87                 .setEvpnDestination(dst).build()).build()).build());
88     }
89
90     @Override
91     public void parseNlri(final ByteBuf nlri, final MpReachNlriBuilder builder) throws BGPParsingException {
92         if (!nlri.isReadable()) {
93             return;
94         }
95         final List<EvpnDestination> dst = parseNlri(nlri);
96
97         builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
98             new DestinationEvpnCaseBuilder().setDestinationEvpn(new DestinationEvpnBuilder().setEvpnDestination(dst).build()).build()).build());
99     }
100
101     @Nullable
102     private List<EvpnDestination> parseNlri(final ByteBuf nlri) {
103         if (!nlri.isReadable()) {
104             return null;
105         }
106         final List<EvpnDestination> dests = new ArrayList<>();
107
108         while (nlri.isReadable()) {
109             final EvpnDestinationBuilder builder = new EvpnDestinationBuilder();
110             final NlriType type = NlriType.forValue(nlri.readUnsignedByte());
111             final int length = nlri.readUnsignedByte();
112             final ByteBuf nlriBuf = nlri.readSlice(length);
113             builder.setRouteDistinguisher(parseRouteDistinguisher(nlriBuf));
114             builder.setEvpnChoice(SimpleEvpnNlriRegistry.getInstance().parseEvpn(type, nlriBuf));
115             dests.add(builder.build());
116         }
117         return dests;
118     }
119
120     @Override
121     public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
122         Preconditions.checkArgument(attribute instanceof Attributes, "Attribute parameter is not a Attributes object");
123         final Attributes pathAttributes = (Attributes) attribute;
124         final Attributes1 pathAttributes1 = pathAttributes.getAugmentation(Attributes1.class);
125         final Attributes2 pathAttributes2 = pathAttributes.getAugmentation(Attributes2.class);
126         if (pathAttributes1 != null) {
127             final AdvertizedRoutes routes = (pathAttributes1.getMpReachNlri()).getAdvertizedRoutes();
128             if ((routes != null) && (routes.getDestinationType() instanceof DestinationEvpnCase)) {
129                 final DestinationEvpnCase evpnCase = (DestinationEvpnCase) routes.getDestinationType();
130                 serializeNlri(evpnCase.getDestinationEvpn().getEvpnDestination(), byteAggregator);
131             }
132         } else if (pathAttributes2 != null) {
133             final MpUnreachNlri mpUnreachNlri = pathAttributes2.getMpUnreachNlri();
134             final WithdrawnRoutes withdrawnRoutes = mpUnreachNlri.getWithdrawnRoutes();
135             if (withdrawnRoutes != null && withdrawnRoutes.getDestinationType() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml
136                 .ns.yang.bgp.evpn.rev160321.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationEvpnCase) {
137                 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.update.attributes.mp.unreach.nlri.withdrawn.
138                     routes.destination.type.DestinationEvpnCase evpnCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml
139                     .ns.yang.bgp.evpn.rev160321.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationEvpnCase) mpUnreachNlri.getWithdrawnRoutes().getDestinationType();
140                 serializeNlri(evpnCase.getDestinationEvpn().getEvpnDestination(), byteAggregator);
141             }
142         }
143     }
144
145     public static void serializeNlri(final List<EvpnDestination> cEvpn, final ByteBuf output) {
146         ByteBuf nlriOutput = null;
147         for (final EvpnDestination dest : cEvpn) {
148             final ByteBuf nlriCommon = Unpooled.buffer();
149             serializeRouteDistinquisher(dest.getRouteDistinguisher(), nlriCommon);
150             nlriOutput = SimpleEvpnNlriRegistry.getInstance().serializeEvpn(dest.getEvpnChoice(), nlriCommon);
151         }
152         output.writeBytes(nlriOutput);
153     }
154 }