2 * Copyright (c) 2013-2014 NEC Corporation
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this
7 * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
10 package org.opendaylight.vtn.manager.internal;
13 import java.io.FileWriter;
14 import java.io.IOException;
15 import java.net.InetAddress;
16 import java.util.ArrayList;
17 import java.util.HashSet;
18 import java.util.Hashtable;
19 import java.util.List;
22 import java.util.concurrent.ConcurrentHashMap;
23 import java.util.concurrent.ConcurrentMap;
25 import org.apache.felix.dm.impl.ComponentImpl;
27 import org.junit.Test;
28 import org.opendaylight.controller.sal.core.Node;
29 import org.opendaylight.controller.sal.core.NodeConnector;
30 import org.opendaylight.controller.sal.core.Property;
31 import org.opendaylight.controller.sal.core.UpdateType;
32 import org.opendaylight.controller.sal.packet.ARP;
33 import org.opendaylight.controller.sal.packet.Ethernet;
34 import org.opendaylight.controller.sal.packet.IEEE8021Q;
35 import org.opendaylight.controller.sal.packet.PacketResult;
36 import org.opendaylight.controller.sal.packet.RawPacket;
37 import org.opendaylight.controller.sal.utils.EtherTypes;
38 import org.opendaylight.controller.sal.utils.GlobalConstants;
39 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
40 import org.opendaylight.controller.sal.utils.NodeCreator;
41 import org.opendaylight.controller.sal.utils.Status;
42 import org.opendaylight.controller.switchmanager.ISwitchManager;
43 import org.opendaylight.controller.topologymanager.ITopologyManager;
44 import org.opendaylight.vtn.manager.IVTNManager;
45 import org.opendaylight.vtn.manager.PortMapConfig;
46 import org.opendaylight.vtn.manager.SwitchPort;
47 import org.opendaylight.vtn.manager.VBridgeConfig;
48 import org.opendaylight.vtn.manager.VBridgeIfPath;
49 import org.opendaylight.vtn.manager.VBridgePath;
50 import org.opendaylight.vtn.manager.VInterfaceConfig;
51 import org.opendaylight.vtn.manager.VTNException;
52 import org.opendaylight.vtn.manager.VTenantConfig;
53 import org.opendaylight.vtn.manager.VTenantPath;
54 import org.opendaylight.vtn.manager.VlanMap;
55 import org.opendaylight.vtn.manager.VlanMapConfig;
56 import org.opendaylight.vtn.manager.internal.cluster.ClusterEventId;
57 import org.opendaylight.vtn.manager.internal.cluster.PortVlan;
58 import org.opendaylight.vtn.manager.internal.cluster.RawPacketEvent;
61 * JUnit test for {@link VTNManagerImplTest}.
64 * Test a function disable some service for a newly detected node.
67 public class VTNManagerImplDisableNodesTest extends TestBase {
68 private VTNManagerImpl vtnMgr = null;
69 private TestStub stubObj = null;
70 private int stubMode = 2;
73 * test case receive packet with existing entry in {@code disabledNode}.
76 public void testWithHavingDisabledNode() {
77 // set a value of EdgeTimeout to 600 sec.
78 setupVTNManager(600000);
80 VTNManagerImpl mgr = vtnMgr;
81 ISwitchManager swMgr = mgr.getSwitchManager();
82 ITopologyManager topoMgr = mgr.getTopologyManager();
83 TestStub stub = stubObj;
84 short[] vlans = new short[] {0, 10, 4095};
87 VTenantPath tpath = new VTenantPath(tname);
88 String bname = "vbridge";
89 VBridgePath bpath = new VBridgePath(tname, bname);
90 VBridgeIfPath ifp = new VBridgeIfPath(tname, bname, "vinterface");
93 List<VBridgePath> bpathlist = new ArrayList<VBridgePath>();
94 List<VBridgeIfPath> ifplist = new ArrayList<VBridgeIfPath>();
97 createTenantAndBridgeAndInterface(mgr, tpath, bpathlist, ifplist);
99 ConcurrentMap<VBridgePath, Set<NodeConnector>> mappedConnectors =
100 new ConcurrentHashMap<VBridgePath, Set<NodeConnector>>();
101 mappedConnectors.put(bpath, new HashSet<NodeConnector>());
103 Set<Node> existNodes = swMgr.getNodes();
104 Set<NodeConnector> existConnectors = new HashSet<NodeConnector>();
105 for (Node node : existNodes) {
106 existConnectors.addAll(swMgr.getNodeConnectors(node));
109 Set<Node> vmapNodes = new HashSet<Node>(existNodes);
112 byte[] src = new byte[] {(byte)0x00, (byte)0x00, (byte)0x00,
113 (byte)0x00, (byte)0x00, (byte)0x11};
114 byte[] dst = new byte[] {(byte)0xff, (byte)0xff, (byte)0xff,
115 (byte)0xff, (byte)0xff, (byte)0xff};
116 byte[] sender = new byte[] {(byte)192, (byte)168, (byte)0, (byte)1};
117 byte[] target = new byte[] {(byte)192, (byte)168, (byte)0, (byte)250};
119 Node pnode = NodeCreator.createOFNode(0L);
120 SwitchPort port = new SwitchPort(
121 NodeConnector.NodeConnectorIDType.OPENFLOW, String.valueOf(10));
122 NodeConnector pmapnc = NodeConnectorCreator.createOFNodeConnector(
123 Short.valueOf((short)10), pnode);
124 Node disableNode = NodeCreator.createOFNode(0L);
126 for (short vlan : vlans) {
128 Set<PortVlan> portMappedThis = new HashSet<PortVlan>();
129 Set<PortVlan> portMappedOther = new HashSet<PortVlan>();
130 short pmapvlan = vlan;
132 PortMapConfig pmconf = new PortMapConfig(pnode, port, pmapvlan);
133 st = mgr.setPortMap(ifp, pmconf);
134 assertTrue(st.isSuccess());
136 Set<NodeConnector> set = mappedConnectors.get(bpath);
138 mappedConnectors.put(bpath, set);
139 portMappedThis.add(new PortVlan(pmapnc, pmapvlan));
141 for (Node vlanMapNode : vmapNodes) {
142 for (short vmapVlan : vlans) {
143 Set<PortVlan> mappedThis = new HashSet<PortVlan>();
144 Set<PortVlan> disabledPV = new HashSet<PortVlan>();
147 VlanMapConfig vlconf = new VlanMapConfig(vlanMapNode,
151 map = mgr.addVlanMap(bpath, vlconf);
152 } catch (VTNException e) {
156 for (Node node : existNodes) {
157 if (vlanMapNode == null || node.equals(vlanMapNode)) {
158 for (NodeConnector nc :
159 swMgr.getNodeConnectors(node)) {
160 if (!topoMgr.isInternal(nc)) {
161 mappedThis.add(new PortVlan(nc, vmapVlan));
162 if (node.equals(disableNode)) {
163 disabledPV.add(new PortVlan(nc,
171 mappedThis.addAll(portMappedThis);
172 mappedThis.removeAll(portMappedOther);
174 if (pmconf.getNode().equals(disableNode)) {
175 disabledPV.add(new PortVlan(pmapnc, pmapvlan));
178 // a result of adding Node, specified Node set to
180 addNode(mgr, swMgr, disableNode);
182 // EdgeTimeout is not infinity, but time is long enough and
183 // expected to return result before timeout.
184 for (PortVlan pv : mappedThis) {
185 String emsg = "vlan=" + vlan + "," + vlconf.toString()
186 + "," + pv.toString();
188 RawPacket inPkt = createARPRawPacket(src, dst, sender,
189 target, (pv.getVlan() > 0) ? pv.getVlan() : -1,
190 pv.getNodeConnector(), ARP.REQUEST);
191 PacketResult result = mgr.receiveDataPacket(inPkt);
192 List<RawPacket> transDatas = stub.
193 getTransmittedDataPacket();
195 if (pv.getNodeConnector().getNode().equals(disableNode)) {
196 assertEquals(emsg, PacketResult.IGNORED, result);
197 assertEquals(emsg, 0, transDatas.size());
199 assertEquals(emsg, PacketResult.KEEP_PROCESSING,
202 mappedThis.size() - disabledPV.size() - 1,
206 for (RawPacket raw : transDatas) {
207 Ethernet pkt = (Ethernet)stub.decodeDataPacket(raw);
208 String emsgr = emsg + ",(out packet)"
209 + pkt.toString() + ",(in nc)"
210 + raw.getIncomingNodeConnector()
212 + raw.getOutgoingNodeConnector();
215 if (pkt.getEtherType() ==
216 EtherTypes.VLANTAGGED.shortValue()) {
217 IEEE8021Q vlantag = (IEEE8021Q)pkt.getPayload();
218 outVlan = vlantag.getVid();
222 PortVlan outPv = new PortVlan(raw.getOutgoingNodeConnector(),
224 assertTrue(emsgr, mappedThis.contains(outPv));
226 checkOutEthernetPacket(
227 emsgr, (Ethernet)pkt, EtherTypes.ARP, src, dst,
228 outVlan, EtherTypes.IPv4, ARP.REQUEST, src, dst,
233 mgr.clearDisabledNode();
235 for (PortVlan pv : mappedThis) {
236 String emsg = "(vlan)" + vlan
237 + ",(VlanMapConfig)" + vlconf.toString()
238 + ",(PortVlan)" + pv.toString();
239 RawPacket inPkt = createARPRawPacket(src, dst, sender,
240 target, (pv.getVlan() > 0) ? pv.getVlan() : -1,
241 pv.getNodeConnector(), ARP.REQUEST);
242 PacketResult result = mgr.receiveDataPacket(inPkt);
243 List<RawPacket> transDatas = stub.getTransmittedDataPacket();
245 assertEquals(emsg, PacketResult.KEEP_PROCESSING, result);
246 assertEquals(emsg, mappedThis.size() - 1, transDatas.size());
249 st = mgr.removeVlanMap(bpath, map.getId());
250 assertTrue("(vlconf)" + vlconf.toString()
261 * test case receive a packet after disabledNode timer is expired.
264 public void testDisabledNodeAfterTimeout() {
265 // set a value of EdgeTimeout to 1 msec.
266 // expect expire before receive a packet.
269 VTNManagerImpl mgr = vtnMgr;
270 ISwitchManager swMgr = mgr.getSwitchManager();
271 ITopologyManager topoMgr = mgr.getTopologyManager();
272 TestStub stub = stubObj;
273 short[] vlans = new short[] {0, 10, 4095};
275 String tname = "vtn";
276 VTenantPath tpath = new VTenantPath(tname);
277 String bname = "vbridge";
278 VBridgePath bpath = new VBridgePath(tname, bname);
279 String ifname = "vinterface";
280 VBridgeIfPath ifp = new VBridgeIfPath(tname, bname, ifname);
283 List<VBridgePath> bpathlist = new ArrayList<VBridgePath>();
284 List<VBridgeIfPath> ifplist = new ArrayList<VBridgeIfPath>();
285 bpathlist.add(bpath);
287 createTenantAndBridgeAndInterface(mgr, tpath, bpathlist, ifplist);
289 ConcurrentMap<VBridgePath, Set<NodeConnector>> mappedConnectors =
290 new ConcurrentHashMap<VBridgePath, Set<NodeConnector>>();
291 mappedConnectors.put(bpath, new HashSet<NodeConnector>());
293 Set<Node> existNodes = swMgr.getNodes();
294 Set<NodeConnector> existConnectors = new HashSet<NodeConnector>();
295 for (Node node : existNodes) {
296 existConnectors.addAll(swMgr.getNodeConnectors(node));
299 Set<Node> vmapNodes = new HashSet<Node>(existNodes);
302 byte[] src = new byte[] {(byte)0x00, (byte)0x00, (byte)0x00,
303 (byte)0x00, (byte)0x00, (byte)0x11};
304 byte[] dst = new byte[] {(byte)0xff, (byte)0xff, (byte)0xff,
305 (byte)0xff, (byte)0xff, (byte)0xff};
306 byte[] sender = new byte[] {(byte)192, (byte)168, (byte)0, (byte)1};
307 byte[] target = new byte[] {(byte)192, (byte)168, (byte)0, (byte)250};
309 Node pnode = NodeCreator.createOFNode(0L);
310 SwitchPort port = new SwitchPort(
311 NodeConnector.NodeConnectorIDType.OPENFLOW, String.valueOf(10));
312 NodeConnector pmapnc = NodeConnectorCreator.
313 createOFNodeConnector(Short.valueOf((short)10), pnode);
314 Node disableNode = NodeCreator.createOFNode(0L);
316 for (short vlan : vlans) {
318 Set<PortVlan> portMappedThis = new HashSet<PortVlan>();
319 Set<PortVlan> portMappedOther = new HashSet<PortVlan>();
320 short pmapvlan = vlan;
322 PortMapConfig pmconf = new PortMapConfig(pnode, port, pmapvlan);
323 st = mgr.setPortMap(ifp, pmconf);
324 assertTrue(st.isSuccess());
326 Set<NodeConnector> set = mappedConnectors.get(bpath);
328 mappedConnectors.put(bpath, set);
329 portMappedThis.add(new PortVlan(pmapnc, pmapvlan));
331 for (Node vlanMapNode : vmapNodes) {
332 for (short vmapVlan : vlans) {
333 Set<PortVlan> mappedThis = new HashSet<PortVlan>();
334 Set<PortVlan> disabledPV = new HashSet<PortVlan>();
337 VlanMapConfig vlconf = new VlanMapConfig(vlanMapNode,
341 map = mgr.addVlanMap(bpath, vlconf);
342 } catch (VTNException e) {
346 for (Node node : existNodes) {
347 if (vlanMapNode == null || node.equals(vlanMapNode)) {
348 for (NodeConnector nc :
349 swMgr.getNodeConnectors(node)) {
350 if (!topoMgr.isInternal(nc)) {
351 mappedThis.add(new PortVlan(nc, vmapVlan));
352 if (node.equals(disableNode)) {
353 disabledPV.add(new PortVlan(nc,
361 mappedThis.addAll(portMappedThis);
362 mappedThis.removeAll(portMappedOther);
364 if (pmconf.getNode().equals(disableNode)) {
365 disabledPV.add(new PortVlan(pmapnc, pmapvlan));
368 // a result of adding Node, specified Node set to
370 addNode(mgr, swMgr, disableNode);
371 waitFor(mgr, disableNode);
373 for (PortVlan pv : mappedThis) {
374 String emsg = "(vlan)" + vlan
375 + ",(vlanmap conf)" + vlconf.toString()
376 + ",(portvlan)" + pv.toString();
377 RawPacket inPkt = createARPRawPacket(src, dst, sender,
378 target, (pv.getVlan() > 0) ? pv.getVlan() : -1,
379 pv.getNodeConnector(), ARP.REQUEST);
380 PacketResult result = mgr.receiveDataPacket(inPkt);
381 List<RawPacket> transDatas = stub.getTransmittedDataPacket();
382 assertEquals(emsg, PacketResult.KEEP_PROCESSING, result);
383 assertEquals(emsg, mappedThis.size() - 1,
386 for (RawPacket raw : transDatas) {
387 Ethernet pkt = (Ethernet)stub.decodeDataPacket(raw);
388 String emsgr = emsg + ",(out packet)"
389 + pkt.toString() + ",(in nc)"
390 + raw.getIncomingNodeConnector()
392 + raw.getOutgoingNodeConnector();
394 if (pkt.getEtherType()
395 == EtherTypes.VLANTAGGED.shortValue()) {
396 IEEE8021Q vlantag = (IEEE8021Q)pkt.getPayload();
397 outVlan = vlantag.getVid();
401 PortVlan outPv = new PortVlan(raw.getOutgoingNodeConnector(),
403 assertTrue(emsgr, mappedThis.contains(outPv));
405 checkOutEthernetPacket(
406 emsgr, (Ethernet)pkt, EtherTypes.ARP, src, dst,
407 outVlan, EtherTypes.IPv4, ARP.REQUEST, src, dst,
412 st = mgr.removeVlanMap(bpath, map.getId());
413 assertTrue("(vlconf)" + vlconf.toString() + ",(status)" + st,
423 * Test method for {@link VTNManagerImpl#entryUpdated}.
424 * This tests {@link RawPacketEvent}.
427 public void testCacheEntryChangeRawPacketEvent() {
428 // set a value of EdgeTimeout to 600 sec.
429 setupVTNManager(600000);
431 VTNManagerImpl mgr = vtnMgr;
432 ISwitchManager swMgr = mgr.getSwitchManager();
434 byte[] src = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
435 byte[] dst = new byte[] {(byte)0xff, (byte)0xff, (byte)0xff,
436 (byte)0xff, (byte)0xff, (byte)0xff};
437 byte[] sender = new byte[] {(byte)192, (byte)168, (byte)0, (byte)1};
438 byte[] target = new byte[] {(byte)192, (byte)168, (byte)0, (byte)10};
439 Node node0 = NodeCreator.createOFNode(Long.valueOf(0L));
440 NodeConnector innc = NodeConnectorCreator.
441 createOFNodeConnector(Short.valueOf((short)10), node0);
442 NodeConnector outnc = NodeConnectorCreator.
443 createOFNodeConnector(Short.valueOf((short)11), node0);
444 RawPacket pkt = createARPRawPacket(src, dst, sender, target, (short)0,
447 RawPacketEvent ev = new RawPacketEvent(pkt, outnc);
449 InetAddress ipaddr = getInetAddressFromAddress(new byte[] {0, 0, 0, 0});
450 ClusterEventId evidRemote = new ClusterEventId(ipaddr, 0);
451 ClusterEventId evidLocal = new ClusterEventId();
453 Set<ClusterEventId> evIdSet = new HashSet<ClusterEventId>();
454 evIdSet.add(evidLocal);
455 evIdSet.add(evidRemote);
457 for (Node disableNode : swMgr.getNodes()) {
458 for (ClusterEventId evid : evIdSet) {
459 mgr.clearDisabledNode();
460 addNode(mgr, swMgr, disableNode);
462 String emsg = evid.toString();
463 // in case entry created, no operation is executed.
464 mgr.entryCreated(evid, VTNManagerImpl.CACHE_EVENT, true);
466 assertEquals(emsg, 0, stubObj.getTransmittedDataPacket().size());
468 mgr.entryCreated(evid, VTNManagerImpl.CACHE_EVENT, false);
470 assertEquals(emsg, 0, stubObj.getTransmittedDataPacket().size());
473 mgr.entryUpdated(evid, ev, VTNManagerImpl.CACHE_EVENT, true);
475 assertEquals(emsg, 0, stubObj.getTransmittedDataPacket().size());
477 mgr.entryUpdated(evid, ev, VTNManagerImpl.CACHE_EVENT, false);
479 if (evid == evidRemote && !disableNode.equals(node0)) {
480 assertEquals(emsg, 1,
481 stubObj.getTransmittedDataPacket().size());
483 assertEquals(emsg, 0,
484 stubObj.getTransmittedDataPacket().size());
487 // in case entry deleted, no operation is executed.
488 mgr.entryDeleted(evid, VTNManagerImpl.CACHE_EVENT, true);
490 assertEquals(emsg, 0,
491 stubObj.getTransmittedDataPacket().size());
493 mgr.entryDeleted(evid, VTNManagerImpl.CACHE_EVENT, false);
495 assertEquals(emsg, 0,
496 stubObj.getTransmittedDataPacket().size());
509 * @param containerName a container name.
510 * @param val {@code nodeEdgeWait} time (in milliseconds)
512 private void setupInifile(String containerName, int val) {
513 String dir = GlobalConstants.STARTUPHOME.toString();
514 String filename = "vtnmanager-" + containerName + ".ini";
517 File inifile = new File(dir, filename);
518 String prop = "nodeEdgeWait=" + val;
520 writer = new FileWriter(inifile);
523 } catch (IOException e) {
531 * @param edgeTimeoutVal a time wait after new node detect in millisecond.
533 private void setupVTNManager(int edgeTimeoutVal) {
534 File confdir = new File(GlobalConstants.STARTUPHOME.toString());
535 boolean result = confdir.exists();
537 result = confdir.mkdirs();
539 File[] list = confdir.listFiles();
540 for (File f : list) {
545 setupInifile("default", edgeTimeoutVal);
547 vtnMgr = new VTNManagerImpl();
548 ComponentImpl c = new ComponentImpl(null, null, null);
549 GlobalResourceManager grsc = new GlobalResourceManager();
550 stubObj = new TestStub(stubMode);
552 Hashtable<String, String> properties = new Hashtable<String, String>();
553 properties.put("containerName", "default");
554 c.setServiceProperties(properties);
556 grsc.setClusterGlobalService(stubObj);
558 vtnMgr.setResourceManager(grsc);
559 vtnMgr.setClusterContainerService(stubObj);
560 vtnMgr.setSwitchManager(stubObj);
561 vtnMgr.setTopologyManager(stubObj);
562 vtnMgr.setDataPacketService(stubObj);
563 vtnMgr.setRouting(stubObj);
564 vtnMgr.setHostTracker(stubObj);
565 vtnMgr.setForwardingRuleManager(stubObj);
566 vtnMgr.setConnectionManager(stubObj);
567 vtnMgr.setContainerManager(stubObj);
569 vtnMgr.clearDisabledNode();
575 private void stopVTNManager() {
578 String currdir = new File(".").getAbsoluteFile().getParent();
579 File confdir = new File(GlobalConstants.STARTUPHOME.toString());
580 if (confdir.exists()) {
581 File[] list = confdir.listFiles();
582 for (File f : list) {
586 while (confdir != null && confdir.getAbsolutePath() != currdir) {
588 String pname = confdir.getParent();
592 confdir = new File(pname);
598 * method for setup a environment. create 1 Tenant and bridges and vinterfaces.
600 private void createTenantAndBridgeAndInterface(IVTNManager mgr,
601 VTenantPath tpath, List<VBridgePath> bpaths,
602 List<VBridgeIfPath> ifpaths) {
604 Status st = mgr.addTenant(tpath, new VTenantConfig(null));
605 assertTrue(st.isSuccess());
606 assertTrue(mgr.isActive());
608 for (VBridgePath bpath : bpaths) {
609 st = mgr.addBridge(bpath, new VBridgeConfig(null));
610 assertTrue(st.isSuccess());
613 for (VBridgeIfPath ifpath : ifpaths) {
614 VInterfaceConfig ifconf = new VInterfaceConfig(null, null);
615 st = mgr.addInterface(ifpath, ifconf);
616 assertTrue(st.isSuccess());
621 * remove and add specified node to add to {@code disabledNode}.
623 * @param mgr a {@link VTNManagerImpl} object.
624 * @param swmgr a {@link ISwitchManager} object.
625 * @param dnode a {@link Node} disabled.
627 private void addNode(VTNManagerImpl mgr, ISwitchManager swmgr, Node dnode) {
628 Map<String, Property> propMap = null;
629 mgr.notifyNode(dnode, UpdateType.REMOVED, propMap);
630 mgr.notifyNode(dnode, UpdateType.ADDED, propMap);
632 Set<NodeConnector> ncs = swmgr.getNodeConnectors(dnode);
633 for (NodeConnector nc : ncs) {
634 propMap = swmgr.getNodeConnectorProps(nc);
635 mgr.notifyNodeConnector(nc, UpdateType.ADDED, propMap);
641 * Wait for the PACKET_IN service on the specified node to be started.
643 * @param mgr VTN Manager service.
644 * @param node A {@link Node} instance.
646 private void waitFor(VTNManagerImpl mgr, Node node) {
647 final long timeout = System.currentTimeMillis() + 10000;
649 while (mgr.isDisabled(node)) {
652 } catch (InterruptedException e) {
656 if (System.currentTimeMillis() > timeout) {
657 fail("PACKET_IN service did not start: " + node);