/* * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.protocol.bgp.flowspec; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.opendaylight.bgp.concepts.RouteDistinguisherUtil.extractRouteDistinguisher; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Set; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.opendaylight.protocol.bgp.flowspec.FlowspecTypeRegistries.SAFI; import org.opendaylight.protocol.bgp.flowspec.handlers.AbstractNumericOperandParser; import org.opendaylight.protocol.bgp.flowspec.handlers.AbstractOperandParser; import org.opendaylight.protocol.bgp.flowspec.handlers.BitmaskOperandParser; import org.opendaylight.protocol.bgp.flowspec.l3vpn.AbstractFlowspecL3vpnNlriParser; import org.opendaylight.protocol.bgp.flowspec.l3vpn.ipv4.FlowspecL3vpnIpv4NlriParser; import org.opendaylight.protocol.bgp.parser.BGPParsingException; import org.opendaylight.protocol.bgp.parser.spi.MultiPathSupport; import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint; import org.opendaylight.protocol.util.ByteArray; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.BitmaskOperand; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.Dscp; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.FlowspecL3vpnSubsequentAddressFamily; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.Fragment; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.NumericOperand; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.Flowspec; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.FlowspecBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.FlowspecType; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.DestinationPortCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.DscpCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.FragmentCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.IcmpCodeCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.IcmpTypeCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.PacketLengthCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.PacketLengthCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.PortCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.PortCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.SourcePortCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.TcpFlagsCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.TcpFlagsCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.destination.port._case.DestinationPorts; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.destination.port._case.DestinationPortsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.dscp._case.Dscps; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.dscp._case.DscpsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.fragment._case.Fragments; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.fragment._case.FragmentsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.icmp.code._case.Codes; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.icmp.code._case.CodesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.icmp.type._case.Types; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.icmp.type._case.TypesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.packet.length._case.PacketLengths; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.packet.length._case.PacketLengthsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.port._case.Ports; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.port._case.PortsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.source.port._case.SourcePorts; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.source.port._case.SourcePortsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.tcp.flags._case.TcpFlags; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.flowspec.flowspec.type.tcp.flags._case.TcpFlagsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.DestinationPrefixCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.DestinationPrefixCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.ProtocolIpCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.SourcePrefixCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.SourcePrefixCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.protocol.ip._case.ProtocolIps; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.destination.group.ipv4.flowspec.flowspec.type.protocol.ip._case.ProtocolIpsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.ipv4.route.FlowspecRoute; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.l3vpn.destination.ipv4.DestinationFlowspecL3vpnIpv4; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.flowspec.l3vpn.destination.ipv4.DestinationFlowspecL3vpnIpv4Builder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.PathId; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.AttributesReachBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.AttributesUnreachBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.reach.MpReachNlriBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.reach.mp.reach.nlri.AdvertizedRoutesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.unreach.MpUnreachNlriBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.unreach.mp.unreach.nlri.WithdrawnRoutesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Ipv4AddressFamily; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.RouteDistinguisher; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.RouteDistinguisherBuilder; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.Uint16; import org.opendaylight.yangtools.yang.common.Uint32; import org.opendaylight.yangtools.yang.common.Uint8; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.builder.DataContainerNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; @RunWith(MockitoJUnitRunner.StrictStubs.class) public class FlowspecL3vpnIpv4NlriParserTest { private static final NodeIdentifier RD_NID = new NodeIdentifier(QName.create(Flowspec.QNAME.getNamespace(), Flowspec.QNAME.getRevision(), "route-distinguisher")); private static final NodeIdentifier PROTOCOL_IP_NID = new NodeIdentifier(ProtocolIps.QNAME); private static final String ROUTE_DISTINGUISHER = "1.2.3.4:10"; private static final PathId PATH_ID = new PathId(Uint32.ONE); @Mock private PeerSpecificParserConstraint constraint; @Mock private MultiPathSupport muliPathSupport; private static final byte[] REACHED_NLRI = new byte[] { 0x29, // NLRI length: 8+33=41 0, 1, 1, 2, 3, 4, 0, 10, // route distinguisher: 1.2.3.4:10 0x01, 0x20, 0x0a, 0x00, 0x01, 0x00, 0x02, 0x20, 0x01, 0x02, 0x03, 0x04, 0x03, (byte) 0x81, 0x06, 0x04, 0x03, (byte) 0x89, 0x45, (byte) 0x8b, (byte) 0x91, 0x1f, (byte) 0x90, 0x05, 0x12, 0x0f, (byte) 0xf9, (byte) 0x81, (byte) 0xb3, 0x06, (byte) 0x91, 0x1f, (byte) 0x90 }; private static final byte[] REACHED_NLRI_ADD_PATH = new byte[] { 0x0, 0x0, 0x0, 0x1, 0x29, // NLRI length: 8+33=41 0, 1, 1, 2, 3, 4, 0, 10, // route distinguisher: 1.2.3.4:10 0x01, 0x20, 0x0a, 0x00, 0x01, 0x00, 0x02, 0x20, 0x01, 0x02, 0x03, 0x04, 0x03, (byte) 0x81, 0x06, 0x04, 0x03, (byte) 0x89, 0x45, (byte) 0x8b, (byte) 0x91, 0x1f, (byte) 0x90, 0x05, 0x12, 0x0f, (byte) 0xf9, (byte) 0x81, (byte) 0xb3, 0x06, (byte) 0x91, 0x1f, (byte) 0x90 }; private static final byte[] UNREACHED_NLRI = new byte[] { 0x23, // NLRI length: 8+33=41 0, 1, 1, 2, 3, 4, 0, 10, // route distinguisher: 1.2.3.4:10 0x07, 4, 2, (byte) 0x84, 3, 0x08, 4, 4, (byte) 0x80, 5, 0x09, 0x12, 4, 1, (byte) 0x91, 0x56, (byte) 0xb1, 0x0a, (byte) 0x94, (byte) 0xde, (byte) 0xad, 0x0b, (byte) 0x82, 0x2a, 0x0c, (byte) 0x81, (byte) 0x0e }; private static final byte[] UNREACHED_NLRI_ADD_PATH = new byte[] { 0x0, 0x0, 0x0, 0x1, 0x23, // NLRI length: 8+27=35 0, 1, 1, 2, 3, 4, 0, 10, // route distinguisher: 1.2.3.4:10 0x07, 4, 2, (byte) 0x84, 3, 0x08, 4, 4, (byte) 0x80, 5, 0x09, 0x12, 4, 1, (byte) 0x91, 0x56, (byte) 0xb1, 0x0a, (byte) 0x94, (byte) 0xde, (byte) 0xad, 0x0b, (byte) 0x82, 0x2a, 0x0c, (byte) 0x81, (byte) 0x0e }; private final FlowspecL3vpnIpv4NlriParser fsParser = new FlowspecL3vpnIpv4NlriParser(SAFI.FLOWSPEC_VPN); @Before public void setUp() { doReturn(Optional.of(muliPathSupport)).when(constraint).getPeerConstraint(any()); doReturn(true).when(muliPathSupport).isTableTypeSupported(any()); } @Test public void testParseMpReachNlri() throws BGPParsingException { final List fs = new ArrayList<>(); final MpReachNlriBuilder mp = new MpReachNlriBuilder(); final FlowspecBuilder builder = new FlowspecBuilder(); final DestinationPrefixCase destinationPrefix = new DestinationPrefixCaseBuilder().setDestinationPrefix( new Ipv4Prefix("10.0.1.0/32")).build(); builder.setFlowspecType(destinationPrefix); fs.add(builder.build()); final SourcePrefixCase sourcePrefix = new SourcePrefixCaseBuilder().setSourcePrefix( new Ipv4Prefix("1.2.3.4/32")).build(); builder.setFlowspecType(sourcePrefix); fs.add(builder.build()); final FlowspecType prots = createProts(); builder.setFlowspecType(prots); fs.add(builder.build()); final PortCase ps = createPorts(); builder.setFlowspecType(ps); fs.add(builder.build()); final FlowspecType dps = createDps(); builder.setFlowspecType(dps); fs.add(builder.build()); final FlowspecType sps = createSps(); builder.setFlowspecType(sps); fs.add(builder.build()); final FlowspecL3vpnIpv4NlriParser parser = new FlowspecL3vpnIpv4NlriParser(SAFI.FLOWSPEC_VPN); final MpReachNlriBuilder result = new MpReachNlriBuilder() .setAfi(Ipv4AddressFamily.VALUE) .setSafi(FlowspecL3vpnSubsequentAddressFamily.VALUE); parser.parseNlri(Unpooled.wrappedBuffer(REACHED_NLRI), result, null); final DestinationFlowspecL3vpnIpv4 flowspecDst = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns .yang.bgp.flowspec.rev200120.update.attributes.mp.reach.nlri.advertized.routes.destination.type .DestinationFlowspecL3vpnIpv4Case) result.getAdvertizedRoutes().getDestinationType()) .getDestinationFlowspecL3vpnIpv4(); final List flows = flowspecDst.getFlowspec(); final RouteDistinguisher rd = flowspecDst.getRouteDistinguisher(); testFlows(flows, destinationPrefix, sourcePrefix, prots, rd, ps, dps, sps); mp.setAdvertizedRoutes( new AdvertizedRoutesBuilder().setDestinationType( new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.update .attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecL3vpnIpv4CaseBuilder() .setDestinationFlowspecL3vpnIpv4( new DestinationFlowspecL3vpnIpv4Builder() .setRouteDistinguisher(rd) .setFlowspec(fs) .build() ).build() ).build() ); final ByteBuf buffer = Unpooled.buffer(); parser.serializeAttribute(new AttributesBuilder() .addAugmentation(new AttributesReachBuilder() .setMpReachNlri(mp.setAfi(Ipv4AddressFamily.VALUE).build()) .build()) .build(), buffer); assertArrayEquals(REACHED_NLRI, ByteArray.readAllBytes(buffer)); 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 \ is greater than or equals to 137 and is less than or equals to 139 or equals to 8080 AND where \ destination port is greater than 4089 or equals to 179 AND where source port equals to 8080 \ """, fsParser.stringNlri(flows)); } private static void testFlows( final List flows, final DestinationPrefixCase destinationPrefix, final SourcePrefixCase sourcePrefix, final FlowspecType prots, final RouteDistinguisher rd, final PortCase ps, final FlowspecType dps, final FlowspecType sps ) { assertEquals(6, flows.size()); assertEquals(ROUTE_DISTINGUISHER, rd.stringValue()); assertEquals(destinationPrefix, flows.get(0).getFlowspecType()); assertEquals(sourcePrefix, flows.get(1).getFlowspecType()); assertEquals(prots, flows.get(2).getFlowspecType()); assertEquals(ps, flows.get(3).getFlowspecType()); assertEquals(dps, flows.get(4).getFlowspecType()); assertEquals(sps, flows.get(5).getFlowspecType()); } private static FlowspecType createSps() { final List sports = List.of(new SourcePortsBuilder().setOp( new NumericOperand(false, true, true, false, false)).setValue(Uint16.valueOf(8080)).build()); return new SourcePortCaseBuilder().setSourcePorts(sports).build(); } private static FlowspecType createProts() { final List protocols = List.of(new ProtocolIpsBuilder().setOp( new NumericOperand(false, true, true, false, false)).setValue(Uint8.valueOf(6)).build()); return new ProtocolIpCaseBuilder().setProtocolIps(protocols).build(); } private static FlowspecType createDps() { final List destports = List.of( new DestinationPortsBuilder().setOp(new NumericOperand(false, false, false, true, false)) .setValue(Uint16.valueOf(4089)).build(), new DestinationPortsBuilder().setOp(new NumericOperand(false, true, true, false, false)) .setValue(Uint16.valueOf(179)).build()); return new DestinationPortCaseBuilder().setDestinationPorts(destports).build(); } @Test public void testParseMpReachNlriConstraint() throws BGPParsingException { final List fs = new ArrayList<>(); final MpReachNlriBuilder mp = new MpReachNlriBuilder(); final FlowspecBuilder builder = new FlowspecBuilder(); final DestinationPrefixCase destinationPrefix = new DestinationPrefixCaseBuilder().setDestinationPrefix( new Ipv4Prefix("10.0.1.0/32")).build(); builder.setFlowspecType(destinationPrefix); fs.add(builder.build()); final SourcePrefixCase sourcePrefix = new SourcePrefixCaseBuilder().setSourcePrefix( new Ipv4Prefix("1.2.3.4/32")).build(); builder.setFlowspecType(sourcePrefix); fs.add(builder.build()); final FlowspecType prots = createProts(); builder.setFlowspecType(prots); fs.add(builder.build()); final PortCase ps = createPorts(); builder.setFlowspecType(ps); fs.add(builder.build()); final FlowspecType dps = createDps(); builder.setFlowspecType(dps); fs.add(builder.build()); final FlowspecType sps = createSps(); builder.setFlowspecType(sps); fs.add(builder.build()); final FlowspecL3vpnIpv4NlriParser parser = new FlowspecL3vpnIpv4NlriParser(SAFI.FLOWSPEC_VPN); final MpReachNlriBuilder result = new MpReachNlriBuilder() .setAfi(Ipv4AddressFamily.VALUE) .setSafi(FlowspecL3vpnSubsequentAddressFamily.VALUE); parser.parseNlri(Unpooled.wrappedBuffer(REACHED_NLRI_ADD_PATH), result, constraint); final DestinationFlowspecL3vpnIpv4 flowspecDst = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns .yang.bgp.flowspec.rev200120.update.attributes.mp.reach.nlri.advertized.routes.destination.type .DestinationFlowspecL3vpnIpv4Case) result.getAdvertizedRoutes().getDestinationType()) .getDestinationFlowspecL3vpnIpv4(); final List flows = flowspecDst.getFlowspec(); final RouteDistinguisher rd = flowspecDst.getRouteDistinguisher(); testFlows(flows, destinationPrefix, sourcePrefix, prots, rd, ps, dps, sps); mp.setAdvertizedRoutes( new AdvertizedRoutesBuilder().setDestinationType( new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.update .attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecL3vpnIpv4CaseBuilder() .setDestinationFlowspecL3vpnIpv4( new DestinationFlowspecL3vpnIpv4Builder() .setRouteDistinguisher(rd) .setPathId(PATH_ID) .setFlowspec(fs) .build() ).build() ).build() ); final ByteBuf buffer = Unpooled.buffer(); parser.serializeAttribute(new AttributesBuilder() .addAugmentation(new AttributesReachBuilder() .setMpReachNlri(mp.setAfi(Ipv4AddressFamily.VALUE).build()) .build()) .build(), buffer); assertArrayEquals(REACHED_NLRI_ADD_PATH, ByteArray.readAllBytes(buffer)); 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 \ is greater than or equals to 137 and is less than or equals to 139 or equals to 8080 AND where \ destination port is greater than 4089 or equals to 179 AND where source port equals to 8080 \ """, fsParser.stringNlri(flows)); } private static PortCase createPorts() { final List ports = List.of( new PortsBuilder().setOp(new NumericOperand(false, false, true, true, false)).setValue(Uint16.valueOf(137)) .build(), new PortsBuilder().setOp(new NumericOperand(true, false, true, false, true)).setValue(Uint16.valueOf(139)) .build(), new PortsBuilder().setOp(new NumericOperand(false, true, true, false, false)).setValue(Uint16.valueOf(8080)) .build()); return new PortCaseBuilder().setPorts(ports).build(); } @Test public void testParseMpUnreachNlri() throws BGPParsingException { final List fs = new ArrayList<>(); final MpUnreachNlriBuilder mp = new MpUnreachNlriBuilder(); final FlowspecBuilder builder = new FlowspecBuilder(); final FlowspecType icmpType = createIcmpType(); builder.setFlowspecType(icmpType); fs.add(builder.build()); final FlowspecType icmpCode = createIcmpCode(); builder.setFlowspecType(icmpCode); fs.add(builder.build()); final TcpFlagsCase tcp = createTcp(); builder.setFlowspecType(tcp); fs.add(builder.build()); final PacketLengthCase packet = createPackets(); builder.setFlowspecType(packet); fs.add(builder.build()); final FlowspecType dscp = createDscp(); builder.setFlowspecType(dscp); fs.add(builder.build()); final FlowspecType fragment = createFragment(); builder.setFlowspecType(fragment); fs.add(builder.build()); final FlowspecL3vpnIpv4NlriParser parser = new FlowspecL3vpnIpv4NlriParser(SAFI.FLOWSPEC_VPN); final MpUnreachNlriBuilder result = new MpUnreachNlriBuilder() .setAfi(Ipv4AddressFamily.VALUE) .setSafi(FlowspecL3vpnSubsequentAddressFamily.VALUE); parser.parseNlri(Unpooled.wrappedBuffer(UNREACHED_NLRI), result, null); DestinationFlowspecL3vpnIpv4 flowspecDst = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang .bgp.flowspec.rev200120.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type .DestinationFlowspecL3vpnIpv4Case) result.getWithdrawnRoutes().getDestinationType()) .getDestinationFlowspecL3vpnIpv4(); final List flows = flowspecDst.getFlowspec(); checkUnreachFlows(flows, icmpType, icmpCode, tcp, packet, dscp, fragment); final RouteDistinguisher rd = flowspecDst.getRouteDistinguisher(); mp.setAfi(Ipv4AddressFamily.VALUE).setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType( new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.update .attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecL3vpnIpv4CaseBuilder() .setDestinationFlowspecL3vpnIpv4( new DestinationFlowspecL3vpnIpv4Builder() .setRouteDistinguisher(rd) .setFlowspec(fs) .build() ).build() ).build() ); final ByteBuf buffer = Unpooled.buffer(); parser.serializeNlri(new Object[] {rd, flows}, null, buffer); assertArrayEquals(UNREACHED_NLRI, ByteArray.readAllBytes(buffer)); parser.serializeAttribute(new AttributesBuilder() .addAugmentation(new AttributesUnreachBuilder().setMpUnreachNlri(mp.build()).build()) .build(), buffer); assertArrayEquals(UNREACHED_NLRI, ByteArray.readAllBytes(buffer)); assertEquals(""" all packets where ICMP type is less than 2 or is less than 3 AND where ICMP code is less than 4 \ or 5 AND where TCP flags is not 1025 or does match 22193 AND where packet length is less than 57005 \ AND where DSCP is greater than 42 AND where fragment does match 'IS FIRST' 'IS LAST' 'IS A' \ """, fsParser.stringNlri(flows)); } private static FlowspecType createFragment() { final List fragments = List.of(new FragmentsBuilder().setOp( new BitmaskOperand(false, true, true, false)).setValue(new Fragment(false, true, true, true)).build()); return new FragmentCaseBuilder().setFragments(fragments).build(); } private static FlowspecType createDscp() { final List dscps = List.of(new DscpsBuilder().setOp( new NumericOperand(false, true, false, true, false)).setValue(new Dscp(Uint8.valueOf(42))).build()); return new DscpCaseBuilder().setDscps(dscps).build(); } private static PacketLengthCase createPackets() { final List packets = List.of(new PacketLengthsBuilder().setOp( new NumericOperand(false, true, false, false, true)).setValue(Uint16.valueOf(57005)).build()); return new PacketLengthCaseBuilder().setPacketLengths(packets).build(); } private static TcpFlagsCase createTcp() { final List flags = List.of( new TcpFlagsBuilder().setOp(new BitmaskOperand(false, false, false, true)).setValue(Uint16.valueOf(1025)) .build(), new TcpFlagsBuilder().setOp(new BitmaskOperand(false, true, true, false)).setValue(Uint16.valueOf(22193)) .build()); return new TcpFlagsCaseBuilder().setTcpFlags(flags).build(); } private static FlowspecType createIcmpCode() { final List codes = List.of( new CodesBuilder().setOp(new NumericOperand(false, false, false, false, true)).setValue(Uint8.valueOf(4)) .build(), new CodesBuilder().setOp(new NumericOperand(false, true, false, false, false)).setValue(Uint8.valueOf(5)) .build()); return new IcmpCodeCaseBuilder().setCodes(codes).build(); } private static FlowspecType createIcmpType() { final List types = List.of( new TypesBuilder().setOp(new NumericOperand(false, false, false, false, true)).setValue(Uint8.TWO) .build(), new TypesBuilder().setOp(new NumericOperand(false, true, false, false, true)).setValue(Uint8.valueOf(3)) .build()); return new IcmpTypeCaseBuilder().setTypes(types).build(); } private static void checkUnreachFlows(final List flows, final FlowspecType icmpType, final FlowspecType icmpCode, final TcpFlagsCase tcp, final PacketLengthCase packet, final FlowspecType dscp, final FlowspecType fragment) { assertEquals(6, flows.size()); assertEquals(icmpType, flows.get(0).getFlowspecType()); assertEquals(icmpCode, flows.get(1).getFlowspecType()); assertEquals(tcp, flows.get(2).getFlowspecType()); assertEquals(packet, flows.get(3).getFlowspecType()); assertEquals(dscp, flows.get(4).getFlowspecType()); assertEquals(fragment, flows.get(5).getFlowspecType()); } @Test public void testParseMpUnreachNlriConstraint() throws BGPParsingException { final List fs = new ArrayList<>(); final MpUnreachNlriBuilder mp = new MpUnreachNlriBuilder(); final FlowspecBuilder builder = new FlowspecBuilder(); final FlowspecType icmpType = createIcmpType(); builder.setFlowspecType(icmpType); fs.add(builder.build()); final FlowspecType icmpCode = createIcmpCode(); builder.setFlowspecType(icmpCode); fs.add(builder.build()); final TcpFlagsCase tcp = createTcp(); builder.setFlowspecType(tcp); fs.add(builder.build()); final PacketLengthCase packet = createPackets(); builder.setFlowspecType(packet); fs.add(builder.build()); final FlowspecType dscp = createDscp(); builder.setFlowspecType(dscp); fs.add(builder.build()); final FlowspecType fragment = createFragment(); builder.setFlowspecType(fragment); fs.add(builder.build()); final FlowspecL3vpnIpv4NlriParser parser = new FlowspecL3vpnIpv4NlriParser(SAFI.FLOWSPEC_VPN); final MpUnreachNlriBuilder result = new MpUnreachNlriBuilder() .setAfi(Ipv4AddressFamily.VALUE) .setSafi(FlowspecL3vpnSubsequentAddressFamily.VALUE); parser.parseNlri(Unpooled.wrappedBuffer(UNREACHED_NLRI_ADD_PATH), result, constraint); DestinationFlowspecL3vpnIpv4 flowspecDst = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang .bgp.flowspec.rev200120.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type .DestinationFlowspecL3vpnIpv4Case) result.getWithdrawnRoutes().getDestinationType()) .getDestinationFlowspecL3vpnIpv4(); final List flows = flowspecDst.getFlowspec(); checkUnreachFlows(flows, icmpType, icmpCode, tcp, packet, dscp, fragment); final RouteDistinguisher rd = flowspecDst.getRouteDistinguisher(); mp.setAfi(Ipv4AddressFamily.VALUE).setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType( new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev200120.update .attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecL3vpnIpv4CaseBuilder() .setDestinationFlowspecL3vpnIpv4( new DestinationFlowspecL3vpnIpv4Builder() .setRouteDistinguisher(rd) .setPathId(PATH_ID) .setFlowspec(fs) .build() ).build() ).build() ); final ByteBuf buffer = Unpooled.buffer(); parser.serializeNlri(new Object[] {rd, flows}, PATH_ID, buffer); assertArrayEquals(UNREACHED_NLRI_ADD_PATH, ByteArray.readAllBytes(buffer)); parser.serializeAttribute(new AttributesBuilder() .addAugmentation(new AttributesUnreachBuilder().setMpUnreachNlri(mp.build()).build()) .build(), buffer); assertArrayEquals(UNREACHED_NLRI_ADD_PATH, ByteArray.readAllBytes(buffer)); assertEquals(""" all packets where ICMP type is less than 2 or is less than 3 AND where ICMP code is less than 4 \ or 5 AND where TCP flags is not 1025 or does match 22193 AND where packet length is less than 57005 \ AND where DSCP is greater than 42 AND where fragment does match 'IS FIRST' 'IS LAST' 'IS A' \ """, fsParser.stringNlri(flows)); } @Test public void testExtractFlowspecDestPrefix() { final DataContainerNodeBuilder entry = Builders.mapEntryBuilder(); entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry)); entry.withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.choiceBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(AbstractFlowspecNlriParser.DEST_PREFIX_NID) .withValue("127.0.0.5/32").build()).build()).build()).build()); final FlowspecBuilder expectedFS = new FlowspecBuilder(); expectedFS.setFlowspecType(new DestinationPrefixCaseBuilder().setDestinationPrefix( new Ipv4Prefix("127.0.0.5/32")).build()); assertEquals(List.of(expectedFS.build()), fsParser.extractFlowspec(entry.build())); } @Test public void testExtractFlowspecSourcePrefix() { final DataContainerNodeBuilder entry = Builders.mapEntryBuilder(); entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry)); entry.withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.choiceBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(AbstractFlowspecNlriParser.SOURCE_PREFIX_NID) .withValue("127.0.0.6/32").build()).build()).build()).build()); final FlowspecBuilder expectedFS = new FlowspecBuilder(); expectedFS.setFlowspecType(new SourcePrefixCaseBuilder().setSourcePrefix(new Ipv4Prefix("127.0.0.6/32")) .build()); final List expected = new ArrayList<>(); expected.add(expectedFS.build()); assertEquals(expected, fsParser.extractFlowspec(entry.build())); } @Test public void testExtractFlowspecProtocolIps() { final DataContainerNodeBuilder entry = Builders.mapEntryBuilder(); entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry)); entry.withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.choiceBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID) .withChild(Builders.unkeyedListBuilder().withNodeIdentifier(PROTOCOL_IP_NID) .withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(PROTOCOL_IP_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withValue(Set.of(AbstractOperandParser.END_OF_LIST_VALUE, AbstractOperandParser.AND_BIT_VALUE)).build()) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID) .withValue(Uint8.valueOf(100)).build()).build()) .withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(PROTOCOL_IP_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE)).build()) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID) .withValue(Uint8.valueOf(200)).build()).build()) .withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(PROTOCOL_IP_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withValue(Set.of(AbstractOperandParser.END_OF_LIST_VALUE, AbstractOperandParser.AND_BIT_VALUE, AbstractNumericOperandParser.EQUALS_VALUE)) .build()) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID) .withValue(Uint8.valueOf(240)).build()).build()) .build()).build()).build()).build()); final FlowspecBuilder expectedFS = new FlowspecBuilder() .setFlowspecType(new ProtocolIpCaseBuilder() .setProtocolIps(List.of(new ProtocolIpsBuilder() .setValue(Uint8.valueOf(100)) .setOp(new NumericOperand(true, true, false, false, false)) .build(), new ProtocolIpsBuilder() .setValue(Uint8.valueOf(200)) .setOp(new NumericOperand(true, false, false, false, false)) .build(), new ProtocolIpsBuilder() .setValue(Uint8.valueOf(240)) .setOp(new NumericOperand(true, true, true, false, false)) .build())) .build()); assertEquals(List.of(expectedFS.build()), fsParser.extractFlowspec(entry.build())); } @Test public void testExtractFlowspecPorts() { final DataContainerNodeBuilder entry = Builders.mapEntryBuilder(); entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry)); entry.withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.choiceBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID) .withChild(Builders.unkeyedListBuilder().withNodeIdentifier(AbstractFlowspecNlriParser.PORTS_NID) .withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(PROTOCOL_IP_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withValue(Set.of(AbstractOperandParser.END_OF_LIST_VALUE, AbstractOperandParser.AND_BIT_VALUE, AbstractNumericOperandParser.LESS_THAN_VALUE)) .build()) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID) .withValue(Uint16.valueOf(100)).build()).build()) .build()).build()).build()).build()); final FlowspecBuilder expectedFS = new FlowspecBuilder() .setFlowspecType(new PortCaseBuilder() .setPorts(List.of(new PortsBuilder() .setValue(Uint16.valueOf(100)) .setOp(new NumericOperand(true, true, false, false, true)) .build())) .build()); final List expected = new ArrayList<>(); expected.add(expectedFS.build()); assertEquals(expected, fsParser.extractFlowspec(entry.build())); } @Test public void testExtractFlowspecDestinationPorts() { final DataContainerNodeBuilder entry = Builders.mapEntryBuilder(); entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry)); entry.withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.choiceBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID) .withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.DEST_PORT_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.OP_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(AbstractFlowspecNlriParser.OP_NID) .withValue(Set.of(AbstractOperandParser.END_OF_LIST_VALUE, AbstractNumericOperandParser.EQUALS_VALUE)).build()) .withChild(Builders.leafBuilder().withNodeIdentifier(AbstractFlowspecNlriParser.VALUE_NID) .withValue(Uint16.valueOf(1024)).build()).build()) .build()).build()).build()).build()); final FlowspecBuilder expectedFS = new FlowspecBuilder(); expectedFS.setFlowspecType(new DestinationPortCaseBuilder() .setDestinationPorts(List.of(new DestinationPortsBuilder() .setValue(Uint16.valueOf(1024)) .setOp(new NumericOperand(false, true, true, false, false)) .build())) .build()); final List expected = new ArrayList<>(); expected.add(expectedFS.build()); assertEquals(expected, fsParser.extractFlowspec(entry.build())); } @Test public void testExtractFlowspecSourcePorts() { final DataContainerNodeBuilder entry = Builders.mapEntryBuilder(); entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry)); entry.withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.choiceBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID) .withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.SOURCE_PORT_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE, AbstractOperandParser.END_OF_LIST_VALUE, AbstractNumericOperandParser.EQUALS_VALUE, AbstractNumericOperandParser.GREATER_THAN_VALUE, AbstractNumericOperandParser.LESS_THAN_VALUE)).build()) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID) .withValue(Uint16.valueOf(8080)).build()).build()) .build()).build()).build()).build()); final FlowspecBuilder expectedFS = new FlowspecBuilder(); expectedFS.setFlowspecType(new SourcePortCaseBuilder() .setSourcePorts(List.of(new SourcePortsBuilder() .setValue(Uint16.valueOf(8080)) .setOp(new NumericOperand(true, true, true, true, true)) .build())) .build()); final List expected = new ArrayList<>(); expected.add(expectedFS.build()); assertEquals(expected, fsParser.extractFlowspec(entry.build())); } @Test public void testExtractFlowspecSourceTypes() { final DataContainerNodeBuilder entry = Builders.mapEntryBuilder(); entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry)); entry.withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.choiceBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID) .withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.ICMP_TYPE_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE, AbstractOperandParser.END_OF_LIST_VALUE, AbstractNumericOperandParser.EQUALS_VALUE, AbstractNumericOperandParser.GREATER_THAN_VALUE, AbstractNumericOperandParser.LESS_THAN_VALUE)).build()) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID) .withValue(Uint8.valueOf(22)).build()).build()) .build()).build()).build()).build()); final FlowspecBuilder expectedFS = new FlowspecBuilder(); expectedFS.setFlowspecType(new IcmpTypeCaseBuilder() .setTypes(List.of(new TypesBuilder() .setValue(Uint8.valueOf(22)) .setOp(new NumericOperand(true, true, true, true, true)) .build())) .build()); final List expected = new ArrayList<>(); expected.add(expectedFS.build()); assertEquals(expected, fsParser.extractFlowspec(entry.build())); } @Test public void testExtractFlowspecSourceCodes() { final DataContainerNodeBuilder entry = Builders.mapEntryBuilder(); entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry)); entry.withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.choiceBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID) .withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.ICMP_CODE_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withValue(Set.of()).build()) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID) .withValue(Uint8.valueOf(23)).build()).build()) .build()).build()).build()).build()); final FlowspecBuilder expectedFS = new FlowspecBuilder(); expectedFS.setFlowspecType(new IcmpCodeCaseBuilder() .setCodes(List.of(new CodesBuilder() .setValue(Uint8.valueOf(23)) .setOp(new NumericOperand(false, false, false, false, false)) .build())) .build()); assertEquals(List.of(expectedFS.build()), fsParser.extractFlowspec(entry.build())); } @Test public void testExtractFlowspecSourceTcpFlags() { final DataContainerNodeBuilder entry = Builders.mapEntryBuilder(); entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry)); entry.withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.choiceBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID) .withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.TCP_FLAGS_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE, AbstractOperandParser.END_OF_LIST_VALUE)).build()) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID) .withValue(Uint16.valueOf(99)).build()).build()) .build()).build()).build()).build()); final FlowspecBuilder expectedFS = new FlowspecBuilder(); expectedFS.setFlowspecType(new TcpFlagsCaseBuilder().setTcpFlags(List.of(new TcpFlagsBuilder() .setValue(Uint16.valueOf(99)).setOp(new BitmaskOperand(true, true, false, false)).build())).build()); final List expected = new ArrayList<>(); expected.add(expectedFS.build()); assertEquals(expected, fsParser.extractFlowspec(entry.build())); } @Test public void testExtractFlowspecPacketLengths() { final DataContainerNodeBuilder entry = Builders.mapEntryBuilder(); entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry)); entry.withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.choiceBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID) .withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.PACKET_LENGTHS_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE, AbstractNumericOperandParser.GREATER_THAN_VALUE)).build()) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID) .withValue(Uint16.valueOf(101)).build()).build()) .build()).build()).build()).build()); final FlowspecBuilder expectedFS = new FlowspecBuilder(); expectedFS.setFlowspecType(new PacketLengthCaseBuilder().setPacketLengths(List.of( new PacketLengthsBuilder().setValue(Uint16.valueOf(101)).setOp( new NumericOperand(true, false, false, true, false)).build())).build()); assertEquals(List.of(expectedFS.build()), fsParser.extractFlowspec(entry.build())); } @Test public void testExtractFlowspecDscps() { final DataContainerNodeBuilder entry = Builders.mapEntryBuilder(); entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry)); entry.withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.choiceBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID) .withChild(Builders.unkeyedListBuilder().withNodeIdentifier(AbstractFlowspecNlriParser.DSCP_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE, AbstractOperandParser.END_OF_LIST_VALUE, AbstractNumericOperandParser.GREATER_THAN_VALUE)).build()) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID) .withValue(Uint8.valueOf(15)).build()).build()) .build()).build()).build()).build()); final FlowspecBuilder expectedFS = new FlowspecBuilder(); expectedFS.setFlowspecType(new DscpCaseBuilder().setDscps(List.of(new DscpsBuilder().setValue( new Dscp(Uint8.valueOf(15))).setOp(new NumericOperand(true, true, false, true, false)).build())).build()); assertEquals(List.of(expectedFS.build()), fsParser.extractFlowspec(entry.build())); } @Test public void testExtractFlowspecFragments() { final DataContainerNodeBuilder entry = Builders.mapEntryBuilder(); entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry)); entry.withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_NID) .withChild(Builders.choiceBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FLOWSPEC_TYPE_NID) .withChild(Builders.unkeyedListBuilder() .withNodeIdentifier(AbstractFlowspecNlriParser.FRAGMENT_NID) .withChild(Builders.unkeyedListEntryBuilder() .withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.OP_NID) .withValue(Set.of(AbstractOperandParser.AND_BIT_VALUE, AbstractOperandParser.END_OF_LIST_VALUE, BitmaskOperandParser.MATCH_VALUE, BitmaskOperandParser.NOT_VALUE)).build()) .withChild(Builders.leafBuilder().withNodeIdentifier(FlowspecL3vpnIpv4NlriParser.VALUE_NID) .withValue(Set.of(AbstractFlowspecNlriParser.DO_NOT_VALUE, AbstractFlowspecNlriParser.FIRST_VALUE, AbstractFlowspecNlriParser.IS_A_VALUE, AbstractFlowspecNlriParser.LAST_VALUE)).build()).build()) .build()).build()).build()).build()); final FlowspecBuilder expectedFS = new FlowspecBuilder(); expectedFS.setFlowspecType(new FragmentCaseBuilder().setFragments(List.of(new FragmentsBuilder() .setValue(new Fragment(true, true, true, true)).setOp(new BitmaskOperand(true, true, true, true)).build())) .build()); assertEquals(List.of(expectedFS.build()), fsParser.extractFlowspec(entry.build())); } @Test public void testExtractFlowspecRouteDistinguisher() { final DataContainerNodeBuilder entry = Builders.mapEntryBuilder(); entry.withNodeIdentifier(NodeIdentifierWithPredicates.of(FlowspecRoute.QNAME, FlowspecRoute.QNAME, entry)); entry.withChild( Builders.leafBuilder() .withNodeIdentifier(RD_NID) .withValue( RouteDistinguisherBuilder.getDefaultInstance(ROUTE_DISTINGUISHER) ).build() ); RouteDistinguisher rd = RouteDistinguisherBuilder.getDefaultInstance(ROUTE_DISTINGUISHER); assertEquals(rd, extractRouteDistinguisher(entry.build(), AbstractFlowspecL3vpnNlriParser.RD_NID)); } }