private void updatePortList() { ArrayList<Short> addedPorts = new ArrayList<Short>(); ArrayList<Short> removedPorts = new ArrayList<Short>(); synchronized (FVConfig.class) { // update our local copy this.localFlowSpace = getLocalFlowSpace(); } Set<Short> ports = FlowSpaceUtil.getPortsBySlice( this.fvClassifier.getSwitchInfo().getDatapathId(), this.sliceName, this.localFlowSpace); if (ports.contains(OFPort.OFPP_ALL.getValue())) { // this switch has access to ALL PORTS; feed them in from the // features request ports.clear(); // remove the OFPP_ALL virtual port this.allowAllPorts = true; for (OFPhysicalPort phyPort : this.fvClassifier.getSwitchInfo().getPorts()) ports.add(phyPort.getPortNumber()); } for (Short port : ports) { if (!allowedPorts.keySet().contains(port)) { FVLog.log(LogLevel.DEBUG, this, "adding access to port ", port); allowedPorts.put(port, Boolean.TRUE); addedPorts.add(port); } } for (Iterator<Short> it = allowedPorts.keySet().iterator(); it.hasNext(); ) { Short port = it.next(); if (!ports.contains(port)) { FVLog.log(LogLevel.DEBUG, this, "removing access to port ", port); it.remove(); removedPorts.add(port); } } updatePortStatus(addedPorts, removedPorts); }
private void reconnect() { FVLog.log(LogLevel.INFO, this, "trying to reconnect to ", this.hostname, ":", this.port); // reset our state to unconnected (might be a NOOP) this.isConnected = false; this.msgStream = null; // try to connect socket to controller try { if (this.sock != null) // note that this automatically unregisters from selector this.sock.close(); this.sock = SocketChannel.open(); sock.configureBlocking(false); // set to non-blocking InetSocketAddress addr = new InetSocketAddress(hostname, port); if (addr.isUnresolved()) { FVLog.log(LogLevel.INFO, this, "retrying: failed to resolve hostname: ", hostname); this.reconnectLater(); return; } this.isConnected = this.sock.connect(addr); // try to connect // register into event loop this.loop.register(this.sock, SelectionKey.OP_CONNECT, this); } catch (IOException e) { FVLog.log(LogLevel.CRIT, this, "Trying to reconnect; trying later; got : ", e); this.reconnectLater(); } }
/** The topologyController handles LLDP messages and ignores everything else */ @Override public void topologyController(TopologyConnection topologyConnection) { synchronized (topologyConnection) { DPIDandPort dpidandport = TopologyConnection.parseLLDP(this.getPacketData()); if (dpidandport == null) { FVLog.log( LogLevel.DEBUG, topologyConnection, "ignoring non-lldp packetin: " + this.toVerboseString()); return; } OFFeaturesReply featuresReply = topologyConnection.getFeaturesReply(); if (featuresReply == null) { FVLog.log(LogLevel.WARN, topologyConnection, "ignoring packet_in: no features_reply yet"); return; } LinkAdvertisement linkAdvertisement = new LinkAdvertisement( dpidandport.getDpid(), dpidandport.getPort(), featuresReply.getDatapathId(), this.inPort); topologyConnection.getTopologyController().reportProbe(linkAdvertisement); topologyConnection.signalFastPort(this.inPort); } }
@Override public List<String> listDevices() { FVLog.log(LogLevel.DEBUG, null, "API listDevices() by: " + APIUserCred.getUserName()); FlowVisor fv = FlowVisor.getInstance(); // get list from main flowvisor instance List<String> dpids = new ArrayList<String>(); String dpidStr; /* * if (TopologyController.isConfigured()) { for (Long dpid : * TopologyController.getRunningInstance() .listDevices()) { dpidStr = * HexString.toHexString(dpid); if (!dpids.contains(dpidStr)) * dpids.add(dpidStr); else FVLog.log(LogLevel.WARN, TopologyController * .getRunningInstance(), "duplicate dpid detected: " + dpidStr); } } * else { */ // only list a device is we have a features reply for it for (FVEventHandler handler : fv.getHandlersCopy()) { if (handler instanceof FVClassifier) { OFFeaturesReply featuresReply = ((FVClassifier) handler).getSwitchInfo(); if (featuresReply != null) { dpidStr = FlowSpaceUtil.dpidToString(featuresReply.getDatapathId()); if (!dpids.contains(dpidStr)) dpids.add(dpidStr); else FVLog.log(LogLevel.WARN, handler, "duplicate dpid detected: " + dpidStr); } } } // } return dpids; }
public void init() { FVLog.log(LogLevel.DEBUG, this, "initializing new FVSlicer"); // snag controller info from config try { hostname = FVConfig.getSliceHost(sliceName); port = FVConfig.getSlicePort(sliceName); lldpOptIn = FVConfig.getLLDPSpam(sliceName); SliceImpl.addListener(sliceName, this); } catch (ConfigError e) { FVLog.log( LogLevel.CRIT, this, "ignoring slice ", sliceName, " malformed slice definition: ", e); this.tearDown(); return; } this.updatePortList(); this.reconnect(); this.keepAlive = new OFKeepAlive(this, this, loop); this.keepAlive.scheduleNextCheck(); fvClassifier.loadLimit(sliceName); fvClassifier.loadRateLimit(sliceName); try { this.fmlimit = SliceImpl.getProxy().getMaxFlowMods(sliceName); } catch (ConfigError e) { FVLog.log(LogLevel.WARN, this, "Global slice flow mod limit unreadable; disabling."); this.fmlimit = -1; } }
@Override public void removeRule(int id) throws ConfigError { Connection conn = null; PreparedStatement ps = null; try { conn = settings.getConnection(); ps = conn.prepareStatement(DFLOWRULE); ps.setInt(1, id); int affected = -1; if ((affected = ps.executeUpdate()) != 1) { FVLog.log( LogLevel.ALERT, null, "Failed to delete rule with id ", id, " : rows affected ", affected); throw new ConfigError("Unable to remove rule with id " + id); } } catch (SQLException e) { FVLog.log(LogLevel.DEBUG, null, e.getMessage()); throw new ConfigError("Unable to remove rule with id " + id); } finally { close(ps); close(conn); } }
@Override public Boolean getFlowTracking() throws PermissionDeniedException { String user = APIUserCred.getUserName(); if (!FVConfig.isSupervisor(user)) throw new PermissionDeniedException( "User " + user + " does not have perms to obtain flow tracking status"); FVLog.log(LogLevel.DEBUG, null, "Getting flow tracking status"); try { return FlowvisorImpl.getProxy().gettrack_flows(); } catch (ConfigError e) { FVLog.log(LogLevel.ALERT, null, "Unable to get flow tracking status ", e.getMessage()); } return null; }
private void handleKeepAlive(FVEvent e) { if (!this.keepAlive.isAlive()) { FVLog.log(LogLevel.WARN, this, "keepAlive timeout; trying to reconnnect later"); try { if (this.sock != null) this.sock.close(); } catch (IOException e1) { FVLog.log(LogLevel.WARN, this, "ignoring error while closing socket: ", e1); } this.reconnectLater(); return; } this.keepAlive.sendPing(); this.keepAlive.scheduleNextCheck(); }
private void reconnectLater() { if (this.sock != null) try { this.sock.close(); this.sock = null; this.isConnected = false; HashMap<String, Object> info = this.getStatusInfo(); TopologyController tc = TopologyController.getRunningInstance(); if (tc != null) tc.sliceConnectionJustChanged(info, TopologyCallback.EventType.SLICE_DISCONNECTED); /* * Place slice connection callback here */ } catch (IOException e) { FVLog.log(LogLevel.WARN, this, "ignoring error closing socket: ", e); } if (this.reconnectEventScheduled) { // Don't schedule another reconnect, one's already in there return; } // exponential back off this.reconnectSeconds = Math.min(2 * this.reconnectSeconds + 1, this.maxReconnectSeconds); this.loop.addTimer(new ReconnectEvent(this.reconnectSeconds, this)); this.reconnectEventScheduled = true; }
@Override public String getFloodPerm(String dpidStr) throws PermissionDeniedException { String user = APIUserCred.getUserName(); if (!FVConfig.isSupervisor(user)) throw new PermissionDeniedException( "User " + user + " does not have perms to obtain the flood perms of " + dpidStr); FVLog.log(LogLevel.DEBUG, null, "Setting flood perm for : ", dpidStr); long dpid = FlowSpaceUtil.parseDPID(dpidStr); try { return SwitchImpl.getProxy().getFloodPerm(dpid); } catch (ConfigError e) { FVLog.log(LogLevel.ALERT, null, "Unable to set floodperm", e.getMessage()); } return null; }
@Override public boolean setMaximumFlowMods(String sliceName, String dpid, String maxFlowMods) throws PermissionDeniedException { String user = APIUserCred.getUserName(); if (!APIAuth.transitivelyCreated(user, sliceName) && !FVConfig.isSupervisor(user)) throw new PermissionDeniedException( "User " + user + " does not have perms to set the flow mod limit for slice " + sliceName); Long dp = FlowSpaceUtil.parseDPID(dpid); int limit = Integer.parseInt(maxFlowMods); FVLog.log( LogLevel.DEBUG, null, "Setting flowmod limit for slice " + sliceName + " for dpid " + dpid + " to " + maxFlowMods); try { if (dp == FlowEntry.ALL_DPIDS) SliceImpl.getProxy().setMaxFlowMods(sliceName, limit); else SwitchImpl.getProxy().setMaxFlowMods(sliceName, dp, limit); } catch (ConfigError e) { return false; } return true; }
public void closeDown(boolean unregisterClassifier) { FVLog.log(LogLevel.DEBUG, this, "tearing down"); this.isShutdown = true; this.loop.unregister(this.sock, this); if (this.sock != null) { try { this.sock.close(); // FIXME will this also cancel() the key in // the event loop? } catch (IOException e) { // ignore if error... we're shutting down already } } // tell the classifier to forget about us if (unregisterClassifier) fvClassifier.tearDownSlice(this.sliceName); this.msgStream = null; // force this to GC, in case we have a memleak on // "this" HashMap<String, Object> info = this.getStatusInfo(); TopologyController tc = TopologyController.getRunningInstance(); if (tc != null) tc.sliceConnectionJustChanged(info, TopologyCallback.EventType.SLICE_DISCONNECTED); SliceImpl.removeListener(sliceName, this); FlowvisorImpl.removeListener(this); }
/** * Tell the classifier to drop packets that look like this * * @param fvClassifier * @param flowEntry * @param hardTimeout * @param idleTimeout */ private void sendDropRule( FVClassifier fvClassifier, FlowEntry flowEntry, String sliceName, short hardTimeout, short idleTimeout) { FVFlowMod flowMod = (FVFlowMod) FlowVisor.getInstance().getFactory().getMessage(OFType.FLOW_MOD); // block this exact flow OFMatch match = new OFMatch(); match.loadFromPacket(this.packetData, this.inPort); // different from previous policty of block by rule // flowMod.setMatch(flowEntry.getRuleMatch()); String drop_policy = null; try { drop_policy = FVConfig.getDropPolicy(sliceName); } catch (ConfigError e) { FVLog.log( LogLevel.ALERT, fvClassifier, "Failed to retrieve drop policy from config." + "\nDefauting to exact drop_policy"); drop_policy = "exact"; } if (drop_policy.equals("exact")) flowMod.setMatch(match); else if (drop_policy.equals("rule")) flowMod.setMatch(flowEntry.getRuleMatch()); else // Should never happen FVLog.log(LogLevel.CRIT, fvClassifier, "Error in configuration!"); flowMod.setCommand(FVFlowMod.OFPFC_ADD); flowMod.setActions(new LinkedList<OFAction>()); // send to zero-length // list, i.e., DROP flowMod.setLengthU(OFFlowMod.MINIMUM_LENGTH); flowMod.setHardTimeout(hardTimeout); flowMod.setIdleTimeout(idleTimeout); flowMod.setPriority((short) 0); // set to lowest priority flowMod.setFlags((short) 1); // send removed msg (1), not the check overlap (2), or // emergency flow cache (4) FVLog.log( LogLevel.WARN, fvClassifier, "inserting drop (hard=" + hardTimeout + ",idle=" + idleTimeout + ") rule for " + flowEntry); fvClassifier.sendMsg(flowMod, fvClassifier); }
protected Collection<FlowEntry> getFlowEntries() throws ConfigError { String sliceName = APIUserCred.getUserName(); FVLog.log(LogLevel.DEBUG, null, "API listFlowSpace() by: " + sliceName); FlowMap flowMap; synchronized (FVConfig.class) { if (FVConfig.isSupervisor(sliceName)) flowMap = FVConfig.getFlowSpaceFlowMap(); else flowMap = FlowSpaceUtil.getSliceFlowSpace(sliceName); return flowMap.getRules(); } }
@Override public Map<String, String> getSliceInfo(String sliceName) throws PermissionDeniedException, SliceNotFound { /* * relaxed security -- anyone can read slice info for now String user = * APIUserCred.getUserName(); if (!FVConfig.isSupervisor(user) && * !APIAuth.transitivelyCreated(user, sliceName)) throw new * PermissionDeniedException( * "not superuser or transitive slice creator"); */ if (!(doesSliceExist(sliceName))) { throw new SliceNotFound("Slice does not exist: " + sliceName); } HashMap<String, String> map = new HashMap<String, String>(); synchronized (FVConfig.class) { try { map.put("contact_email", FVConfig.getSliceEmail(sliceName)); map.put("controller_hostname", FVConfig.getSliceHost(sliceName)); map.put("controller_port", String.valueOf(FVConfig.getSlicePort(sliceName))); map.put("creator", FVConfig.getSliceCreator(sliceName)); map.put("drop_policy", FVConfig.getSlicePolicy(sliceName)); } catch (ConfigError e) { FVLog.log(LogLevel.CRIT, null, "malformed slice: " + e); e.printStackTrace(); } } long dpid; int connection = 1; // TODO: come back an architect this so we can walk the list of slicers, // not the list of classifiers, and then slicers for (Iterator<FVEventHandler> it = FlowVisor.getInstance().getHandlersCopy().iterator(); it.hasNext(); ) { FVEventHandler eventHandler = it.next(); if (eventHandler instanceof FVClassifier) { FVClassifier classifier = (FVClassifier) eventHandler; if (!classifier.isIdentified()) // only print switches have have // been identified continue; dpid = classifier.getDPID(); FVSlicer fvSlicer = classifier.getSlicerByName(sliceName); if (fvSlicer != null) { map.put( "connection_" + connection++, FlowSpaceUtil.dpidToString(dpid) + "-->" + fvSlicer.getConnectionName()); } } } return map; }
private HashMap<String, Object> getStatusInfo() { HashMap<String, Object> info = new HashMap<String, Object>(); info.put("connection-status", this.isConnected()); info.put("slice-name", this.sliceName); info.put("controller-host", this.hostname); info.put("controller-port", this.port); info.put("shutdown-status", this.isShutdown); info.put("floodperms", this.floodPerms); FVLog.log(LogLevel.DEBUG, this, "FVSlicer StatusInfo: " + info); return info; }
private void sendPortStatusUpdate(OFPhysicalPort phyPort, boolean added) { FVPortStatus portStatus = new FVPortStatus(); portStatus.setDesc(phyPort); portStatus.setReason( added ? (byte) OFPortReason.OFPPR_ADD.ordinal() : (byte) OFPortReason.OFPPR_DELETE.ordinal()); FVLog.log( LogLevel.INFO, this, (added ? "added " : "removed ") + "port " + phyPort.getPortNumber()); sendMsg(portStatus, this); }
@Override public Boolean deleteSlice(String sliceName) throws SliceNotFound, PermissionDeniedException, ConfigError { String changerSlice = APIUserCred.getUserName(); if (!APIAuth.transitivelyCreated(changerSlice, sliceName)) { FVLog.log( LogLevel.WARN, null, "API deletSlice(" + sliceName + ") failed by: " + APIUserCred.getUserName()); throw new PermissionDeniedException( "Slice " + changerSlice + " does not have perms to change the passwd of " + sliceName); } synchronized (FVConfig.class) { FVLog.log( LogLevel.DEBUG, null, "API removeSlice(" + sliceName + ") by: " + APIUserCred.getUserName()); FlowMap flowSpace = FlowSpaceUtil.deleteFlowSpaceBySlice(sliceName); try { // this is also synchronized against FVConfig.class FVConfig.deleteSlice(sliceName); } catch (Exception e) { throw new SliceNotFound("slice does not exist: " + sliceName); } /* * We need to do this because of the linear flowmap, because * it wants the slicers and classifiers to update their * view of the flowspace. * Once linearflowmap is dropped, this should be dropped as * well. * * FIXME */ FlowSpaceImpl.getProxy().notifyChange(flowSpace); // FVConfig.sendUpdates(FVConfig.FLOWSPACE); // signal that FS has changed FlowVisor.getInstance().checkPointConfig(); } return true; }
public synchronized HashMap<Integer, ArrayList<Integer>> getPrioSetRange() { FVLog.log(LogLevel.DEBUG, null, "prioSet: ", prioSet); Set<Integer> prios = prioSet.keySet(); Integer pSize = prioSet.size(); Integer range = 65536 / pSize; HashMap<Integer, ArrayList<Integer>> prioRange = new HashMap<Integer, ArrayList<Integer>>(); Short index = 0; for (Integer prio : prios) { index++; Integer rangeEnd = (index * range) - 1; Integer rangeStart = rangeEnd - range + 1; ArrayList<Integer> pRange = new ArrayList<Integer>(); pRange.add(rangeStart); pRange.add(rangeEnd); prioRange.put(prio, pRange); } FVLog.log(LogLevel.DEBUG, null, "prioRange: ", prioRange); return prioRange; }
@Override public Boolean setFlowTracking(String flowtracking) throws PermissionDeniedException { String user = APIUserCred.getUserName(); if (!FVConfig.isSupervisor(user)) throw new PermissionDeniedException( "User " + user + " does not have perms to enable or disable flow tracking"); boolean track = Boolean.parseBoolean(flowtracking); FVLog.log( LogLevel.DEBUG, null, "Setting flow tracking to " + (track ? "enabled." : "disabled.")); FlowvisorImpl.getProxy().settrack_flows(track); return true; }
@Override public void sendMsg(OFMessage msg, FVSendMsg from) { if (this.msgStream != null) { FVLog.log(LogLevel.DEBUG, this, "send to controller: ", msg); try { this.msgStream.testAndWrite(msg); } catch (BufferFull e) { FVLog.log( LogLevel.CRIT, this, "buffer full: tearing down: got ", e, ": resetting connection"); this.reconnectLater(); } catch (MalformedOFMessage e) { this.stats.increment(FVStatsType.DROP, from, msg); FVLog.log(LogLevel.CRIT, this, "BUG: ", e); } catch (IOException e) { FVLog.log(LogLevel.WARN, this, "reconnection; got IO error: ", e); this.reconnectLater(); } } else { this.stats.increment(FVStatsType.DROP, from, msg); FVLog.log(LogLevel.WARN, this, "dropping msg: controller not connected: ", msg); } }
/** * For now, create a circular, bidirectional loop between existing switches FIXME need to actually * infer and calc real topology */ @Override public Collection<Map<String, String>> getLinks() { FVLog.log(LogLevel.DEBUG, null, "API getLinks() by: " + APIUserCred.getUserName()); TopologyController topologyController = TopologyController.getRunningInstance(); if (topologyController == null) return getFakeLinks(); List<Map<String, String>> list = new LinkedList<Map<String, String>>(); for (Iterator<LinkAdvertisement> it = topologyController.getLinks().iterator(); it.hasNext(); ) { LinkAdvertisement linkAdvertisement = it.next(); list.add(linkAdvertisement.toMap()); } return list; }
/* * (non-Javadoc) * * @see * org.flowvisor.events.FVEventHandler#handleEvent(org.flowvisor.events. * FVEvent) */ @Override public void handleEvent(FVEvent e) throws UnhandledEvent { if (isShutdown) { FVLog.log(LogLevel.WARN, this, "is shutdown; ignoring: " + e); return; // don't process any events after shutdown } if (e instanceof FVIOEvent) handleIOEvent((FVIOEvent) e); else if (e instanceof OFKeepAlive) handleKeepAlive(e); else if (e instanceof ReconnectEvent) { this.reconnectEventScheduled = false; this.reconnect(); } else if (e instanceof TearDownEvent) this.tearDown(); else throw new UnhandledEvent(e); }
@Override public Boolean setFloodPerm(String floodPerm) throws PermissionDeniedException { String user = APIUserCred.getUserName(); if (!FVConfig.isSupervisor(user)) throw new PermissionDeniedException( "User " + user + " does not have perms to change the default flood perms to " + floodPerm); FVLog.log(LogLevel.DEBUG, null, "Setting default flood perm to " + floodPerm); FlowvisorImpl.getProxy().setFloodPerm(floodPerm); return true; }
private FlowMap getLocalFlowSpace() { FlowMap fm = this.fvClassifier.getSwitchFlowMap(); switch (fm.getType()) { case LINEAR: return fm.clone(); case FEDERATED: return fm; } FVLog.log( LogLevel.FATAL, null, "Something is fatally wrong with the flowmap. Cannot determine its type."); return null; }
/** * A big ugly method to set a field of an intersection. * * @param flowIntersect - the intersection to update * @param flowEntry - the flowentry from where to get the value from. * @param field - the field to update * @throws UnknownMatchField - Should never happen, but people can be funny. */ private void setField(FlowIntersect flowIntersect, FVMatch match, int field) throws UnknownMatchField { flowIntersect.getMatch().setWildcards(flowIntersect.getMatch().getWildcards() & ~field); switch (field) { case FVMatch.OFPFW_DL_DST: flowIntersect.getMatch().setDataLayerDestination(match.getDataLayerDestination()); break; case FVMatch.OFPFW_DL_SRC: flowIntersect.getMatch().setDataLayerSource(match.getDataLayerSource()); break; case FVMatch.OFPFW_DL_TYPE: flowIntersect.getMatch().setDataLayerType(match.getDataLayerType()); break; case FVMatch.OFPFW_IN_PORT: FVLog.log(LogLevel.DEBUG, null, "Setting input port"); flowIntersect.getMatch().setInputPort(match.getInputPort()); break; case FVMatch.OFPFW_DL_VLAN: flowIntersect.getMatch().setDataLayerVirtualLan(match.getDataLayerVirtualLan()); break; case FVMatch.OFPFW_DL_VLAN_PCP: flowIntersect .getMatch() .setDataLayerVirtualLanPriorityCodePoint( match.getDataLayerVirtualLanPriorityCodePoint()); break; case FVMatch.OFPFW_NW_SRC_ALL: flowIntersect.getMatch().setNetworkSource(match.getNetworkSource()); break; case FVMatch.OFPFW_NW_DST_ALL: flowIntersect.getMatch().setNetworkDestination(match.getNetworkDestination()); break; case FVMatch.OFPFW_NW_PROTO: flowIntersect.getMatch().setNetworkProtocol(match.getNetworkProtocol()); break; case FVMatch.OFPFW_NW_TOS: flowIntersect.getMatch().setNetworkTypeOfService(match.getNetworkTypeOfService()); break; case FVMatch.OFPFW_TP_SRC: flowIntersect.getMatch().setTransportSource(match.getTransportSource()); break; case FVMatch.OFPFW_TP_DST: flowIntersect.getMatch().setTransportDestination(match.getTransportDestination()); break; default: throw new UnknownMatchField("Unknown field type!"); } }
@Override public Integer getMaximumFlowMods(String sliceName, String dpid) throws PermissionDeniedException { String user = APIUserCred.getUserName(); if (!APIAuth.transitivelyCreated(user, sliceName) && !FVConfig.isSupervisor(user)) throw new PermissionDeniedException( "User " + user + " does not have perms to get the flow mod limit for slice " + sliceName); Long dp = FlowSpaceUtil.parseDPID(dpid); try { if (dp == FlowEntry.ALL_DPIDS) return SliceImpl.getProxy().getMaxFlowMods(sliceName); else return SwitchImpl.getProxy().getMaxFlowMods(sliceName, dp); } catch (ConfigError e) { FVLog.log(LogLevel.DEBUG, null, "Unable to get flow mod limit; " + e.getMessage()); return null; } }
protected List<Map<String, String>> getFakeLinks() { FVLog.log(LogLevel.ALERT, null, "API: topology server not running: faking getLinks()"); List<String> devices = listDevices(); List<Map<String, String>> list = new LinkedList<Map<String, String>>(); for (int i = 0; i < devices.size(); i++) { // forward direction LinkAdvertisement link = new LinkAdvertisement(); link.srcDPID = devices.get(i); link.dstDPID = devices.get((i + 1) % devices.size()); link.srcPort = 0; link.dstPort = 1; link.setAttribute("fakeLink", "true"); list.add(link.toMap()); } return list; }
@Override public void updateDB(int version) { FVLog.log(LogLevel.INFO, null, "Updating FlowSpace database table."); if (version == 0) { processAlter("ALTER TABLE FlowSpaceRule ADD COLUMN " + FORCED_QUEUE + " INT DEFAULT -1"); processAlter( "CREATE TABLE FSRQueue( " + "id INT GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), " + "fsr_id INT NOT NULL, " + "queue_id INT DEFAULT -1, " + "PRIMARY KEY (id))"); processAlter("CREATE INDEX fsrqueue_index on FSRQueue (fsr_id ASC)"); processAlter( "ALTER TABLE FSRQueue " + "ADD CONSTRAINT FlowSpaceRule_to_queue_fk FOREIGN KEY (fsr_id) " + "REFERENCES FlowSpaceRule (id) ON DELETE CASCADE"); version++; } }
/** * Protocol-specific fields within ofp_match will be ignored within a single table when the * corresponding protocol is not specified in the match. The IP header and transport header fields * will be ignored unless the Ethertype is specified as either IPv4 or ARP. The tp_src and tp_dst * fields will be ignored unless the network protocol specified is as TCP, UDP or SCTP. Fields * that are ignored don't need to be wildcarded and should be set to 0. */ private void normalize(FVMatch match) { int wildcards = match.getWildcards(); short etherType = match.getDataLayerType(); short proto = match.getNetworkProtocol(); if (etherType != IPTYPE && etherType != ARPTYPE) { wildcards |= FVMatch.OFPFW_NW_SRC_ALL; wildcards |= FVMatch.OFPFW_NW_DST_ALL; wildcards |= FVMatch.OFPFW_NW_PROTO; wildcards |= FVMatch.OFPFW_NW_TOS; wildcards |= FVMatch.OFPFW_TP_DST; wildcards |= FVMatch.OFPFW_TP_SRC; } if (proto != ICMP && proto != TCP && proto != UDP && proto != SCTP) { wildcards |= FVMatch.OFPFW_TP_DST; wildcards |= FVMatch.OFPFW_TP_SRC; } match.setWildcards(wildcards); FVLog.log(LogLevel.DEBUG, null, match.toString()); }