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