/* * Copyright (c) 2013 Big Switch Networks, Inc. * * Licensed under the Eclipse Public License, Version 1.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ package org.sdnplatform.messagefilter; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import org.openflow.protocol.OFType; import org.openflow.protocol.OFMessage; import org.sdnplatform.core.ListenerContext; import org.sdnplatform.core.OFMessageFilterManager; import org.sdnplatform.netvirt.core.VNSInterface; import org.sdnplatform.netvirt.manager.INetVirtManagerService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MessageFilterManager extends OFMessageFilterManager { /** * @author Srini * * This class overrides the getMatchedFilters function of OFMessageFilterManager. * This class will have visibility to NetVirt name through the context while the * OFMessageFilter resides on the open-source side of the project, which is unaware of NetVirt. * * @param bp sdnplatform provider */ protected static Logger log = LoggerFactory.getLogger(MessageFilterManager.class); private HashSet<String> getNetVirtsByInterface(List<VNSInterface> ifaces) { HashSet<String> netVirts = new HashSet<String>(); if (ifaces != null && !ifaces.isEmpty()) { for (VNSInterface iface : ifaces) { netVirts.add(iface.getParentVNS().getName()); } } return netVirts; } @Override public HashSet<String> getMatchedFilters(OFMessage m, ListenerContext cntx) { // If no context, no NetVirt affiliation can be determined. if (cntx == null) { log.debug("Empty context for packet {}", m); return null; } // Since the BigMessageFilterManager is after virtual routing, // it is guaranteed that the source and destination interfaces // will be identical at this stage. List<VNSInterface> srcIface = INetVirtManagerService.bcStore.get(cntx, INetVirtManagerService.CONTEXT_SRC_IFACES); HashSet<String> netVirts = getNetVirtsByInterface(srcIface); HashSet<String> matchedFilters = new HashSet<String>(); Iterator<String> filterIt = filterMap.keySet().iterator(); while (filterIt.hasNext()) { // for every filter boolean filterMatch = false; String filterSessionId = filterIt.next(); ConcurrentHashMap<String,String> filter = filterMap.get(filterSessionId); // If the filter has empty fields, then it is not considered as a match. if (filter == null || filter.isEmpty()) continue; Iterator<String> fieldIt = filter.keySet().iterator(); while (fieldIt.hasNext()) { // for every filter field // and if even one fails, the filter match fails. String filterFieldType = fieldIt.next(); String filterFieldValue = filter.get(filterFieldType); // Match on direction log.debug("Looking for {}:{} in NetVirts {}", new Object[] {filterFieldType, filterFieldValue, m.getType().toString()}); if (filterFieldType.equals("direction")) { if (filterFieldValue.equalsIgnoreCase("both")) { filterMatch = true; } else if (filterFieldValue.equalsIgnoreCase("in") && m.getType() == OFType.PACKET_IN) { filterMatch = true; } else if (filterFieldValue.equalsIgnoreCase("out") && (m.getType() == OFType.FLOW_MOD || m.getType() == OFType.PACKET_OUT)) { filterMatch = true; // matches at least one NetVirt name } else { filterMatch = false; break; } } // Match on netVirt log.debug("Looking for {} in NetVirts {}", filterFieldValue, netVirts.toString()); if (filterFieldType.equals("netVirt")) { if (netVirts.contains(filterFieldValue)) { log.debug("packet {} matches netVirt {} for session {}", new Object[]{m, filterFieldValue, filterSessionId}); filterMatch = true; // matches at least one NetVirt name } else { filterMatch = false; break; } } // currently the check is performed only for NetVirt. If we need more // checks, we can append this section. } if (filterMatch) { matchedFilters.add(filterSessionId); } } if (matchedFilters.isEmpty()) { return null; } else { return matchedFilters; } } @Override public boolean isCallbackOrderingPrereq(OFType type, String name) { return (type == OFType.PACKET_IN && name.equals("virtualrouting")); } @Override public boolean isCallbackOrderingPostreq(OFType type, String name) { return (type == OFType.PACKET_IN && name.equals("forwarding")); } }