Eliminate RouteDistinguisherBuilder
[bgpcep.git] / bgp / extensions / flowspec / src / test / java / org / opendaylight / protocol / bgp / flowspec / FlowspecL3vpnIpv4NlriParserTest.java
1 /*
2  * Copyright (c) 2015 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.flowspec;
9
10 import static org.junit.Assert.assertArrayEquals;
11 import static org.junit.Assert.assertEquals;
12 import static org.mockito.ArgumentMatchers.any;
13 import static org.mockito.Mockito.doReturn;
14 import static org.opendaylight.bgp.concepts.RouteDistinguisherUtil.extractRouteDistinguisher;
15
16 import io.netty.buffer.ByteBuf;
17 import io.netty.buffer.Unpooled;
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Optional;
21 import java.util.Set;
22 import org.junit.Before;
23 import org.junit.Test;
24 import org.junit.runner.RunWith;
25 import org.mockito.Mock;
26 import org.mockito.junit.MockitoJUnitRunner;
27 import org.opendaylight.bgp.concepts.RouteDistinguisherUtil;
28 import org.opendaylight.protocol.bgp.flowspec.FlowspecTypeRegistries.SAFI;
29 import org.opendaylight.protocol.bgp.flowspec.handlers.AbstractNumericOperandParser;
30 import org.opendaylight.protocol.bgp.flowspec.handlers.AbstractOperandParser;
31 import org.opendaylight.protocol.bgp.flowspec.handlers.BitmaskOperandParser;
32 import org.opendaylight.protocol.bgp.flowspec.l3vpn.AbstractFlowspecL3vpnNlriParser;
33 import org.opendaylight.protocol.bgp.flowspec.l3vpn.ipv4.FlowspecL3vpnIpv4NlriParser;
34 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
35 import org.opendaylight.protocol.bgp.parser.spi.MultiPathSupport;
36 import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
37 import org.opendaylight.protocol.util.ByteArray;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.BitmaskOperand;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.Dscp;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.FlowspecL3vpnSubsequentAddressFamily;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.Fragment;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.NumericOperand;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.Flowspec;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.FlowspecBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.FlowspecType;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.DestinationPortCaseBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.DscpCaseBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.FragmentCaseBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.IcmpCodeCaseBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.IcmpTypeCaseBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.PacketLengthCase;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.PacketLengthCaseBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.PortCase;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.PortCaseBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.SourcePortCaseBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.TcpFlagsCase;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.TcpFlagsCaseBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.destination.port._case.DestinationPorts;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.destination.port._case.DestinationPortsBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.dscp._case.Dscps;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.dscp._case.DscpsBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.fragment._case.Fragments;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.fragment._case.FragmentsBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.icmp.code._case.Codes;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.icmp.code._case.CodesBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.icmp.type._case.Types;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.icmp.type._case.TypesBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.packet.length._case.PacketLengths;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.packet.length._case.PacketLengthsBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.port._case.Ports;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.port._case.PortsBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.source.port._case.SourcePorts;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.source.port._case.SourcePortsBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.tcp.flags._case.TcpFlags;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.tcp.flags._case.TcpFlagsBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.DestinationPrefixCase;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.DestinationPrefixCaseBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.ProtocolIpCaseBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.SourcePrefixCase;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.SourcePrefixCaseBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.protocol.ip._case.ProtocolIps;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.protocol.ip._case.ProtocolIpsBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.ipv4.route.FlowspecRoute;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.l3vpn.destination.ipv4.DestinationFlowspecL3vpnIpv4;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.l3vpn.destination.ipv4.DestinationFlowspecL3vpnIpv4Builder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.PathId;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.AttributesReachBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.AttributesUnreachBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.reach.MpReachNlriBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.reach.mp.reach.nlri.AdvertizedRoutesBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.unreach.MpUnreachNlriBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.unreach.mp.unreach.nlri.WithdrawnRoutesBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Ipv4AddressFamily;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.RouteDistinguisher;
97 import org.opendaylight.yangtools.yang.common.QName;
98 import org.opendaylight.yangtools.yang.common.Uint16;
99 import org.opendaylight.yangtools.yang.common.Uint32;
100 import org.opendaylight.yangtools.yang.common.Uint8;
101 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
102 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
103 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
104 import org.opendaylight.yangtools.yang.data.api.schema.builder.DataContainerNodeBuilder;
105 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
106 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
107
108 @RunWith(MockitoJUnitRunner.StrictStubs.class)
109 public class FlowspecL3vpnIpv4NlriParserTest {
110     private static final NodeIdentifier RD_NID = new NodeIdentifier(QName.create(Flowspec.QNAME.getNamespace(),
111         Flowspec.QNAME.getRevision(), "route-distinguisher"));
112     private static final NodeIdentifier PROTOCOL_IP_NID = new NodeIdentifier(ProtocolIps.QNAME);
113
114     private static final String ROUTE_DISTINGUISHER = "1.2.3.4:10";
115
116     private static final PathId PATH_ID = new PathId(Uint32.ONE);
117
118     @Mock
119     private PeerSpecificParserConstraint constraint;
120     @Mock
121     private MultiPathSupport muliPathSupport;
122
123     private static final byte[] REACHED_NLRI = new byte[] {
124         0x29,   // NLRI length: 8+33=41
125         0, 1, 1, 2, 3, 4, 0, 10,    // route distinguisher: 1.2.3.4:10
126         0x01, 0x20, 0x0a, 0x00, 0x01, 0x00,
127         0x02, 0x20, 0x01, 0x02, 0x03, 0x04,
128         0x03, (byte) 0x81, 0x06,
129         0x04, 0x03, (byte) 0x89, 0x45, (byte) 0x8b, (byte) 0x91, 0x1f, (byte) 0x90,
130         0x05, 0x12, 0x0f, (byte) 0xf9, (byte) 0x81, (byte) 0xb3,
131         0x06, (byte) 0x91, 0x1f, (byte) 0x90
132     };
133
134     private static final byte[] REACHED_NLRI_ADD_PATH = new byte[] {
135         0x0, 0x0, 0x0, 0x1,
136         0x29,   // NLRI length: 8+33=41
137         0, 1, 1, 2, 3, 4, 0, 10,    // route distinguisher: 1.2.3.4:10
138         0x01, 0x20, 0x0a, 0x00, 0x01, 0x00,
139         0x02, 0x20, 0x01, 0x02, 0x03, 0x04,
140         0x03, (byte) 0x81, 0x06,
141         0x04, 0x03, (byte) 0x89, 0x45, (byte) 0x8b, (byte) 0x91, 0x1f, (byte) 0x90,
142         0x05, 0x12, 0x0f, (byte) 0xf9, (byte) 0x81, (byte) 0xb3,
143         0x06, (byte) 0x91, 0x1f, (byte) 0x90
144     };
145
146     private static final byte[] UNREACHED_NLRI = new byte[] {
147         0x23,   // NLRI length: 8+33=41
148         0, 1, 1, 2, 3, 4, 0, 10,    // route distinguisher: 1.2.3.4:10
149         0x07, 4, 2, (byte) 0x84, 3,
150         0x08, 4, 4, (byte) 0x80, 5,
151         0x09, 0x12, 4, 1, (byte) 0x91, 0x56, (byte) 0xb1,
152         0x0a, (byte) 0x94, (byte) 0xde, (byte) 0xad,
153         0x0b, (byte) 0x82, 0x2a,
154         0x0c, (byte) 0x81, (byte) 0x0e
155     };
156
157     private static final byte[] UNREACHED_NLRI_ADD_PATH = new byte[] {
158         0x0, 0x0, 0x0, 0x1,
159         0x23,   // NLRI length: 8+27=35
160         0, 1, 1, 2, 3, 4, 0, 10,    // route distinguisher: 1.2.3.4:10
161         0x07, 4, 2, (byte) 0x84, 3,
162         0x08, 4, 4, (byte) 0x80, 5,
163         0x09, 0x12, 4, 1, (byte) 0x91, 0x56, (byte) 0xb1,
164         0x0a, (byte) 0x94, (byte) 0xde, (byte) 0xad,
165         0x0b, (byte) 0x82, 0x2a,
166         0x0c, (byte) 0x81, (byte) 0x0e
167     };
168
169     private final FlowspecL3vpnIpv4NlriParser fsParser = new FlowspecL3vpnIpv4NlriParser(SAFI.FLOWSPEC_VPN);
170
171     @Before
172     public void setUp() {
173         doReturn(Optional.of(muliPathSupport)).when(constraint).getPeerConstraint(any());
174         doReturn(true).when(muliPathSupport).isTableTypeSupported(any());
175     }
176
177     @Test
178     public void testParseMpReachNlri() throws BGPParsingException {
179         final List<Flowspec> fs = new ArrayList<>();
180         final MpReachNlriBuilder mp = new MpReachNlriBuilder();
181
182         final FlowspecBuilder builder = new FlowspecBuilder();
183         final DestinationPrefixCase destinationPrefix = new DestinationPrefixCaseBuilder().setDestinationPrefix(
184             new Ipv4Prefix("10.0.1.0/32")).build();
185         builder.setFlowspecType(destinationPrefix);
186         fs.add(builder.build());
187         final SourcePrefixCase sourcePrefix = new SourcePrefixCaseBuilder().setSourcePrefix(
188             new Ipv4Prefix("1.2.3.4/32")).build();
189         builder.setFlowspecType(sourcePrefix);
190         fs.add(builder.build());
191
192         final FlowspecType prots = createProts();
193         builder.setFlowspecType(prots);
194         fs.add(builder.build());
195
196         final PortCase ps = createPorts();
197         builder.setFlowspecType(ps);
198         fs.add(builder.build());
199
200         final FlowspecType dps = createDps();
201         builder.setFlowspecType(dps);
202         fs.add(builder.build());
203
204         final FlowspecType sps = createSps();
205         builder.setFlowspecType(sps);
206         fs.add(builder.build());
207
208         final FlowspecL3vpnIpv4NlriParser parser = new FlowspecL3vpnIpv4NlriParser(SAFI.FLOWSPEC_VPN);
209
210         final MpReachNlriBuilder result = new MpReachNlriBuilder()
211             .setAfi(Ipv4AddressFamily.VALUE)
212             .setSafi(FlowspecL3vpnSubsequentAddressFamily.VALUE);
213         parser.parseNlri(Unpooled.wrappedBuffer(REACHED_NLRI), result, null);
214
215         final DestinationFlowspecL3vpnIpv4 flowspecDst = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns
216                 .yang.bgp.flowspec.rev200120.update.attributes.mp.reach.nlri.advertized.routes.destination.type
217                 .DestinationFlowspecL3vpnIpv4Case) result.getAdvertizedRoutes().getDestinationType())
218                 .getDestinationFlowspecL3vpnIpv4();
219         final List<Flowspec> flows = flowspecDst.getFlowspec();
220         final RouteDistinguisher rd = flowspecDst.getRouteDistinguisher();
221
222         testFlows(flows, destinationPrefix, sourcePrefix, prots, rd, ps, dps, sps);
223
224         mp.setAdvertizedRoutes(
225             new AdvertizedRoutesBuilder().setDestinationType(
226                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.update
227                 .attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecL3vpnIpv4CaseBuilder()
228                     .setDestinationFlowspecL3vpnIpv4(
229                         new DestinationFlowspecL3vpnIpv4Builder()
230                             .setRouteDistinguisher(rd)
231                             .setFlowspec(fs)
232                             .build()
233                     ).build()
234             ).build()
235         );
236
237         final ByteBuf buffer = Unpooled.buffer();
238         parser.serializeAttribute(new AttributesBuilder()
239             .addAugmentation(new AttributesReachBuilder()
240                 .setMpReachNlri(mp.setAfi(Ipv4AddressFamily.VALUE).build())
241                 .build())
242             .build(), buffer);
243         assertArrayEquals(REACHED_NLRI, ByteArray.readAllBytes(buffer));
244
245         assertEquals("""
246             all packets to 10.0.1.0/32 AND from 1.2.3.4/32 AND where IP protocol equals to 6 AND where port \
247             is greater than or equals to 137 and is less than or equals to 139 or equals to 8080 AND where \
248             destination port is greater than 4089 or equals to 179 AND where source port equals to 8080 \
249             """,
250             fsParser.stringNlri(flows));
251     }
252
253     private static void testFlows(
254         final List<Flowspec> flows,
255         final DestinationPrefixCase destinationPrefix,
256         final SourcePrefixCase sourcePrefix,
257         final FlowspecType prots,
258         final RouteDistinguisher rd,
259         final PortCase ps,
260         final FlowspecType dps,
261         final FlowspecType sps
262     ) {
263         assertEquals(6, flows.size());
264         assertEquals(ROUTE_DISTINGUISHER, rd.stringValue());
265         assertEquals(destinationPrefix, flows.get(0).getFlowspecType());
266         assertEquals(sourcePrefix, flows.get(1).getFlowspecType());
267         assertEquals(prots, flows.get(2).getFlowspecType());
268         assertEquals(ps, flows.get(3).getFlowspecType());
269         assertEquals(dps, flows.get(4).getFlowspecType());
270         assertEquals(sps, flows.get(5).getFlowspecType());
271     }
272
273     private static FlowspecType createSps() {
274         final List<SourcePorts> sports = List.of(new SourcePortsBuilder().setOp(
275             new NumericOperand(false, true, true, false, false)).setValue(Uint16.valueOf(8080)).build());
276         return new SourcePortCaseBuilder().setSourcePorts(sports).build();
277     }
278
279     private static FlowspecType createProts() {
280         final List<ProtocolIps> protocols = List.of(new ProtocolIpsBuilder().setOp(
281             new NumericOperand(false, true, true, false, false)).setValue(Uint8.valueOf(6)).build());
282         return new ProtocolIpCaseBuilder().setProtocolIps(protocols).build();
283     }
284
285     private static FlowspecType createDps() {
286         final List<DestinationPorts> destports = List.of(
287             new DestinationPortsBuilder().setOp(new NumericOperand(false, false, false, true, false))
288                 .setValue(Uint16.valueOf(4089)).build(),
289             new DestinationPortsBuilder().setOp(new NumericOperand(false, true, true, false, false))
290                 .setValue(Uint16.valueOf(179)).build());
291         return new DestinationPortCaseBuilder().setDestinationPorts(destports).build();
292     }
293
294     @Test
295     public void testParseMpReachNlriConstraint() throws BGPParsingException {
296         final List<Flowspec> fs = new ArrayList<>();
297         final MpReachNlriBuilder mp = new MpReachNlriBuilder();
298
299         final FlowspecBuilder builder = new FlowspecBuilder();
300         final DestinationPrefixCase destinationPrefix = new DestinationPrefixCaseBuilder().setDestinationPrefix(
301             new Ipv4Prefix("10.0.1.0/32")).build();
302         builder.setFlowspecType(destinationPrefix);
303         fs.add(builder.build());
304         final SourcePrefixCase sourcePrefix = new SourcePrefixCaseBuilder().setSourcePrefix(
305             new Ipv4Prefix("1.2.3.4/32")).build();
306         builder.setFlowspecType(sourcePrefix);
307         fs.add(builder.build());
308
309         final FlowspecType prots = createProts();
310         builder.setFlowspecType(prots);
311         fs.add(builder.build());
312
313         final PortCase ps = createPorts();
314         builder.setFlowspecType(ps);
315         fs.add(builder.build());
316
317         final FlowspecType dps = createDps();
318         builder.setFlowspecType(dps);
319         fs.add(builder.build());
320
321         final FlowspecType sps = createSps();
322         builder.setFlowspecType(sps);
323         fs.add(builder.build());
324
325         final FlowspecL3vpnIpv4NlriParser parser = new FlowspecL3vpnIpv4NlriParser(SAFI.FLOWSPEC_VPN);
326
327         final MpReachNlriBuilder result = new MpReachNlriBuilder()
328             .setAfi(Ipv4AddressFamily.VALUE)
329             .setSafi(FlowspecL3vpnSubsequentAddressFamily.VALUE);
330         parser.parseNlri(Unpooled.wrappedBuffer(REACHED_NLRI_ADD_PATH), result, constraint);
331
332         final DestinationFlowspecL3vpnIpv4 flowspecDst = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns
333                 .yang.bgp.flowspec.rev200120.update.attributes.mp.reach.nlri.advertized.routes.destination.type
334                 .DestinationFlowspecL3vpnIpv4Case) result.getAdvertizedRoutes().getDestinationType())
335                 .getDestinationFlowspecL3vpnIpv4();
336         final List<Flowspec> flows = flowspecDst.getFlowspec();
337         final RouteDistinguisher rd = flowspecDst.getRouteDistinguisher();
338
339         testFlows(flows, destinationPrefix, sourcePrefix, prots, rd, ps, dps, sps);
340
341         mp.setAdvertizedRoutes(
342             new AdvertizedRoutesBuilder().setDestinationType(
343                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.update
344                 .attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecL3vpnIpv4CaseBuilder()
345                     .setDestinationFlowspecL3vpnIpv4(
346                         new DestinationFlowspecL3vpnIpv4Builder()
347                             .setRouteDistinguisher(rd)
348                             .setPathId(PATH_ID)
349                             .setFlowspec(fs)
350                             .build()
351                     ).build()
352             ).build()
353         );
354
355         final ByteBuf buffer = Unpooled.buffer();
356         parser.serializeAttribute(new AttributesBuilder()
357             .addAugmentation(new AttributesReachBuilder()
358                 .setMpReachNlri(mp.setAfi(Ipv4AddressFamily.VALUE).build())
359                 .build())
360             .build(), buffer);
361         assertArrayEquals(REACHED_NLRI_ADD_PATH, ByteArray.readAllBytes(buffer));
362
363         assertEquals("""
364             all packets to 10.0.1.0/32 AND from 1.2.3.4/32 AND where IP protocol equals to 6 AND where port \
365             is greater than or equals to 137 and is less than or equals to 139 or equals to 8080 AND where \
366             destination port is greater than 4089 or equals to 179 AND where source port equals to 8080 \
367             """,
368             fsParser.stringNlri(flows));
369     }
370
371     private static PortCase createPorts() {
372         final List<Ports> ports = List.of(
373             new PortsBuilder().setOp(new NumericOperand(false, false, true, true, false)).setValue(Uint16.valueOf(137))
374                 .build(),
375             new PortsBuilder().setOp(new NumericOperand(true, false, true, false, true)).setValue(Uint16.valueOf(139))
376                 .build(),
377             new PortsBuilder().setOp(new NumericOperand(false, true, true, false, false)).setValue(Uint16.valueOf(8080))
378                 .build());
379
380         return new PortCaseBuilder().setPorts(ports).build();
381     }
382
383     @Test
384     public void testParseMpUnreachNlri() throws BGPParsingException {
385         final List<Flowspec> fs = new ArrayList<>();
386         final MpUnreachNlriBuilder mp = new MpUnreachNlriBuilder();
387
388         final FlowspecBuilder builder = new FlowspecBuilder();
389
390         final FlowspecType icmpType = createIcmpType();
391         builder.setFlowspecType(icmpType);
392         fs.add(builder.build());
393
394         final FlowspecType icmpCode = createIcmpCode();
395         builder.setFlowspecType(icmpCode);
396         fs.add(builder.build());
397
398         final TcpFlagsCase tcp = createTcp();
399         builder.setFlowspecType(tcp);
400         fs.add(builder.build());
401
402         final PacketLengthCase packet = createPackets();
403         builder.setFlowspecType(packet);
404         fs.add(builder.build());
405
406         final FlowspecType dscp = createDscp();
407         builder.setFlowspecType(dscp);
408         fs.add(builder.build());
409
410         final FlowspecType fragment = createFragment();
411         builder.setFlowspecType(fragment);
412         fs.add(builder.build());
413
414         final FlowspecL3vpnIpv4NlriParser parser = new FlowspecL3vpnIpv4NlriParser(SAFI.FLOWSPEC_VPN);
415
416         final MpUnreachNlriBuilder result = new MpUnreachNlriBuilder()
417             .setAfi(Ipv4AddressFamily.VALUE)
418             .setSafi(FlowspecL3vpnSubsequentAddressFamily.VALUE);
419         parser.parseNlri(Unpooled.wrappedBuffer(UNREACHED_NLRI), result, null);
420
421         DestinationFlowspecL3vpnIpv4 flowspecDst = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang
422                 .bgp.flowspec.rev200120.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type
423                 .DestinationFlowspecL3vpnIpv4Case) result.getWithdrawnRoutes().getDestinationType())
424                 .getDestinationFlowspecL3vpnIpv4();
425         final List<Flowspec> flows = flowspecDst.getFlowspec();
426         checkUnreachFlows(flows, icmpType, icmpCode, tcp, packet, dscp, fragment);
427
428         final RouteDistinguisher rd = flowspecDst.getRouteDistinguisher();
429
430         mp.setAfi(Ipv4AddressFamily.VALUE).setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
431             new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.update
432             .attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecL3vpnIpv4CaseBuilder()
433                 .setDestinationFlowspecL3vpnIpv4(
434                     new DestinationFlowspecL3vpnIpv4Builder()
435                         .setRouteDistinguisher(rd)
436                         .setFlowspec(fs)
437                         .build()
438                 ).build()
439             ).build()
440         );
441
442         final ByteBuf buffer = Unpooled.buffer();
443         parser.serializeNlri(rd, flows, null, buffer);
444         assertArrayEquals(UNREACHED_NLRI, ByteArray.readAllBytes(buffer));
445
446         parser.serializeAttribute(new AttributesBuilder()
447             .addAugmentation(new AttributesUnreachBuilder().setMpUnreachNlri(mp.build()).build())
448             .build(), buffer);
449         assertArrayEquals(UNREACHED_NLRI, ByteArray.readAllBytes(buffer));
450
451         assertEquals("""
452             all packets where ICMP type is less than 2 or is less than 3 AND where ICMP code is less than 4 \
453             or 5 AND where TCP flags is not 1025 or does match 22193 AND where packet length is less than 57005 \
454             AND where DSCP is greater than 42 AND where fragment does match 'IS FIRST' 'IS LAST' 'IS A' \
455             """,
456             fsParser.stringNlri(flows));
457     }
458
459     private static FlowspecType createFragment() {
460         final List<Fragments> fragments = List.of(new FragmentsBuilder().setOp(
461             new BitmaskOperand(false, true, true, false)).setValue(new Fragment(false, true, true, true)).build());
462         return new FragmentCaseBuilder().setFragments(fragments).build();
463     }
464
465     private static FlowspecType createDscp() {
466         final List<Dscps> dscps = List.of(new DscpsBuilder().setOp(
467             new NumericOperand(false, true, false, true, false)).setValue(new Dscp(Uint8.valueOf(42))).build());
468         return new DscpCaseBuilder().setDscps(dscps).build();
469     }
470
471     private static PacketLengthCase createPackets() {
472         final List<PacketLengths> packets = List.of(new PacketLengthsBuilder().setOp(
473             new NumericOperand(false, true, false, false, true)).setValue(Uint16.valueOf(57005)).build());
474         return new PacketLengthCaseBuilder().setPacketLengths(packets).build();
475     }
476
477     private static TcpFlagsCase createTcp() {
478         final List<TcpFlags> flags = List.of(
479             new TcpFlagsBuilder().setOp(new BitmaskOperand(false, false, false, true)).setValue(Uint16.valueOf(1025))
480                 .build(),
481             new TcpFlagsBuilder().setOp(new BitmaskOperand(false, true, true, false)).setValue(Uint16.valueOf(22193))
482                 .build());
483         return new TcpFlagsCaseBuilder().setTcpFlags(flags).build();
484     }
485
486     private static FlowspecType createIcmpCode() {
487         final List<Codes> codes = List.of(
488             new CodesBuilder().setOp(new NumericOperand(false, false, false, false, true)).setValue(Uint8.valueOf(4))
489                 .build(),
490             new CodesBuilder().setOp(new NumericOperand(false, true, false, false, false)).setValue(Uint8.valueOf(5))
491                 .build());
492         return new IcmpCodeCaseBuilder().setCodes(codes).build();
493     }
494
495     private static FlowspecType createIcmpType() {
496         final List<Types> types = List.of(
497             new TypesBuilder().setOp(new NumericOperand(false, false, false, false, true)).setValue(Uint8.TWO)
498                 .build(),
499             new TypesBuilder().setOp(new NumericOperand(false, true, false, false, true)).setValue(Uint8.valueOf(3))
500                 .build());
501         return new IcmpTypeCaseBuilder().setTypes(types).build();
502     }
503
504     private static void checkUnreachFlows(final List<Flowspec> flows, final FlowspecType icmpType,
505             final FlowspecType icmpCode, final TcpFlagsCase tcp,
506             final PacketLengthCase packet, final FlowspecType dscp, final FlowspecType fragment) {
507         assertEquals(6, flows.size());
508         assertEquals(icmpType, flows.get(0).getFlowspecType());
509         assertEquals(icmpCode, flows.get(1).getFlowspecType());
510         assertEquals(tcp, flows.get(2).getFlowspecType());
511         assertEquals(packet, flows.get(3).getFlowspecType());
512         assertEquals(dscp, flows.get(4).getFlowspecType());
513         assertEquals(fragment, flows.get(5).getFlowspecType());
514     }
515
516     @Test
517     public void testParseMpUnreachNlriConstraint() throws BGPParsingException {
518         final List<Flowspec> fs = new ArrayList<>();
519         final MpUnreachNlriBuilder mp = new MpUnreachNlriBuilder();
520
521         final FlowspecBuilder builder = new FlowspecBuilder();
522
523         final FlowspecType icmpType = createIcmpType();
524         builder.setFlowspecType(icmpType);
525         fs.add(builder.build());
526
527         final FlowspecType icmpCode = createIcmpCode();
528         builder.setFlowspecType(icmpCode);
529         fs.add(builder.build());
530
531         final TcpFlagsCase tcp = createTcp();
532         builder.setFlowspecType(tcp);
533         fs.add(builder.build());
534
535         final PacketLengthCase packet = createPackets();
536         builder.setFlowspecType(packet);
537         fs.add(builder.build());
538
539         final FlowspecType dscp = createDscp();
540         builder.setFlowspecType(dscp);
541         fs.add(builder.build());
542
543         final FlowspecType fragment = createFragment();
544         builder.setFlowspecType(fragment);
545         fs.add(builder.build());
546
547         final FlowspecL3vpnIpv4NlriParser parser = new FlowspecL3vpnIpv4NlriParser(SAFI.FLOWSPEC_VPN);
548
549         final MpUnreachNlriBuilder result = new MpUnreachNlriBuilder()
550             .setAfi(Ipv4AddressFamily.VALUE)
551             .setSafi(FlowspecL3vpnSubsequentAddressFamily.VALUE);
552         parser.parseNlri(Unpooled.wrappedBuffer(UNREACHED_NLRI_ADD_PATH), result, constraint);
553
554         DestinationFlowspecL3vpnIpv4 flowspecDst = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang
555                 .bgp.flowspec.rev200120.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type
556                 .DestinationFlowspecL3vpnIpv4Case) result.getWithdrawnRoutes().getDestinationType())
557                 .getDestinationFlowspecL3vpnIpv4();
558         final List<Flowspec> flows = flowspecDst.getFlowspec();
559         checkUnreachFlows(flows, icmpType, icmpCode, tcp, packet, dscp, fragment);
560
561         final RouteDistinguisher rd = flowspecDst.getRouteDistinguisher();
562
563         mp.setAfi(Ipv4AddressFamily.VALUE).setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
564             new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.update
565             .attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecL3vpnIpv4CaseBuilder()
566                 .setDestinationFlowspecL3vpnIpv4(
567                     new DestinationFlowspecL3vpnIpv4Builder()
568                         .setRouteDistinguisher(rd)
569                         .setPathId(PATH_ID)
570                         .setFlowspec(fs)
571                         .build()
572                 ).build()
573             ).build()
574         );
575
576         final ByteBuf buffer = Unpooled.buffer();
577         parser.serializeNlri(rd, flows, PATH_ID, buffer);
578         assertArrayEquals(UNREACHED_NLRI_ADD_PATH, ByteArray.readAllBytes(buffer));
579
580         parser.serializeAttribute(new AttributesBuilder()
581             .addAugmentation(new AttributesUnreachBuilder().setMpUnreachNlri(mp.build()).build())
582             .build(), buffer);
583         assertArrayEquals(UNREACHED_NLRI_ADD_PATH, ByteArray.readAllBytes(buffer));
584
585         assertEquals("""
586             all packets where ICMP type is less than 2 or is less than 3 AND where ICMP code is less than 4 \
587             or 5 AND where TCP flags is not 1025 or does match 22193 AND where packet length is less than 57005 \
588             AND where DSCP is greater than 42 AND where fragment does match 'IS FIRST' 'IS LAST' 'IS A' \
589             """,
590             fsParser.stringNlri(flows));
591     }
592
593     @Test
594     public void testExtractFlowspecDestPrefix() {
595         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry =
596                 Builders.mapEntryBuilder();
597         entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry));
598         entry.withChild(Builders.unkeyedListBuilder()
599             .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
600             .withChild(Builders.unkeyedListEntryBuilder()
601                 .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
602                 .withChild(Builders.choiceBuilder()
603                     .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID)
604                     .withChild(Builders.leafBuilder().withNodeIdentifier(AbstractFlowspecNlriParser.DEST_PREFIX_NID)
605                         .withValue("127.0.0.5/32").build()).build()).build()).build());
606
607         final FlowspecBuilder expectedFS = new FlowspecBuilder();
608         expectedFS.setFlowspecType(new DestinationPrefixCaseBuilder().setDestinationPrefix(
609             new Ipv4Prefix("127.0.0.5/32")).build());
610         assertEquals(List.of(expectedFS.build()), fsParser.extractFlowspec(entry.build()));
611     }
612
613     @Test
614     public void testExtractFlowspecSourcePrefix() {
615         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry =
616                 Builders.mapEntryBuilder();
617         entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry));
618         entry.withChild(Builders.unkeyedListBuilder()
619             .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
620             .withChild(Builders.unkeyedListEntryBuilder()
621                 .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
622                 .withChild(Builders.choiceBuilder()
623                     .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID)
624                     .withChild(Builders.leafBuilder().withNodeIdentifier(AbstractFlowspecNlriParser.SOURCE_PREFIX_NID)
625                         .withValue("127.0.0.6/32").build()).build()).build()).build());
626
627         final FlowspecBuilder expectedFS = new FlowspecBuilder();
628         expectedFS.setFlowspecType(new SourcePrefixCaseBuilder().setSourcePrefix(new Ipv4Prefix("127.0.0.6/32"))
629             .build());
630         final List<Flowspec> expected = new ArrayList<>();
631         expected.add(expectedFS.build());
632         assertEquals(expected, fsParser.extractFlowspec(entry.build()));
633     }
634
635     @Test
636     public void testExtractFlowspecProtocolIps() {
637         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry =
638                 Builders.mapEntryBuilder();
639         entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry));
640         entry.withChild(Builders.unkeyedListBuilder()
641             .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
642             .withChild(Builders.unkeyedListEntryBuilder()
643                 .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
644                 .withChild(Builders.choiceBuilder()
645                     .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID)
646                     .withChild(Builders.unkeyedListBuilder().withNodeIdentifier(PROTOCOL_IP_NID)
647                         .withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(PROTOCOL_IP_NID)
648                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
649                                 .withValue(Set.of(AbstractOperandParser.END_OF_LIST_VALUE,
650                                     AbstractOperandParser.AND_BIT_VALUE)).build())
651                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID)
652                                 .withValue(Uint8.valueOf(100)).build()).build())
653                         .withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(PROTOCOL_IP_NID)
654                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
655                                 .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE)).build())
656                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID)
657                                 .withValue(Uint8.valueOf(200)).build()).build())
658                         .withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(PROTOCOL_IP_NID)
659                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
660                                 .withValue(Set.of(AbstractOperandParser.END_OF_LIST_VALUE,
661                                     AbstractOperandParser.AND_BIT_VALUE, AbstractNumericOperandParser.EQUALS_VALUE))
662                                 .build())
663                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID)
664                                 .withValue(Uint8.valueOf(240)).build()).build())
665                         .build()).build()).build()).build());
666
667         final FlowspecBuilder expectedFS = new FlowspecBuilder()
668                 .setFlowspecType(new ProtocolIpCaseBuilder()
669                     .setProtocolIps(List.of(new ProtocolIpsBuilder()
670                         .setValue(Uint8.valueOf(100))
671                         .setOp(new NumericOperand(true, true, false, false, false))
672                         .build(), new ProtocolIpsBuilder()
673                         .setValue(Uint8.valueOf(200))
674                         .setOp(new NumericOperand(true, false, false, false, false))
675                         .build(), new ProtocolIpsBuilder()
676                         .setValue(Uint8.valueOf(240))
677                         .setOp(new NumericOperand(true, true, true, false, false))
678                         .build()))
679                     .build());
680         assertEquals(List.of(expectedFS.build()), fsParser.extractFlowspec(entry.build()));
681     }
682
683     @Test
684     public void testExtractFlowspecPorts() {
685         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry =
686                 Builders.mapEntryBuilder();
687         entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry));
688         entry.withChild(Builders.unkeyedListBuilder()
689             .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
690             .withChild(Builders.unkeyedListEntryBuilder()
691                 .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
692                 .withChild(Builders.choiceBuilder()
693                     .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID)
694                     .withChild(Builders.unkeyedListBuilder().withNodeIdentifier(AbstractFlowspecNlriParser.PORTS_NID)
695                         .withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(PROTOCOL_IP_NID)
696                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
697                                 .withValue(Set.of(AbstractOperandParser.END_OF_LIST_VALUE,
698                                     AbstractOperandParser.AND_BIT_VALUE, AbstractNumericOperandParser.LESS_THAN_VALUE))
699                                 .build())
700                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID)
701                                 .withValue(Uint16.valueOf(100)).build()).build())
702                         .build()).build()).build()).build());
703
704         final FlowspecBuilder expectedFS = new FlowspecBuilder()
705                 .setFlowspecType(new PortCaseBuilder()
706                     .setPorts(List.of(new PortsBuilder()
707                         .setValue(Uint16.valueOf(100))
708                         .setOp(new NumericOperand(true, true, false, false, true))
709                         .build()))
710                     .build());
711         final List<Flowspec> expected = new ArrayList<>();
712         expected.add(expectedFS.build());
713         assertEquals(expected, fsParser.extractFlowspec(entry.build()));
714     }
715
716     @Test
717     public void testExtractFlowspecDestinationPorts() {
718         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry =
719                 Builders.mapEntryBuilder();
720         entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry));
721         entry.withChild(Builders.unkeyedListBuilder()
722             .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
723             .withChild(Builders.unkeyedListEntryBuilder()
724                 .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
725                 .withChild(Builders.choiceBuilder()
726                     .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID)
727                     .withChild(Builders.unkeyedListBuilder()
728                         .withNodeIdentifier(AbstractFlowspecNlriParser.DEST_PORT_NID)
729                         .withChild(Builders.unkeyedListEntryBuilder()
730                             .withNodeIdentifier(AbstractFlowspecNlriParser.OP_NID)
731                             .withChild(Builders.leafBuilder().withNodeIdentifier(AbstractFlowspecNlriParser.OP_NID)
732                                 .withValue(Set.of(AbstractOperandParser.END_OF_LIST_VALUE,
733                                     AbstractNumericOperandParser.EQUALS_VALUE)).build())
734                             .withChild(Builders.leafBuilder().withNodeIdentifier(AbstractFlowspecNlriParser.VALUE_NID)
735                                 .withValue(Uint16.valueOf(1024)).build()).build())
736                         .build()).build()).build()).build());
737         final FlowspecBuilder expectedFS = new FlowspecBuilder();
738         expectedFS.setFlowspecType(new DestinationPortCaseBuilder()
739             .setDestinationPorts(List.of(new DestinationPortsBuilder()
740                 .setValue(Uint16.valueOf(1024))
741                 .setOp(new NumericOperand(false, true, true, false, false))
742                 .build()))
743             .build());
744         final List<Flowspec> expected = new ArrayList<>();
745         expected.add(expectedFS.build());
746         assertEquals(expected, fsParser.extractFlowspec(entry.build()));
747     }
748
749     @Test
750     public void testExtractFlowspecSourcePorts() {
751         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry =
752                 Builders.mapEntryBuilder();
753         entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry));
754         entry.withChild(Builders.unkeyedListBuilder()
755             .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
756             .withChild(Builders.unkeyedListEntryBuilder()
757                 .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
758                 .withChild(Builders.choiceBuilder()
759                     .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID)
760                     .withChild(Builders.unkeyedListBuilder()
761                         .withNodeIdentifier(AbstractFlowspecNlriParser.SOURCE_PORT_NID)
762                         .withChild(Builders.unkeyedListEntryBuilder()
763                             .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
764                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
765                                 .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE,
766                                     AbstractOperandParser.END_OF_LIST_VALUE, AbstractNumericOperandParser.EQUALS_VALUE,
767                                     AbstractNumericOperandParser.GREATER_THAN_VALUE,
768                                     AbstractNumericOperandParser.LESS_THAN_VALUE)).build())
769                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID)
770                                 .withValue(Uint16.valueOf(8080)).build()).build())
771                         .build()).build()).build()).build());
772         final FlowspecBuilder expectedFS = new FlowspecBuilder();
773         expectedFS.setFlowspecType(new SourcePortCaseBuilder()
774             .setSourcePorts(List.of(new SourcePortsBuilder()
775                 .setValue(Uint16.valueOf(8080))
776                 .setOp(new NumericOperand(true, true, true, true, true))
777                 .build()))
778             .build());
779         final List<Flowspec> expected = new ArrayList<>();
780         expected.add(expectedFS.build());
781         assertEquals(expected, fsParser.extractFlowspec(entry.build()));
782     }
783
784     @Test
785     public void testExtractFlowspecSourceTypes() {
786         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry =
787                 Builders.mapEntryBuilder();
788         entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry));
789         entry.withChild(Builders.unkeyedListBuilder()
790             .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
791             .withChild(Builders.unkeyedListEntryBuilder()
792                 .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
793                 .withChild(Builders.choiceBuilder()
794                     .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID)
795                     .withChild(Builders.unkeyedListBuilder()
796                         .withNodeIdentifier(AbstractFlowspecNlriParser.ICMP_TYPE_NID)
797                         .withChild(Builders.unkeyedListEntryBuilder()
798                             .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
799                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
800                                 .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE,
801                                     AbstractOperandParser.END_OF_LIST_VALUE, AbstractNumericOperandParser.EQUALS_VALUE,
802                                     AbstractNumericOperandParser.GREATER_THAN_VALUE,
803                                     AbstractNumericOperandParser.LESS_THAN_VALUE)).build())
804                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID)
805                                 .withValue(Uint8.valueOf(22)).build()).build())
806                         .build()).build()).build()).build());
807         final FlowspecBuilder expectedFS = new FlowspecBuilder();
808         expectedFS.setFlowspecType(new IcmpTypeCaseBuilder()
809             .setTypes(List.of(new TypesBuilder()
810                 .setValue(Uint8.valueOf(22))
811                 .setOp(new NumericOperand(true, true, true, true, true))
812                 .build()))
813             .build());
814         final List<Flowspec> expected = new ArrayList<>();
815         expected.add(expectedFS.build());
816         assertEquals(expected, fsParser.extractFlowspec(entry.build()));
817     }
818
819     @Test
820     public void testExtractFlowspecSourceCodes() {
821         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry =
822                 Builders.mapEntryBuilder();
823         entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry));
824         entry.withChild(Builders.unkeyedListBuilder()
825             .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
826             .withChild(Builders.unkeyedListEntryBuilder()
827                 .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
828                 .withChild(Builders.choiceBuilder()
829                     .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID)
830                     .withChild(Builders.unkeyedListBuilder()
831                         .withNodeIdentifier(AbstractFlowspecNlriParser.ICMP_CODE_NID)
832                         .withChild(Builders.unkeyedListEntryBuilder()
833                             .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
834                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
835                                 .withValue(Set.of()).build())
836                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID)
837                                 .withValue(Uint8.valueOf(23)).build()).build())
838                         .build()).build()).build()).build());
839         final FlowspecBuilder expectedFS = new FlowspecBuilder();
840         expectedFS.setFlowspecType(new IcmpCodeCaseBuilder()
841             .setCodes(List.of(new CodesBuilder()
842                 .setValue(Uint8.valueOf(23))
843                 .setOp(new NumericOperand(false, false, false, false, false))
844                 .build()))
845             .build());
846         assertEquals(List.of(expectedFS.build()), fsParser.extractFlowspec(entry.build()));
847     }
848
849     @Test
850     public void testExtractFlowspecSourceTcpFlags() {
851         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry =
852                 Builders.mapEntryBuilder();
853         entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry));
854         entry.withChild(Builders.unkeyedListBuilder()
855             .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
856             .withChild(Builders.unkeyedListEntryBuilder()
857                 .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
858                 .withChild(Builders.choiceBuilder()
859                     .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID)
860                     .withChild(Builders.unkeyedListBuilder()
861                         .withNodeIdentifier(AbstractFlowspecNlriParser.TCP_FLAGS_NID)
862                         .withChild(Builders.unkeyedListEntryBuilder()
863                             .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
864                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
865                                 .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE,
866                                     AbstractOperandParser.END_OF_LIST_VALUE)).build())
867                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID)
868                                 .withValue(Uint16.valueOf(99)).build()).build())
869                         .build()).build()).build()).build());
870         final FlowspecBuilder expectedFS = new FlowspecBuilder();
871         expectedFS.setFlowspecType(new TcpFlagsCaseBuilder().setTcpFlags(List.of(new TcpFlagsBuilder()
872             .setValue(Uint16.valueOf(99)).setOp(new BitmaskOperand(true, true, false, false)).build())).build());
873         final List<Flowspec> expected = new ArrayList<>();
874         expected.add(expectedFS.build());
875         assertEquals(expected, fsParser.extractFlowspec(entry.build()));
876     }
877
878     @Test
879     public void testExtractFlowspecPacketLengths() {
880         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry =
881                 Builders.mapEntryBuilder();
882         entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry));
883         entry.withChild(Builders.unkeyedListBuilder()
884             .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
885             .withChild(Builders.unkeyedListEntryBuilder()
886                 .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
887                 .withChild(Builders.choiceBuilder()
888                     .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID)
889                     .withChild(Builders.unkeyedListBuilder()
890                         .withNodeIdentifier(AbstractFlowspecNlriParser.PACKET_LENGTHS_NID)
891                         .withChild(Builders.unkeyedListEntryBuilder()
892                             .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
893                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
894                                 .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE,
895                                     AbstractNumericOperandParser.GREATER_THAN_VALUE)).build())
896                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID)
897                                 .withValue(Uint16.valueOf(101)).build()).build())
898                         .build()).build()).build()).build());
899         final FlowspecBuilder expectedFS = new FlowspecBuilder();
900         expectedFS.setFlowspecType(new PacketLengthCaseBuilder().setPacketLengths(List.of(
901             new PacketLengthsBuilder().setValue(Uint16.valueOf(101)).setOp(
902                 new NumericOperand(true, false, false, true, false)).build())).build());
903         assertEquals(List.of(expectedFS.build()), fsParser.extractFlowspec(entry.build()));
904     }
905
906     @Test
907     public void testExtractFlowspecDscps() {
908         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry =
909                 Builders.mapEntryBuilder();
910         entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry));
911         entry.withChild(Builders.unkeyedListBuilder()
912             .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
913             .withChild(Builders.unkeyedListEntryBuilder()
914                 .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
915                 .withChild(Builders.choiceBuilder()
916                     .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID)
917                     .withChild(Builders.unkeyedListBuilder().withNodeIdentifier(AbstractFlowspecNlriParser.DSCP_NID)
918                         .withChild(Builders.unkeyedListEntryBuilder()
919                             .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
920                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
921                                 .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE,
922                                     AbstractOperandParser.END_OF_LIST_VALUE,
923                                     AbstractNumericOperandParser.GREATER_THAN_VALUE)).build())
924                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID)
925                                 .withValue(Uint8.valueOf(15)).build()).build())
926                         .build()).build()).build()).build());
927         final FlowspecBuilder expectedFS = new FlowspecBuilder();
928         expectedFS.setFlowspecType(new DscpCaseBuilder().setDscps(List.of(new DscpsBuilder().setValue(
929             new Dscp(Uint8.valueOf(15))).setOp(new NumericOperand(true, true, false, true, false)).build())).build());
930         assertEquals(List.of(expectedFS.build()), fsParser.extractFlowspec(entry.build()));
931     }
932
933     @Test
934     public void testExtractFlowspecFragments() {
935         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry =
936                 Builders.mapEntryBuilder();
937         entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry));
938         entry.withChild(Builders.unkeyedListBuilder()
939             .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
940             .withChild(Builders.unkeyedListEntryBuilder()
941                 .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID)
942                 .withChild(Builders.choiceBuilder()
943                     .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID)
944                     .withChild(Builders.unkeyedListBuilder()
945                         .withNodeIdentifier(AbstractFlowspecNlriParser.FRAGMENT_NID)
946                         .withChild(Builders.unkeyedListEntryBuilder()
947                             .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
948                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID)
949                                 .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE,
950                                     AbstractOperandParser.END_OF_LIST_VALUE, BitmaskOperandParser.MATCH_VALUE,
951                                     BitmaskOperandParser.NOT_VALUE)).build())
952                             .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID)
953                                 .withValue(Set.of(AbstractFlowspecNlriParser.DO_NOT_VALUE,
954                                     AbstractFlowspecNlriParser.FIRST_VALUE, AbstractFlowspecNlriParser.IS_A_VALUE,
955                                     AbstractFlowspecNlriParser.LAST_VALUE)).build()).build())
956                         .build()).build()).build()).build());
957         final FlowspecBuilder expectedFS = new FlowspecBuilder();
958         expectedFS.setFlowspecType(new FragmentCaseBuilder().setFragments(List.of(new FragmentsBuilder()
959             .setValue(new Fragment(true, true, true, true)).setOp(new BitmaskOperand(true, true, true, true)).build()))
960             .build());
961         assertEquals(List.of(expectedFS.build()), fsParser.extractFlowspec(entry.build()));
962     }
963
964     @Test
965     public void testExtractFlowspecRouteDistinguisher() {
966         assertEquals(RouteDistinguisherUtil.parseRouteDistinguisher(ROUTE_DISTINGUISHER),
967             extractRouteDistinguisher(Builders.mapEntryBuilder()
968                 .withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, "foo"))
969                 .withChild(ImmutableNodes.leafNode(RD_NID, ROUTE_DISTINGUISHER))
970                 .build(), AbstractFlowspecL3vpnNlriParser.RD_NID));
971     }
972 }
973