/** * match is called when a switch sends a packet in to the controller. The goal is to find all flow * space rules which match the fields of the packet in. * * @param dpid - the datapath id of the switch which sent the packet in. * @param match - the packet in information * @return a list, sorted by priority, of flow space rules which match. */ public List<FlowEntry> match(long dpid, FVMatch match) { BitSet set = new BitSet(); LinkedList<FlowEntry> flowrules = new LinkedList<FlowEntry>(); int wildcards = match.getWildcards(); FVLog.log(LogLevel.DEBUG, null, "dpid: ", dpid, "match: ", match.toString()); set.or(allRules); FVLog.log(LogLevel.DEBUG, null, "allRules: ", set.toString()); try { testEmpty(set, dpids, dpid, FlowEntry.ALL_DPIDS, wildcards, 0); /* * Test every field and intersect the resulting bitset. If the bit * set is empty an exception is thrown to stop the search. */ testEmpty(set, port, match.getInputPort(), ANY_IN_PORT, wildcards, FVMatch.OFPFW_IN_PORT); if (match.getDataLayerVirtualLan() != ANY_VLAN_ID) { testEmpty( set, vlan, (int) match.getDataLayerVirtualLan(), (int) ANY_VLAN_ID, wildcards, FVMatch.OFPFW_DL_VLAN); testEmpty( set, vlan, match.getDataLayerVirtualLanPriorityCodePoint() << 16, ANY_VLAN_PCP << 16, wildcards, FVMatch.OFPFW_DL_VLAN_PCP); } else { set.andNot(vlan_ignore); } testEmpty( set, dl_type, match.getDataLayerType(), ANY_ETHER, wildcards, FVMatch.OFPFW_DL_TYPE); testEmpty( set, nw, (short) match.getNetworkProtocol(), (short) ANY_NW_PROTO_TOS, wildcards, FVMatch.OFPFW_NW_PROTO); testEmpty( set, nw, (short) (match.getNetworkTypeOfService() << 8), (short) (ANY_NW_PROTO_TOS << 8), wildcards, FVMatch.OFPFW_NW_TOS); testEmpty( set, tp, (int) match.getTransportSource(), (int) ANY_TP, wildcards, FVMatch.OFPFW_TP_SRC); testEmpty( set, tp, match.getTransportDestination() << 16, ANY_TP << 16, wildcards, FVMatch.OFPFW_TP_DST); testEmpty( set, dl_src, FVMatch.toLong(match.getDataLayerSource()), ANY_MAC, wildcards, FVMatch.OFPFW_DL_SRC); testEmpty( set, dl_dst, FVMatch.toLong(match.getDataLayerDestination()), ANY_MAC, wildcards, FVMatch.OFPFW_DL_DST); for (int i = set.nextSetBit(0); i >= 0; i = set.nextSetBit(i + 1)) { FlowEntry fe = rules.get(i); FVMatch ruleMatch = fe.getRuleMatch(); FlowIntersect inter; inter = new FlowIntersect(fe.clone()); FVMatch interMatch = inter.getMatch(); interMatch.setNetworkDestination( testIP( inter, FVMatch.OFPFW_NW_DST_SHIFT, match.getNetworkDestinationMaskLen(), ruleMatch.getNetworkDestinationMaskLen(), match.getNetworkDestination(), ruleMatch.getNetworkDestination())); if (inter.getMatchType() == MatchType.NONE) { set.clear(i); continue; } // test ip_src interMatch.setNetworkSource( testIP( inter, FVMatch.OFPFW_NW_SRC_SHIFT, match.getNetworkSourceMaskLen(), ruleMatch.getNetworkSourceMaskLen(), match.getNetworkSource(), ruleMatch.getNetworkSource())); if (inter.getMatchType() == MatchType.NONE) { set.clear(i); continue; } } } catch (NoMatch e) { FVLog.log(LogLevel.INFO, null, "No match for: ", match); return flowrules; } /* * If we got here we have a match. Now return a prioritized list of * matches. * * Higher numbers have higher priorities. */ TreeSet<FlowEntry> entries = new TreeSet<FlowEntry>(); for (int i = set.nextSetBit(0); i >= 0; i = set.nextSetBit(i + 1)) { entries.add(rules.get(i)); } flowrules.addAll(entries); return flowrules; }
/* * (non-Javadoc) * * @see java.lang.Object#clone() */ @Override public FlowMap clone() { LinearFlowMap flowMap = new LinearFlowMap(); for (FlowEntry flowEntry : this.rules) flowMap.addRule(flowEntry.clone()); return flowMap; }