Improve RouteDistinguisherUtil
[bgpcep.git] / bgp / extensions / flowspec / src / main / java / org / opendaylight / protocol / bgp / flowspec / l3vpn / AbstractFlowspecL3vpnNlriParser.java
1 /*
2  * Copyright (c) 2016 Brocade Communications 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.flowspec.l3vpn;
9
10 import static org.opendaylight.bgp.concepts.RouteDistinguisherUtil.extractRouteDistinguisher;
11
12 import com.google.common.annotations.VisibleForTesting;
13 import io.netty.buffer.ByteBuf;
14 import io.netty.buffer.Unpooled;
15 import java.util.ArrayList;
16 import java.util.List;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.bgp.concepts.RouteDistinguisherUtil;
20 import org.opendaylight.protocol.bgp.flowspec.AbstractFlowspecNlriParser;
21 import org.opendaylight.protocol.bgp.flowspec.FlowspecTypeRegistry;
22 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.Flowspec;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.FlowspecBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.PathId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.destination.DestinationType;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.RouteDistinguisher;
28 import org.opendaylight.yangtools.yang.common.QName;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
30 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 public abstract class AbstractFlowspecL3vpnNlriParser extends AbstractFlowspecNlriParser {
35     private static final Logger LOG = LoggerFactory.getLogger(AbstractFlowspecL3vpnNlriParser.class);
36     public static final NodeIdentifier RD_NID =
37         new NodeIdentifier(QName.create(Flowspec.QNAME, "route-distinguisher").intern());
38
39     protected AbstractFlowspecL3vpnNlriParser(final FlowspecTypeRegistry flowspecTypeRegistry) {
40         super(flowspecTypeRegistry);
41     }
42
43     @Override
44     public final String stringNlri(final DataContainerNode flowspec) {
45         final StringBuilder buffer = new StringBuilder();
46         final RouteDistinguisher rd = extractRouteDistinguisher(flowspec, RD_NID);
47         if (rd != null) {
48             buffer.append("[l3vpn with route-distinguisher ").append(rd.stringValue()).append("] ");
49         }
50         buffer.append(super.stringNlri(flowspec));
51         return buffer.toString();
52     }
53
54     /**
55      * For flowspec-l3vpn, there is a route distinguisher field at the beginning of NLRI (8 bytes).
56      */
57     private static @NonNull RouteDistinguisher readRouteDistinguisher(final ByteBuf nlri) {
58         final var rd = RouteDistinguisherUtil.parseRouteDistinguisher(nlri);
59         LOG.trace("Route Distinguisher read from NLRI: {}", rd);
60         return rd;
61     }
62
63     @VisibleForTesting
64     public final void serializeNlri(final @NonNull RouteDistinguisher rd, final List<Flowspec> flowspecList,
65             final @Nullable PathId pathId, final @NonNull ByteBuf buffer) {
66         final var nlri = Unpooled.buffer();
67         RouteDistinguisherUtil.serializeRouteDistinquisher(rd, nlri);
68         serializeNlri(flowspecList, nlri);
69         appendNlri(pathId, nlri, buffer);
70     }
71
72     @Override
73     protected final DestinationType parseAdvertizedNlri(final ByteBuf nlri, final PathId pathId)
74             throws BGPParsingException {
75         readNlriLength(nlri);
76         return createAdvertizedRoutesDestinationType(readRouteDistinguisher(nlri),
77             parseL3vpnNlriFlowspecList(nlri), pathId);
78     }
79
80     /**
81      * Create advertized destination type.
82      *
83      * @param rd           the RouteDistinguisher
84      * @param flowspecList a list of {@link Flowspec}s
85      * @param pathId       associated path id with given destination
86      * @return created destination type
87      */
88     protected abstract @NonNull DestinationType createAdvertizedRoutesDestinationType(RouteDistinguisher rd,
89         @Nullable List<Flowspec> flowspecList, @Nullable PathId pathId);
90
91     @Override
92     protected final DestinationType parseWithdrawnNlri(final ByteBuf nlri, final PathId pathId)
93             throws BGPParsingException {
94         readNlriLength(nlri);
95         return createWithdrawnDestinationType(readRouteDistinguisher(nlri), parseL3vpnNlriFlowspecList(nlri), pathId);
96     }
97
98     /**
99      * Create withdrawn destination type.
100      *
101      * @param rd           the RouteDistinguisher
102      * @param flowspecList a list of {@link Flowspec}s
103      * @param pathId       associated path id with given destination
104      * @return created destination type
105      */
106     protected abstract @NonNull DestinationType createWithdrawnDestinationType(RouteDistinguisher rd,
107         @Nullable List<Flowspec> flowspecList, @Nullable PathId pathId);
108
109     private @Nullable List<Flowspec> parseL3vpnNlriFlowspecList(final ByteBuf nlri) {
110         if (!nlri.isReadable()) {
111             return null;
112         }
113
114         final var fss = new ArrayList<Flowspec>();
115         while (nlri.isReadable()) {
116             fss.add(new FlowspecBuilder().setFlowspecType(flowspecTypeRegistry.parseFlowspecType(nlri)).build());
117         }
118         return fss;
119     }
120 }
121