static { FlowMod2 = new OFFlowMod(); TestRule2 = new HashMap<String, Object>(); TestRule2.put(COLUMN_NAME, "TestRule2"); TestRule2.put(COLUMN_SWITCH, TestSwitch1DPID); // setup match OFMatch match = new OFMatch(); TestRule2.put(COLUMN_NW_DST, "192.168.1.0/24"); match.fromString("nw_dst=192.168.1.0/24"); // setup actions List<OFAction> actions = new LinkedList<OFAction>(); TestRule2.put(COLUMN_ACTIONS, "output=1"); actions.add(new OFActionOutput((short) 1, (short) Short.MAX_VALUE)); // done FlowMod2.setMatch(match); FlowMod2.setActions(actions); FlowMod2.setBufferId(-1); FlowMod2.setOutPort(OFPort.OFPP_NONE.getValue()); FlowMod2.setPriority(Short.MAX_VALUE); FlowMod2.setLengthU(OFFlowMod.MINIMUM_LENGTH + 8); // 8 bytes of actions }
static { FlowMod3 = new OFFlowMod(); TestRule3 = new HashMap<String, Object>(); TestRule3.put(COLUMN_NAME, "TestRule3"); TestRule3.put(COLUMN_SWITCH, TestSwitch1DPID); // setup match OFMatch match = new OFMatch(); TestRule3.put(COLUMN_DL_DST, "00:20:30:40:50:60"); TestRule3.put(COLUMN_DL_VLAN, 4096); match.fromString("dl_dst=00:20:30:40:50:60,dl_vlan=4096"); // setup actions TestRule3.put(COLUMN_ACTIONS, "output=controller"); List<OFAction> actions = new LinkedList<OFAction>(); actions.add(new OFActionOutput(OFPort.OFPP_CONTROLLER.getValue(), (short) Short.MAX_VALUE)); // done FlowMod3.setMatch(match); FlowMod3.setActions(actions); FlowMod3.setBufferId(-1); FlowMod3.setOutPort(OFPort.OFPP_NONE.getValue()); FlowMod3.setPriority(Short.MAX_VALUE); FlowMod3.setLengthU(OFFlowMod.MINIMUM_LENGTH + 8); // 8 bytes of actions }
@Test public void testStaticFlowPush() throws IOException { StaticFlowEntryPusher staticFlowEntryPusher = new StaticFlowEntryPusher(); IStorageSourceService storage = createStorageWithFlowEntries(); long dpid = HexString.toLong(TestSwitch1DPID); // Create a Switch and attach a switch IOFSwitch mockSwitch = createNiceMock(IOFSwitch.class); Capture<OFMessage> writeCapture = new Capture<OFMessage>(CaptureType.ALL); Capture<ListenerContext> contextCapture = new Capture<ListenerContext>(CaptureType.ALL); Capture<List<OFMessage>> writeCaptureList = new Capture<List<OFMessage>>(CaptureType.ALL); // OFMessageSafeOutStream mockOutStream = createNiceMock(OFMessageSafeOutStream.class); mockSwitch.write(capture(writeCapture), capture(contextCapture)); expectLastCall().anyTimes(); mockSwitch.write(capture(writeCaptureList), capture(contextCapture)); expectLastCall().anyTimes(); mockSwitch.flush(); expectLastCall().anyTimes(); staticFlowEntryPusher.setStorageSource(storage); ModuleContext fmc = new ModuleContext(); MockControllerProvider mockControllerProvider = getMockControllerProvider(); Map<Long, IOFSwitch> switchMap = new HashMap<Long, IOFSwitch>(); switchMap.put(dpid, mockSwitch); // NO ! expect(mockControllerProvider.getSwitches()).andReturn(switchMap).anyTimes(); mockControllerProvider.setSwitches(switchMap); staticFlowEntryPusher.setControllerProvider(mockControllerProvider); RestApiServer restApi = new RestApiServer(); try { restApi.init(fmc); } catch (ModuleException e) { e.printStackTrace(); } staticFlowEntryPusher.restApi = restApi; staticFlowEntryPusher.startUp(null); // again, to hack unittest // verify that flowpusher read all three entries from storage assertEquals(TotalTestRules, staticFlowEntryPusher.countEntries()); // if someone calls mockSwitch.getOutputStream(), return mockOutStream instead // expect(mockSwitch.getOutputStream()).andReturn(mockOutStream).anyTimes(); // if someone calls getId(), return this dpid instead expect(mockSwitch.getId()).andReturn(dpid).anyTimes(); expect(mockSwitch.getStringId()).andReturn(TestSwitch1DPID).anyTimes(); replay(mockSwitch); // hook the static pusher up to the fake switch staticFlowEntryPusher.addedSwitch(mockSwitch); verify(mockSwitch); // Verify that the switch has gotten some flow_mods assertEquals(true, writeCapture.hasCaptured()); assertEquals(TotalTestRules, writeCapture.getValues().size()); // Order assumes how things are stored in hash bucket; // should be fixed because OFMessage.hashCode() is deterministic OFFlowMod firstFlowMod = (OFFlowMod) writeCapture.getValues().get(2); verifyFlowMod(firstFlowMod, FlowMod1); OFFlowMod secondFlowMod = (OFFlowMod) writeCapture.getValues().get(1); verifyFlowMod(secondFlowMod, FlowMod2); OFFlowMod thirdFlowMod = (OFFlowMod) writeCapture.getValues().get(0); verifyFlowMod(thirdFlowMod, FlowMod3); writeCapture.reset(); contextCapture.reset(); // delete two rules and verify they've been removed // this should invoke staticFlowPusher.rowsDeleted() storage.deleteRow(StaticFlowEntryPusher.TABLE_NAME, "TestRule1"); storage.deleteRow(StaticFlowEntryPusher.TABLE_NAME, "TestRule2"); assertEquals(1, staticFlowEntryPusher.countEntries()); assertEquals(2, writeCapture.getValues().size()); OFFlowMod firstDelete = (OFFlowMod) writeCapture.getValues().get(0); FlowMod1.setCommand(OFFlowMod.OFPFC_DELETE_STRICT); verifyFlowMod(firstDelete, FlowMod1); OFFlowMod secondDelete = (OFFlowMod) writeCapture.getValues().get(1); FlowMod2.setCommand(OFFlowMod.OFPFC_DELETE_STRICT); verifyFlowMod(secondDelete, FlowMod2); // add rules back to make sure that staticFlowPusher.rowsInserted() works writeCapture.reset(); FlowMod2.setCommand(OFFlowMod.OFPFC_ADD); storage.insertRow(StaticFlowEntryPusher.TABLE_NAME, TestRule2); assertEquals(2, staticFlowEntryPusher.countEntries()); assertEquals(1, writeCaptureList.getValues().size()); List<OFMessage> outList = (List<OFMessage>) writeCaptureList.getValues().get(0); assertEquals(1, outList.size()); OFFlowMod firstAdd = (OFFlowMod) outList.get(0); verifyFlowMod(firstAdd, FlowMod2); writeCapture.reset(); contextCapture.reset(); writeCaptureList.reset(); // now try an overwriting update, calling staticFlowPusher.rowUpdated() TestRule3.put(COLUMN_DL_VLAN, 333); storage.updateRow(StaticFlowEntryPusher.TABLE_NAME, TestRule3); assertEquals(2, staticFlowEntryPusher.countEntries()); assertEquals(1, writeCaptureList.getValues().size()); outList = (List<OFMessage>) writeCaptureList.getValues().get(0); assertEquals(2, outList.size()); OFFlowMod removeFlowMod = (OFFlowMod) outList.get(0); FlowMod3.setCommand(OFFlowMod.OFPFC_DELETE_STRICT); verifyFlowMod(removeFlowMod, FlowMod3); FlowMod3.setCommand(OFFlowMod.OFPFC_ADD); FlowMod3.getMatch().fromString("dl_dst=00:20:30:40:50:60,dl_vlan=333"); OFFlowMod updateFlowMod = (OFFlowMod) outList.get(1); verifyFlowMod(updateFlowMod, FlowMod3); writeCaptureList.reset(); // now try an action modifying update, calling staticFlowPusher.rowUpdated() TestRule3.put(COLUMN_ACTIONS, "output=controller,strip-vlan"); // added strip-vlan storage.updateRow(StaticFlowEntryPusher.TABLE_NAME, TestRule3); assertEquals(2, staticFlowEntryPusher.countEntries()); assertEquals(1, writeCaptureList.getValues().size()); outList = (List<OFMessage>) writeCaptureList.getValues().get(0); assertEquals(1, outList.size()); OFFlowMod modifyFlowMod = (OFFlowMod) outList.get(0); FlowMod3.setCommand(OFFlowMod.OFPFC_MODIFY_STRICT); List<OFAction> modifiedActions = FlowMod3.getActions(); modifiedActions.add( new OFActionStripVirtualLan()); // add the new action to what we should expect FlowMod3.setActions(modifiedActions); FlowMod3.setLengthU(OFFlowMod.MINIMUM_LENGTH + 16); // accommodate the addition of new actions verifyFlowMod(modifyFlowMod, FlowMod3); }
@Override public void addedSwitch(IOFSwitch sw) { /** * Insert static flows on all ports of the switch to redirect DHCP client --> DHCP DHCPServer * traffic to the controller. DHCP client's operate on UDP port 67 */ OFFlowMod flow = new OFFlowMod(); OFMatch match = new OFMatch(); ArrayList<OFAction> actionList = new ArrayList<OFAction>(); OFActionOutput action = new OFActionOutput(); String flowName; if (sw.getStringId().equals(ROOT_NODE_WIFI_OVS_DPID)) { // root node, WiFi bridge, patch to tunnel port flow = new OFFlowMod(); match = new OFMatch(); match.setInputPort(ROOT_NODE_WIFI_OVS_PATCH); action.setType(OFActionType.OUTPUT); action.setPort(ROOT_NODE_WIFI_OVS_TUNNEL); action.setLength((short) OFActionOutput.MINIMUM_LENGTH); actionList.add(action); flow.setCookie(0); flow.setBufferId(-1); flow.setOutPort(ROOT_NODE_WIFI_OVS_TUNNEL); flow.setActions(actionList); flow.setMatch(match); flow.setPriority(PRIORITY_HIGH); flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); flowName = "root-node-wifi-br-patch-tun"; sfp.addFlow(flowName, flow, sw.getStringId()); log.info("added flow on SW " + sw.getStringId() + flowName); actionList.clear(); // root node, WiFi bridge, physical to patch flow = new OFFlowMod(); match = new OFMatch(); match.setInputPort(ROOT_NODE_WIFI_OVS_TUNNEL); action.setType(OFActionType.OUTPUT); action.setPort(ROOT_NODE_WIFI_OVS_PATCH); action.setLength((short) OFActionOutput.MINIMUM_LENGTH); actionList.add(action); flow.setCookie(0); flow.setBufferId(-1); flow.setOutPort(ROOT_NODE_WIFI_OVS_PATCH); flow.setActions(actionList); flow.setMatch(match); flow.setPriority(PRIORITY_HIGH); flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); flowName = "root-node-wifi-br-tun-patch"; sfp.addFlow(flowName, flow, sw.getStringId()); log.info("added flow on SW " + sw.getStringId() + flowName); actionList.clear(); } else if (sw.getStringId().equals(ROOT_NODE_WIMAX_OVS_DPID)) { // root node, WiMAX bridge, patch to physical flow = new OFFlowMod(); match = new OFMatch(); match.setInputPort(ROOT_NODE_WIMAX_OVS_PATCH); action.setType(OFActionType.OUTPUT); action.setPort(ROOT_NODE_WIMAX_OVS_VLAN); action.setLength((short) OFActionOutput.MINIMUM_LENGTH); actionList.add(action); flow.setCookie(0); flow.setBufferId(-1); flow.setOutPort(ROOT_NODE_WIMAX_OVS_VLAN); flow.setActions(actionList); flow.setMatch(match); flow.setPriority(PRIORITY_HIGH); flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); flowName = "root-node-wimax-br-patch-phys"; sfp.addFlow(flowName, flow, sw.getStringId()); log.info("added flow on SW " + sw.getStringId() + flowName); actionList.clear(); // root node, WiMAX bridge, interface to patch flow = new OFFlowMod(); match = new OFMatch(); match.setInputPort(ROOT_NODE_WIMAX_OVS_VLAN); action.setType(OFActionType.OUTPUT); action.setPort(ROOT_NODE_WIMAX_OVS_PATCH); action.setLength((short) OFActionOutput.MINIMUM_LENGTH); actionList.add(action); flow.setCookie(0); flow.setBufferId(-1); flow.setOutPort(ROOT_NODE_WIMAX_OVS_PATCH); flow.setActions(actionList); flow.setMatch(match); flow.setPriority(PRIORITY_HIGH); flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); flowName = "root-node-wimax-br-phys-patch"; sfp.addFlow(flowName, flow, sw.getStringId()); log.info("added flow on SW " + sw.getStringId() + flowName); actionList.clear(); // root node, WiMAX bridge, DHCP on physical match.setInputPort(ROOT_NODE_WIMAX_OVS_VLAN); match.setDataLayerType(Ethernet.TYPE_IPv4); match.setNetworkProtocol(IPv4.PROTOCOL_UDP); match.setTransportSource(UDP.DHCP_CLIENT_PORT); action.setType(OFActionType.OUTPUT); action.setLength((short) OFActionOutput.MINIMUM_LENGTH); action.setPort(OFPort.OFPP_CONTROLLER.getValue()); actionList.add(action); flow.setCookie(0); flow.setBufferId(-1); flow.setOutPort(OFPort.OFPP_CONTROLLER.getValue()); flow.setActions(actionList); flow.setMatch(match); flow.setPriority(PRIORITY_MAX); flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); flowName = "root-node-wimax-br-DHCP-phys"; sfp.addFlow(flowName, flow, sw.getStringId()); log.info("added flow on SW " + sw.getStringId() + flowName); actionList.clear(); } else if (sw.getStringId().equals(ROOT_NODE_ROOT_OVS_DPID)) { // root node, root bridge, patch AP3 (WiFi) to Linux flow = new OFFlowMod(); match = new OFMatch(); match.setInputPort(ROOT_NODE_ROOT_OVS_WIFI_PATCH); action.setType(OFActionType.OUTPUT); action.setPort(OFPort.OFPP_LOCAL.getValue()); action.setLength((short) OFActionOutput.MINIMUM_LENGTH); actionList.add(action); flow.setCookie(0); flow.setBufferId(-1); flow.setOutPort(OFPort.OFPP_LOCAL.getValue()); flow.setActions(actionList); flow.setMatch(match); flow.setPriority(PRIORITY_HIGH); flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); flowName = "root-node-root-br-patchWiFi-linux"; sfp.addFlow(flowName, flow, sw.getStringId()); log.info("added flow on SW " + sw.getStringId() + flowName); actionList.clear(); // root node, root bridge, patch WiMAX to Linux flow = new OFFlowMod(); match = new OFMatch(); match.setInputPort(ROOT_NODE_ROOT_OVS_WIMAX_PATCH); action.setType(OFActionType.OUTPUT); action.setPort(OFPort.OFPP_LOCAL.getValue()); action.setLength((short) OFActionOutput.MINIMUM_LENGTH); actionList.add(action); flow.setCookie(0); flow.setBufferId(-1); flow.setOutPort(OFPort.OFPP_LOCAL.getValue()); flow.setActions(actionList); flow.setMatch(match); flow.setPriority(PRIORITY_HIGH); flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); flowName = "root-node-root-br-patchWiMAX-linux"; sfp.addFlow(flowName, flow, sw.getStringId()); log.info("added flow on SW " + sw.getStringId() + flowName); actionList.clear(); // root node, root bridge, physical to Linux // flow = new OFFlowMod(); // match = new OFMatch(); // match.setInputPort((short) 1); // action.setType(OFActionType.OUTPUT); // action.setPort(OFPort.OFPP_LOCAL.getValue()); // action.setLength((short) OFActionOutput.MINIMUM_LENGTH); // actionList.add(action); // flow.setCookie(0); // flow.setBufferId(-1); // flow.setOutPort(OFPort.OFPP_LOCAL.getValue()); // flow.setActions(actionList); // flow.setMatch(match); // flow.setPriority(PRIORITY_HIGH); // flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); // flowName = "root-ovs-root-br-phys-linux"; // sfp.addFlow(flowName, flow, sw.getStringId()); // log.info("added flow on SW " + sw.getStringId() + flowName); // actionList.clear(); // root node, root bridge, Linux to physical (match extra: src-ip of root node...i.e. it's // outbound) // flow = new OFFlowMod(); // match = new OFMatch(); // match.setInputPort(OFPort.OFPP_LOCAL.getValue()); // match.setDataLayerType(Ethernet.TYPE_IPv4); // ... IP packets ... required for a match on // an IP address // match.setNetworkSource(ROOT_NODE_ROOT_OVS_IP); // action.setType(OFActionType.OUTPUT); // action.setPort((short) 1); // action.setLength((short) OFActionOutput.MINIMUM_LENGTH); // actionList.add(action); // flow.setCookie(0); // flow.setBufferId(-1); // flow.setOutPort((short) 1); // flow.setActions(actionList); // flow.setMatch(match); // flow.setPriority(PRIORITY_HIGH); // flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); // flowName = "root-ovs-root-br-linux-phys-egress"; // sfp.addFlow(flowName, flow, sw.getStringId()); // log.info("added flow on SW " + sw.getStringId() + flowName); // actionList.clear(); } else if (sw.getStringId().equals(WIFI_NODE_WIFI_OVS_DPID)) { // WiFi node, WiFi bridge, physical to patch flow = new OFFlowMod(); match = new OFMatch(); match.setInputPort((short) 1); action.setType(OFActionType.OUTPUT); action.setPort(WIFI_NODE_WIFI_OVS_PATCH); action.setLength((short) OFActionOutput.MINIMUM_LENGTH); actionList.add(action); flow.setCookie(0); flow.setBufferId(-1); flow.setOutPort(WIFI_NODE_WIFI_OVS_PATCH); flow.setActions(actionList); flow.setMatch(match); flow.setPriority(PRIORITY_HIGH); flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); flowName = "wifi-node-wifi-br-phys-patch"; sfp.addFlow(flowName, flow, sw.getStringId()); log.info("added flow on SW " + sw.getStringId() + flowName); actionList.clear(); // WiFi node, WiFi bridge, patch to physical flow = new OFFlowMod(); match = new OFMatch(); match.setInputPort(WIFI_NODE_WIFI_OVS_PATCH); action.setType(OFActionType.OUTPUT); action.setPort((short) 1); action.setLength((short) OFActionOutput.MINIMUM_LENGTH); actionList.add(action); flow.setCookie(0); flow.setBufferId(-1); flow.setOutPort((short) 1); flow.setActions(actionList); flow.setMatch(match); flow.setPriority(PRIORITY_HIGH); flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); flowName = "wifi-node-wifi-br-patch-phys"; sfp.addFlow(flowName, flow, sw.getStringId()); log.info("added flow on SW " + sw.getStringId() + flowName); actionList.clear(); // root node, WiMAX bridge, DHCP on physical match.setInputPort((short) 1); match.setDataLayerType(Ethernet.TYPE_IPv4); match.setNetworkProtocol(IPv4.PROTOCOL_UDP); match.setTransportSource(UDP.DHCP_CLIENT_PORT); action.setType(OFActionType.OUTPUT); action.setLength((short) OFActionOutput.MINIMUM_LENGTH); action.setPort(OFPort.OFPP_CONTROLLER.getValue()); actionList.add(action); flow.setCookie(0); flow.setBufferId(-1); flow.setOutPort(OFPort.OFPP_CONTROLLER.getValue()); flow.setActions(actionList); flow.setMatch(match); flow.setPriority(PRIORITY_MAX); flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); flowName = "wifi-node-wifi-br-DHCP-phys"; sfp.addFlow(flowName, flow, sw.getStringId()); log.info("added flow on SW " + sw.getStringId() + flowName); actionList.clear(); } else if (sw.getStringId().equals(WIFI_NODE_TUNNEL_OVS_DPID)) { // WiFi node, tunnel bridge, tunnel to patch flow = new OFFlowMod(); match = new OFMatch(); match.setInputPort(WIFI_NODE_TUNNEL_OVS_TUNNEL); action.setType(OFActionType.OUTPUT); action.setPort(WIFI_NODE_TUNNEL_OVS_PATCH); action.setLength((short) OFActionOutput.MINIMUM_LENGTH); actionList.add(action); flow.setCookie(0); flow.setBufferId(-1); flow.setOutPort(WIFI_NODE_TUNNEL_OVS_PATCH); flow.setActions(actionList); flow.setMatch(match); flow.setPriority(PRIORITY_HIGH); flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); flowName = "wifi-node-tunnel-br-tun-patch"; sfp.addFlow(flowName, flow, sw.getStringId()); log.info("added flow on SW " + sw.getStringId() + flowName); actionList.clear(); // WiFi node, tunnel bridge, patch to tunnel flow = new OFFlowMod(); match = new OFMatch(); match.setInputPort(WIFI_NODE_TUNNEL_OVS_PATCH); action.setType(OFActionType.OUTPUT); action.setPort(WIFI_NODE_TUNNEL_OVS_TUNNEL); action.setLength((short) OFActionOutput.MINIMUM_LENGTH); actionList.add(action); flow.setCookie(0); flow.setBufferId(-1); flow.setOutPort(WIFI_NODE_TUNNEL_OVS_TUNNEL); flow.setActions(actionList); flow.setMatch(match); flow.setPriority(PRIORITY_HIGH); flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU()); flowName = "wifi-node-tunnel-br-patch-tun"; sfp.addFlow(flowName, flow, sw.getStringId()); log.info("added flow on SW " + sw.getStringId() + flowName); actionList.clear(); } }