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