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