diff options
Diffstat (limited to 'framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfFlowRuleProvider.java')
-rw-r--r-- | framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfFlowRuleProvider.java | 403 |
1 files changed, 403 insertions, 0 deletions
diff --git a/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfFlowRuleProvider.java b/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfFlowRuleProvider.java new file mode 100644 index 00000000..b29d687e --- /dev/null +++ b/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfFlowRuleProvider.java @@ -0,0 +1,403 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 + * + * 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.onosproject.provider.netconf.flow.impl; + +import static com.google.common.base.Strings.isNullOrEmpty; +import static org.onlab.util.Tools.get; +import static org.slf4j.LoggerFactory.getLogger; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Modified; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.jboss.netty.util.HashedWheelTimer; +import org.jboss.netty.util.Timeout; +import org.jboss.netty.util.TimerTask; +import org.onlab.util.Timer; +import org.onosproject.core.ApplicationId; +import org.onosproject.net.DeviceId; +import org.onosproject.net.flow.FlowEntry; +import org.onosproject.net.flow.FlowRule; +import org.onosproject.net.flow.FlowRuleBatchOperation; +import org.onosproject.net.flow.FlowRuleProvider; +import org.onosproject.net.flow.FlowRuleProviderRegistry; +import org.onosproject.net.flow.FlowRuleProviderService; +import org.onosproject.net.provider.AbstractProvider; +import org.onosproject.net.provider.ProviderId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.AccessList; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.AccessListBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.AccessListEntries; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.AccessListEntriesBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.ActionsBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.Matches; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.MatchesBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.actions.packet.handling.DenyBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.actions.packet.handling.PermitBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.AceIp; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.AceIpBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.ace.ip.ace.ip.version.AceIpv4; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.acl.transport.header.fields.DestinationPortRange; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.acl.transport.header.fields.DestinationPortRangeBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.acl.transport.header.fields.SourcePortRange; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.acl.transport.header.fields.SourcePortRangeBuilder; +import org.osgi.service.component.ComponentContext; +import org.slf4j.Logger; + +/** + * Netconf provider to accept any flow and report them. + */ +@Component(immediate = true) +public class NetconfFlowRuleProvider extends AbstractProvider + implements FlowRuleProvider { + private final Logger log = getLogger(getClass()); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected FlowRuleProviderRegistry providerRegistry; + + private ConcurrentMap<DeviceId, Set<FlowEntry>> flowTable = new ConcurrentHashMap<>(); + + private FlowRuleProviderService providerService; + + private XmlBuilder xmlBuilder; + + private AceIp aceIp; + private SourcePortRange srcPortRange; + private DestinationPortRange destPortRange; + private Matches matches; + private HashedWheelTimer timer = Timer.getTimer(); + private Timeout timeout; + private static final String ACL_NAME_KEY = "acl-name"; + private static final String ACL_LIST_ENTRIES_RULE_NAME_KEY = "access-list-entries.rule-name"; + private static final String ACL_LIST_SP_LOWER_KEY = "source-port-range.lower-port"; + private static final String ACL_LIST_SP_UPPER_KEY = "source-port-range.upper-port"; + private static final String ACL_LIST_DP_LOWER_KEY = "destination-port-range.lower-port"; + private static final String ACL_LIST_DP_UPPER_KEY = "destination-port-range.upper-port"; + private static final String ACL_LIST_DEST_IPV4_KEY = "matches.destination-ipv4-address"; + private static final String ACL_LIST_SRC_IPV4_KEY = "matches.source-ipv4-address"; + private static final String ACL_LIST_ACTIONS_KEY = "actions"; + + public NetconfFlowRuleProvider() { + super(new ProviderId("netconf", "org.onosproject.provider.netconf")); + } + + @Activate + public void activate(ComponentContext context) { + providerService = providerRegistry.register(this); + timeout = timer.newTimeout(new StatisticTask(), 5, TimeUnit.SECONDS); + applyRule(); + modified(context); + log.info("Started"); + } + + @Deactivate + public void deactivate() { + providerRegistry.unregister(this); + providerService = null; + timeout.cancel(); + log.info("Stopped"); + } + + @Modified + public void modified(ComponentContext context) { + if (xmlBuilder == null) { + xmlBuilder = new XmlBuilder(); + } + if (context == null) { + log.info("No configuration file"); + return; + } + Dictionary<?, ?> properties = context.getProperties(); + String deviceEntry = get(properties, "devConfigs"); + log.info("Settings: devConfigs={}", deviceEntry); + Enumeration<?> elements = properties.keys(); + Object nextElement = elements.nextElement(); + while (elements.hasMoreElements()) { + if (nextElement instanceof String) { + log.info("key::" + nextElement + ", value::" + + get(properties, (String) nextElement)); + } + nextElement = elements.nextElement(); + } + if (!isNullOrEmpty(deviceEntry)) { + Map<String, String> deviceMap = processDeviceEntry(deviceEntry); + AccessList accessList = buildAccessList(properties); + String xmlMsg = xmlBuilder.buildAclRequestXml(accessList); + log.info("The resultant xml from the builder\n" + xmlMsg); + NetconfOperation netconfOperation = new NetconfOperation(); + netconfOperation.sendXmlMessage(xmlMsg, deviceMap.get("username"), + deviceMap.get("password"), + deviceMap.get("hostIp"), Integer + .parseInt(deviceMap + .get("hostPort"))); + } + } + + /** + * @param properties + * @return accessList + */ + private AccessList buildAccessList(Dictionary<?, ?> properties) { + /** + * Populating Access List. + */ + AccessListBuilder abuilder = new AccessListBuilder(); + String aclName = get(properties, ACL_NAME_KEY); + if (aclName != null) { + abuilder.setAclName(aclName); + } + AccessList accessList = abuilder.build(); + abuilder.setAccessListEntries(getAccessListEntries(properties, matches)); + srcPortRange = getSourcePortRange(properties); + destPortRange = getDestinationPortRange(properties); + aceIp = getAceIp(properties, srcPortRange, destPortRange); + matches = getMatches(properties); + return accessList; + } + + /** + * @param properties + * @return matches + */ + private Matches getMatches(Dictionary<?, ?> properties) { + /** + * Building Matches for given ACL model. + */ + MatchesBuilder matchesBuilder = new MatchesBuilder(); + if (aceIp != null) { + matchesBuilder.setAceType(aceIp); + } + matches = matchesBuilder.build(); + return matches; + } + + /** + * @param properties + * @return srcPortRange + */ + private SourcePortRange getSourcePortRange(Dictionary<?, ?> properties) { + /** + * Building Source Port Range for given ACL model. + */ + String spRangeLowerStr = get(properties, ACL_LIST_SP_LOWER_KEY); + String spRangeUpperStr = get(properties, ACL_LIST_SP_UPPER_KEY); + SourcePortRangeBuilder srcPortRangeBuilder = new SourcePortRangeBuilder(); + if (spRangeLowerStr != null) { + int spRangeLower = Integer.parseInt(spRangeLowerStr); + srcPortRangeBuilder.setLowerPort(new PortNumber(spRangeLower)); + } + if (spRangeUpperStr != null) { + int spRangeUpper = Integer.parseInt(spRangeUpperStr); + srcPortRangeBuilder.setUpperPort(new PortNumber(spRangeUpper)); + } + srcPortRange = srcPortRangeBuilder.build(); + return srcPortRange; + } + + /** + * @param properties + * @return destPortRange + */ + private DestinationPortRange getDestinationPortRange(Dictionary<?, ?> properties) { + /** + * Building Destination Port Range for given ACL model. + */ + String dpRangeLowerStr = get(properties, ACL_LIST_DP_LOWER_KEY); + String dpRangeUpperStr = get(properties, ACL_LIST_DP_UPPER_KEY); + DestinationPortRangeBuilder destPortRangeBuilder = new DestinationPortRangeBuilder(); + if (dpRangeLowerStr != null) { + int dpRangeLower = Integer.parseInt(dpRangeLowerStr); + destPortRangeBuilder.setLowerPort(new PortNumber(dpRangeLower)); + } + if (dpRangeUpperStr != null) { + int dpRangeUpper = Integer.parseInt(dpRangeUpperStr); + destPortRangeBuilder.setUpperPort(new PortNumber(dpRangeUpper)); + } + destPortRange = destPortRangeBuilder.build(); + return destPortRange; + } + + /** + * @param properties + * @return accessListEntries + */ + private List<AccessListEntries> getAccessListEntries(Dictionary<?, ?> properties, + Matches matches) { + /** + * Build and Populate Access List Entries. + */ + AccessListEntriesBuilder acLListEntriesBuilder = new AccessListEntriesBuilder(); + String aclListEntriesRuleName = get(properties, + ACL_LIST_ENTRIES_RULE_NAME_KEY); + if (aclListEntriesRuleName != null) { + acLListEntriesBuilder.setRuleName(aclListEntriesRuleName); + } + acLListEntriesBuilder.setMatches(matches); + String aclActions = get(properties, ACL_LIST_ACTIONS_KEY); + if (aclActions != null) { + ActionsBuilder actionBuilder = new ActionsBuilder(); + if (aclActions.equalsIgnoreCase("deny")) { + DenyBuilder denyBuilder = new DenyBuilder(); + actionBuilder.setPacketHandling(denyBuilder.build()); + } else if (aclActions.equalsIgnoreCase("permit")) { + PermitBuilder permitBuilder = new PermitBuilder(); + actionBuilder.setPacketHandling(permitBuilder.build()); + } + acLListEntriesBuilder.setActions(actionBuilder.build()); + } + AccessListEntries aclListEntries = acLListEntriesBuilder.build(); + List<AccessListEntries> accessListEntries = new ArrayList<AccessListEntries>(); + accessListEntries.add(aclListEntries); + return accessListEntries; + } + + /** + * @param properties + * @return aceIp + */ + private AceIp getAceIp(Dictionary<?, ?> properties, + SourcePortRange srcPortRange, + DestinationPortRange destPortRange) { + /** + * Building Ace IPV4 Type + */ + String destIpv4 = get(properties, ACL_LIST_DEST_IPV4_KEY); + String srcIpv4 = get(properties, ACL_LIST_SRC_IPV4_KEY); + AceIpv4Builder aceIpv4Builder = new AceIpv4Builder(); + aceIp = null; + if (destIpv4 != null) { + Ipv4Prefix destinationIp = new Ipv4Prefix(destIpv4); + aceIpv4Builder.setDestinationIpv4Address(destinationIp); + } + if (srcIpv4 != null) { + Ipv4Prefix sourceIp = new Ipv4Prefix(srcIpv4); + aceIpv4Builder.setSourceIpv4Address(sourceIp); + } + if (destIpv4 != null || srcIpv4 != null) { + AceIpv4 aceIpv4 = aceIpv4Builder.build(); + AceIpBuilder aceIpBuilder = new AceIpBuilder(); + aceIpBuilder.setAceIpVersion(aceIpv4); + aceIpBuilder.setSourcePortRange(srcPortRange); + aceIpBuilder.setDestinationPortRange(destPortRange); + aceIp = aceIpBuilder.build(); + } + return aceIp; + } + + /** + * @param deviceEntry + * @return deviceMap + */ + private Map<String, String> processDeviceEntry(String deviceEntry) { + if (deviceEntry == null) { + log.info("No content for Device Entry, so cannot proceed further."); + return null; + } + + Map<String, String> deviceMap = new HashMap<String, String>(); + log.info("Trying to convert Device Entry String: " + deviceEntry + + " to a Netconf Device Object"); + try { + URI uri = new URI(deviceEntry); + String path = uri.getPath(); + String userInfo = path.substring(path.lastIndexOf('@')); + String hostInfo = path.substring(path.lastIndexOf('@') + 1); + String[] infoSplit = userInfo.split(":"); + String username = infoSplit[0]; + String password = infoSplit[1]; + infoSplit = hostInfo.split(":"); + String hostIp = infoSplit[0]; + String hostPort = infoSplit[1]; + if (isNullOrEmpty(username) || isNullOrEmpty(password) + || isNullOrEmpty(hostIp) || isNullOrEmpty(hostPort)) { + log.warn("Bad Configuration Data: both user and device" + + " information parts of Configuration " + deviceEntry + + " should be non-nullable"); + } else { + deviceMap.put("hostIp", hostIp); + deviceMap.put("hostPort", hostPort); + deviceMap.put("username", username); + deviceMap.put("password", password); + } + } catch (ArrayIndexOutOfBoundsException aie) { + log.error("Error while reading config infromation from the config file: " + + "The user, host and device state infomation should be " + + "in the order 'userInfo@hostInfo:deviceState'" + + deviceEntry, aie); + } catch (URISyntaxException urie) { + log.error("Error while parsing config information for the device entry: " + + "Illegal character in path " + deviceEntry, + urie); + } catch (Exception e) { + log.error("Error while parsing config information for the device entry: " + + deviceEntry, e); + } + return deviceMap; + } + + @Override + public void applyFlowRule(FlowRule... flowRules) { + } + + @Override + public void removeFlowRule(FlowRule... flowRules) { + } + + private void applyRule() { + // applyFlowRule(flowRules);//currentl + } + + @Override + public void removeRulesById(ApplicationId id, FlowRule... flowRules) { + log.info("removal by app id not supported in null provider"); + } + + @Override + public void executeBatch(FlowRuleBatchOperation batch) { + + } + + private class StatisticTask implements TimerTask { + + @Override + public void run(Timeout to) throws Exception { + for (DeviceId devId : flowTable.keySet()) { + providerService.pushFlowMetrics(devId, flowTable + .getOrDefault(devId, Collections.emptySet())); + } + timeout = timer.newTimeout(to.getTask(), 5, TimeUnit.SECONDS); + + } + } +} |