Merge "Tests for neutron-ovsdb"
[groupbasedpolicy.git] / renderers / ofoverlay / src / test / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / arp / ArpTaskerTest.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
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.arp;
10
11 import static org.junit.Assert.assertArrayEquals;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertTrue;
14 import static org.junit.Assume.assumeNoException;
15 import static org.mockito.Matchers.any;
16 import static org.mockito.Mockito.mock;
17 import static org.mockito.Mockito.never;
18 import static org.mockito.Mockito.verify;
19 import static org.mockito.Mockito.when;
20
21 import java.net.InetAddress;
22 import java.util.Collections;
23 import java.util.concurrent.Future;
24
25 import com.google.common.util.concurrent.UncheckedExecutionException;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.mockito.ArgumentCaptor;
29 import org.mockito.Matchers;
30 import org.mockito.Mockito;
31 import org.opendaylight.controller.liblldp.EtherTypes;
32 import org.opendaylight.controller.liblldp.Ethernet;
33 import org.opendaylight.controller.liblldp.HexEncode;
34 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
35 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
36 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
37 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
38 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
39 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
40 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.test.OfOverlayDataBrokerTest;
41 import org.opendaylight.groupbasedpolicy.util.IidFactory;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2ContextId;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3Context;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3ContextBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayNodeConfig;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayNodeConfigBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.nodes.node.ExternalInterfacesBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.TenantsBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantKey;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ForwardingContext;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ForwardingContextBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceivedBuilder;
97 import org.opendaylight.yangtools.yang.binding.DataObject;
98 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
99 import org.opendaylight.yangtools.yang.common.RpcResult;
100
101 import com.google.common.base.Optional;
102 import com.google.common.util.concurrent.CheckedFuture;
103 import com.google.common.util.concurrent.Futures;
104
105 public class ArpTaskerTest extends OfOverlayDataBrokerTest {
106
107     private ArpTasker arpTasker;
108     private DataBroker broker;
109     private RpcProviderRegistry rpcRegistry;
110     private SalFlowService flowService;
111
112     @Before
113     public void init() {
114
115         PacketProcessingService packetService = mock(PacketProcessingService.class);
116         flowService = mock(SalFlowService.class);
117         rpcRegistry = mock(RpcProviderRegistry.class);
118         when(rpcRegistry.getRpcService(PacketProcessingService.class)).thenReturn(packetService);
119         when(rpcRegistry.getRpcService(SalFlowService.class)).thenReturn(flowService);
120     }
121
122     @SuppressWarnings("unchecked")
123     @Test
124     public void addMacForL3EpAndCreateEp_onPacketReceivedTest() throws Exception {
125
126         IpAddress ipAddr = new IpAddress(new Ipv4Address("192.168.0.1"));
127         L3ContextId l3conId = new L3ContextId("l3context");
128         EndpointL3Key key = new EndpointL3Key(ipAddr, l3conId);
129         EndpointL3Builder epL3 = new EndpointL3Builder();
130         // node conector
131         NodeConnectorId connectorId = new NodeConnectorId("nodeConnector");
132         MacAddress macAddr = new MacAddress("00:00:00:00:00:01");
133         FlowCapableNodeConnectorBuilder fcnConnector =
134                 new FlowCapableNodeConnectorBuilder().setHardwareAddress(macAddr);
135         NodeConnectorBuilder connector = new NodeConnectorBuilder().setKey(new NodeConnectorKey(connectorId))
136             .addAugmentation(FlowCapableNodeConnector.class, fcnConnector.build());
137         // node
138         NodeId nodeId = new NodeId("node");
139         ExternalInterfacesBuilder extIface = new ExternalInterfacesBuilder().setNodeConnectorId(connectorId);
140         OfOverlayNodeConfigBuilder ofOverNodeCfg =
141                 new OfOverlayNodeConfigBuilder().setExternalInterfaces(Collections.singletonList(extIface.build()));
142         NodeBuilder node = new NodeBuilder().addAugmentation(OfOverlayNodeConfig.class, ofOverNodeCfg.build())
143                 .setKey(new NodeKey(nodeId))
144                 .setId(nodeId)
145                 .setNodeConnector(Collections.singletonList(connector.build()));
146         // subnet
147         NetworkDomainId domainId = new NetworkDomainId("domainId");
148         TenantId tenantId = new TenantId("tenant");
149         L2ContextId l2conId = new L2ContextId("l2context");
150         SubnetBuilder subnet = new SubnetBuilder().setId(new SubnetId(domainId))
151             .setIpPrefix(new IpPrefix(new Ipv4Prefix(ipAddr.getIpv4Address().getValue() + "/24")))
152             .setParent(l2conId);
153         TenantsBuilder tenants =
154                 new TenantsBuilder().setTenant(Collections.singletonList(new TenantBuilder().setId(tenantId)
155                     .setForwardingContext(
156                             new ForwardingContextBuilder().setSubnet(Collections.singletonList(subnet.build())).build())
157                     .build()));
158
159         // test without key
160         ReadOnlyTransaction rtx = mock(ReadOnlyTransaction.class);
161         broker = mock(DataBroker.class);
162         arpTasker = new ArpTasker(rpcRegistry, broker);
163
164         epL3.setKey(new EndpointL3Key(mock(IpAddress.class), null));
165         arpTasker.addMacForL3EpAndCreateEp(epL3.build());
166         verify(broker, never()).newReadOnlyTransaction();
167
168         // test without node with external interface
169         epL3.setKey(key);
170         when(broker.newReadOnlyTransaction()).thenReturn(rtx);
171         CheckedFuture<Optional<DataObject>, ReadFailedException> future =
172                 Futures.immediateCheckedFuture(Optional.<DataObject>absent());
173         when(rtx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION),
174                 any(InstanceIdentifier.class)))
175             .thenReturn(future);
176         arpTasker.addMacForL3EpAndCreateEp(epL3.build());
177         verify(broker).newReadOnlyTransaction();
178         verify(rtx).close();
179
180         // test correct
181         broker = getDataBroker();
182         arpTasker = new ArpTasker(rpcRegistry, broker);
183         WriteTransaction wtx = broker.newWriteOnlyTransaction();
184         wtx.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(Nodes.class).build(),
185                 new NodesBuilder().setNode(Collections.singletonList(node.build())).build(), true);
186         wtx.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(Nodes.class)
187                 .child(Node.class, node.getKey())
188                 .child(NodeConnector.class, new NodeConnectorKey(connectorId))
189                 .build(),
190                 connector.build(), true);
191         // ignoring a Windows-specific bug
192         try {
193             wtx.put(LogicalDatastoreType.CONFIGURATION,
194                     InstanceIdentifier.builder(Tenants.class).build(), tenants.build(), true);
195         } catch (UncheckedExecutionException e) {
196             assumeNoException(e);
197         }
198         wtx.submit().get();
199
200         Future<RpcResult<AddFlowOutput>> flowFuture = mock(Future.class);
201         when(flowService.addFlow(any(AddFlowInput.class))).thenReturn(flowFuture);
202
203         epL3.setNetworkContainment(domainId).setTenant(tenantId);
204         arpTasker.addMacForL3EpAndCreateEp(epL3.build());
205         ArgumentCaptor<AddFlowInput> argument = ArgumentCaptor.forClass(AddFlowInput.class);
206         verify(flowService).addFlow(argument.capture());
207         AddFlowInput result = argument.getValue();
208         assertEquals(EtherTypes.ARP.intValue(), result.getMatch()
209                 .getEthernetMatch()
210                 .getEthernetType()
211                 .getType()
212                 .getValue()
213                 .intValue());
214         ArpMatch match = (ArpMatch)result.getMatch().getLayer3Match();
215         assertEquals(ArpOperation.REPLY.intValue(), match.getArpOp().intValue());
216         assertEquals("192.168.0.254/32", match.getArpTargetTransportAddress().getValue());
217         assertEquals("192.168.0.1/32", match.getArpSourceTransportAddress().getValue());
218         assertEquals(connectorId, result.getMatch().getInPort());
219         assertEquals(new NodeRef(
220                 InstanceIdentifier.builder(Nodes.class).child(Node.class, node.getKey()).build()),
221                 result.getNode());
222
223         // onPacketReceived
224         Arp arp = new Arp();
225         byte[] sha = HexEncode.bytesFromHexString("00:00:00:00:00:01");
226         byte[] spa = InetAddress.getByName("192.168.0.1").getAddress();
227         byte[] tha = HexEncode.bytesFromHexString("00:00:00:00:00:02");
228         byte[] tpa = InetAddress.getByName("192.168.0.2").getAddress();
229         int htype = 1;
230         int ptype = EtherTypes.IPv4.intValue();
231         short hlen = 6;
232         short plen = 4;
233         int operation = ArpOperation.REPLY.intValue();
234
235         arp.setSenderHardwareAddress(sha);
236         arp.setSenderProtocolAddress(spa);
237         arp.setTargetHardwareAddress(tha);
238         arp.setTargetProtocolAddress(tpa);
239         arp.setOperation(operation);
240         arp.setHardwareLength(hlen);
241         arp.setProtocolLength(plen);
242         arp.setHardwareType(htype);
243         arp.setProtocolType(ptype);
244
245         Ethernet arpFrame = new Ethernet().setSourceMACAddress(sha)
246             .setDestinationMACAddress(tha)
247             .setEtherType(EtherTypes.ARP.shortValue());
248         arpFrame.setPayload(arp);
249
250         L2BridgeDomainId l2domainId = new L2BridgeDomainId(l2conId);
251         L2BridgeDomainBuilder l2domain = new L2BridgeDomainBuilder().setId(l2domainId);
252
253         InstanceIdentifier<NodeConnector> ncIid = InstanceIdentifier.builder(Nodes.class)
254             .child(Node.class, new NodeKey(new NodeId("node")))
255             .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("connector")))
256             .build();
257         PacketReceived packet = new PacketReceivedBuilder().setPayload(arpFrame.serialize())
258             .setIngress(new NodeConnectorRef(ncIid))
259             .build();
260
261         wtx = broker.newWriteOnlyTransaction();
262         OfOverlayL3Context augment = new OfOverlayL3ContextBuilder().build();
263         epL3.addAugmentation(OfOverlayL3Context.class, augment);
264         InstanceIdentifier<EndpointL3> epL3Iid =
265                 InstanceIdentifier.builder(Endpoints.class).child(EndpointL3.class, key).build();
266         wtx.put(LogicalDatastoreType.OPERATIONAL, epL3Iid, epL3.build(), true);
267
268         InstanceIdentifier<L2BridgeDomain> l2domainIid = InstanceIdentifier.builder(Tenants.class)
269             .child(Tenant.class, new TenantKey(tenantId))
270             .child(ForwardingContext.class)
271             .child(L2BridgeDomain.class, new L2BridgeDomainKey(l2domainId))
272             .build();
273         wtx.put(LogicalDatastoreType.OPERATIONAL, l2domainIid, l2domain.build() ,true);
274         wtx.submit();
275
276         arpTasker.onPacketReceived(packet);
277         rtx = broker.newReadOnlyTransaction();
278         Optional<EndpointL3> optional = rtx.read(LogicalDatastoreType.OPERATIONAL, epL3Iid).get();
279         assertTrue(optional.isPresent());
280         EndpointL3 epl3 = optional.get();
281         assertArrayEquals(sha, HexEncode.bytesFromHexString(epl3.getMacAddress().getValue()));
282         assertEquals(l2domain.getId(), epl3.getL2Context());
283         Optional<Endpoint> optionalEp = rtx.read(LogicalDatastoreType.OPERATIONAL,
284                 IidFactory.endpointIid(l2domainId, new MacAddress("00:00:00:00:00:01"))).get();
285         assertTrue(optionalEp.isPresent());
286         assertEquals(new OfOverlayContextBuilder(augment).build(),
287                 optionalEp.get().getAugmentation(OfOverlayContext.class));
288     }
289 }