From 13d05bc8458758ee39cb829098241e89616717ee Mon Sep 17 00:00:00 2001 From: Ashlee Young Date: Wed, 9 Sep 2015 22:15:21 -0700 Subject: ONOS checkin based on commit tag e796610b1f721d02f9b0e213cf6f7790c10ecd60 Change-Id: Ife8810491034fe7becdba75dda20de4267bd15cd --- framework/src/onos/providers/netconf/flow/pom.xml | 259 +++++++++++++ .../netconf/flow/impl/NetconfFlowRuleProvider.java | 403 +++++++++++++++++++++ .../netconf/flow/impl/NetconfOperation.java | 139 +++++++ .../provider/netconf/flow/impl/XmlBuilder.java | 223 ++++++++++++ .../provider/netconf/flow/impl/package-info.java | 21 ++ 5 files changed, 1045 insertions(+) create mode 100644 framework/src/onos/providers/netconf/flow/pom.xml create mode 100644 framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfFlowRuleProvider.java create mode 100644 framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfOperation.java create mode 100644 framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/XmlBuilder.java create mode 100644 framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/package-info.java (limited to 'framework/src/onos/providers/netconf/flow') diff --git a/framework/src/onos/providers/netconf/flow/pom.xml b/framework/src/onos/providers/netconf/flow/pom.xml new file mode 100644 index 00000000..8ee4c4e4 --- /dev/null +++ b/framework/src/onos/providers/netconf/flow/pom.xml @@ -0,0 +1,259 @@ + + + + 4.0.0 + + + org.onosproject + onos-netconf-providers + 1.3.0-SNAPSHOT + ../pom.xml + + + onos-netconf-provider-flow + bundle + + + + org.osgi + org.osgi.compendium + + + ch.ethz.ganymed + ganymed-ssh2 + 262 + + + + org.onosproject + jnc + 1.0 + + + org.jdom + jdom2 + 2.0.5 + + + jaxen + jaxen + 1.1.4 + true + + + org.osgi + org.osgi.core + + + org.onosproject + onlab-junit + test + + + org.easymock + easymock + test + + + org.onosproject + onos-yang-tool + 1.3 + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + + com.tailf:JNC + + com/tailf/jnc/** + + + + ch.ethz.ganymed:ganymed-ssh2 + + ch/ethz/ssh2/** + + + + org.jdom:jdom2 + + org/jdom2/** + + + + org.onosproject:onos-yang-tool + + org/opendaylight/yang/gen/** + + + + + + + package + + shade + + + + + + org.apache.felix + maven-scr-plugin + + + org.apache.felix + maven-bundle-plugin + + + + com.tailf.jnc, + ch.ethz.ssh2, + ch.ethz.ssh2.auth, + ch.ethz.ssh2.channel, + ch.ethz.ssh2.crypto, + ch.ethz.ssh2.crypto.cipher, + ch.ethz.ssh2.crypto.dh, + ch.ethz.ssh2.crypto.digest, + ch.ethz.ssh2.log, + ch.ethz.ssh2.packets, + ch.ethz.ssh2.server, + ch.ethz.ssh2.sftp, + ch.ethz.ssh2.signature, + ch.ethz.ssh2.transport, + ch.ethz.ssh2.util, + org.jdom2, + org.jdom2.input, + org.jdom2.output, + org.jdom2.adapters, + org.jdom2.filter, + org.jdom2.internal, + org.jdom2.located, + org.jdom2.transform, + org.jdom2.util, + org.jdom2.xpath, + org.jdom2.input.sax, + org.jdom2.input.stax, + org.jdom2.output.support, + org.jdom2.xpath.jaxen, + org.jdom2.xpath.util, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520, + org.opendaylight.yangtools.yang.data.impl.schema.tree, + org.opendaylight.yangtools.yang.data.impl.codec, + org.opendaylight.yangtools.yang.model.parser.api, + org.opendaylight.yangtools.yang.data.impl.schema.nodes, + org.opendaylight.yangtools.yang.binding.util, + org.opendaylight.yangtools.yang.data.impl, + org.opendaylight.yangtools.sal.binding.generator.impl, + org.opendaylight.yangtools.yang.parser.impl.util, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625, + org.opendaylight.yangtools.yang.data.api, + org.opendaylight.yangtools.objcache.spi, + org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser, + org.opendaylight.yangtools.maven.sal.api.gen.plugin, + org.opendaylight.yangtools.yang.data.impl.schema.builder.impl, + org.opendaylight.yangtools.yang.data.api.schema.tree, + org.opendaylight.yangtools.binding.generator.util, + org.opendaylight.yangtools.sal.binding.generator.spi, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715, + org.opendaylight.yangtools.yang2sources.spi, + org.opendaylight.yangtools.yang.model.repo.api, + org.opendaylight.yangtools.util, + org.opendaylight.yangtools.yang.parser.util, + org.opendaylight.yangtools.yang.data.api.schema.stream, + org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer, + org.opendaylight.yangtools.concepts, + org.opendaylight.yangtools.yang.binding, + org.opendaylight.yangtools.yang.model.util.repo, + org.opendaylight.yangtools.yang.wadl.generator.maven, + org.opendaylight.yangtools.yang.data.api.schema, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type, + org.opendaylight.yangtools.concepts.util, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries, + 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, + org.opendaylight.yangtools.sal.binding.model.api, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.ace.ip, + org.opendaylight.yangtools.yang.data.impl.schema.builder.api, + org.opendaylight.yangtools.util.concurrent, + org.opendaylight.yangtools.yang.parser.builder.impl, + org.opendaylight.yangtools.yang.data.impl.schema.transform.base, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.actions.packet.handling, + org.opendaylight.yangtools.sal.binding.model.api.type.builder, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.acl.transport.header.fields, + org.opendaylight.yangtools.yang2sources.plugin, + org.opendaylight.yangtools.yang.data.impl.codec.xml, + org.opendaylight.yangtools.antlrv4.code.gen, + org.opendaylight.yangtools.yang.parser.builder.util, + org.opendaylight.yangtools.yang.data.impl.schema.transform, + org.opendaylight.yangtools.yang.model.api.type, + org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer, + org.opendaylight.yangtools.yang.data.api.schema.tree.spi, + org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser, + org.opendaylight.yangtools.sal.binding.yang.types, + org.opendaylight.yangtools.yang.data.impl.schema.transform.dom, + org.opendaylight.yangtools.yang.data.impl.util, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.packet.fields.rev140625.timerange, + org.opendaylight.yangtools.sal.binding.generator.api, + org.opendaylight.yangtools.sal.java.api.generator, + org.opendaylight.yangtools.yang.binding.annotations, + org.opendaylight.yangtools.sal.binding.generator.util, + org.opendaylight.yangtools.yang.model.repo.util, + org.opendaylight.yangtools.yang.model.api, + org.opendaylight.yangtools.yang.common, + org.opendaylight.yangtools.yang.wadl.generator, + org.opendaylight.yangtools.yang.parser.builder.api, + org.opendaylight.yangtools.yang.model.util, + org.opendaylight.yangtools.yang.parser.impl, + org.opendaylight.yangtools.yang.data.impl.schema, + org.opendaylight.yangtools.yang.data.api.codec, + org.opendaylight.yangtools.yang.unified.doc.generator, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list, + org.opendaylight.yangtools.objcache, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.actions, + org.opendaylight.yangtools.yang.data.util, + org.opendaylight.yangtools.yang.unified.doc.generator.maven, + org.opendaylight.yangtools.binding.generator.util.generated.type.builder, + org.opendaylight.yangtools.yang.model.repo.spi, + org.opendaylight.yangtools.yang.parser.repo, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches, + org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid, + com.romix.scala, + com.romix.scala.collection, + com.romix.scala.collection.concurrent, + org.opendaylight.yangtools.objcache.impl + + + + + + org.onosproject + onos-maven-plugin + + + + + 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> 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 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 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 = new ArrayList(); + 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 processDeviceEntry(String deviceEntry) { + if (deviceEntry == null) { + log.info("No content for Device Entry, so cannot proceed further."); + return null; + } + + Map deviceMap = new HashMap(); + 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); + + } + } +} diff --git a/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfOperation.java b/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfOperation.java new file mode 100644 index 00000000..d03e75ac --- /dev/null +++ b/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/NetconfOperation.java @@ -0,0 +1,139 @@ +/* + * 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 org.onlab.util.Tools.delay; +import static org.slf4j.LoggerFactory.getLogger; + +import java.io.IOException; + +import org.slf4j.Logger; + +import com.tailf.jnc.Capabilities; +import com.tailf.jnc.JNCException; +import com.tailf.jnc.SSHConnection; +import com.tailf.jnc.SSHSession; + +/** + * This is to carry necessary information to connect and execute NETCONF + * operations. + */ +public class NetconfOperation { + private final Logger log = getLogger(NetconfOperation.class); + private static final int EVENTINTERVAL = 2000; + private static final int CONNECTION_CHECK_INTERVAL = 3; + private static final String INPUT_HELLO_XML_MSG = new StringBuilder( + "") + .append("") + .append("urn:ietf:params:netconf:base:1.0") + .append("").toString(); + + /** + * This will send a Xml message to the device. + * @param xmlMsg XML to send + * @param username user name + * @param password pass word + * @param deviceIp ip address of the device + * @param devicePort port on the device + */ + protected void sendXmlMessage(String xmlMsg, String username, + String password, String deviceIp, + Integer devicePort) { + SSHSession ssh = null; + try { + SSHConnection sshConnection = getConnection(username, password, + deviceIp, devicePort); + ssh = new SSHSession(sshConnection); + executeMessage(ssh, INPUT_HELLO_XML_MSG); + /* + * execute acl message + */ + executeMessage(ssh, xmlMsg); + + } catch (IOException e) { + log.error("Unable to send Hello Message to the device: ", e); + } catch (JNCException e) { + log.error("Authentication fail while sending Hello Message to the device: ", + e); + } catch (Exception e) { + log.error("Unable to send Hello Message to the device: ", e); + } finally { + log.debug("Closing the session after successful execution"); + ssh.close(); + } + } + + private void executeMessage(SSHSession ssh, String xmlMsg) + throws IOException, JNCException { + String helloRequestXML = xmlMsg.trim(); + + log.debug("Sending Hello"); + ssh.print(helloRequestXML); + ssh.flush(); + String xmlResponse = null; + int i = CONNECTION_CHECK_INTERVAL; + while (!ssh.ready() && i > 0) { + delay(EVENTINTERVAL); + i--; + } + + if (ssh.ready()) { + StringBuffer readOne = ssh.readOne(); + if (readOne == null) { + log.error("The Hello Contains No Capabilites"); + throw new JNCException( + JNCException.SESSION_ERROR, + "server does not support NETCONF base capability: " + + Capabilities.NETCONF_BASE_CAPABILITY); + } else { + xmlResponse = readOne.toString().trim(); + + log.debug("Reading Capabilities: " + + ssh.getSSHConnection().getGanymedConnection() + .getHostname()); + } + } + } + + /** + * To establish SSH Connection. + * + * @param username user name + * @param password pass word + * @param sshHost host + * @param sshPort port + * @return new SSH connection + * @throws IOException if connection fails + * @throws JNCException if connection causes an error + */ + public SSHConnection getConnection(String username, String password, + String sshHost, Integer sshPort) + throws IOException, JNCException { + SSHConnection sshConnection; + try { + sshConnection = new SSHConnection(sshHost, sshPort); + sshConnection.authenticateWithPassword(username, password); + } catch (IOException e) { + log.error("Unable to create a connection to the device: "); + throw e; + } catch (JNCException e) { + log.error("Failed to connect to the device: "); + throw e; + } + return sshConnection; + } + +} diff --git a/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/XmlBuilder.java b/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/XmlBuilder.java new file mode 100644 index 00000000..389f1669 --- /dev/null +++ b/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/XmlBuilder.java @@ -0,0 +1,223 @@ +/* + * 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 org.slf4j.LoggerFactory.getLogger; + +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.Namespace; +import org.jdom2.output.Format; +import org.jdom2.output.XMLOutputter; +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.access.list.access.list.entries.matches.AceType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.acl.rev140520.access.list.access.list.entries.matches.ace.type.AceEth; +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.ace.ip.AceIpVersion; +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.AceIpv6; +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.SourcePortRange; +import org.slf4j.Logger; + +/** + * Xml Builder to generate the xml according to given ACL model. + */ +public class XmlBuilder { + private final Logger log = getLogger(XmlBuilder.class); + + public String buildAclRequestXml(AccessList accessList) { + Document doc = new Document(); + Namespace namespaceRpc = Namespace + .getNamespace("urn:ietf:params:xml:ns:netconf:base:1.0"); + Namespace accessNamespaceRpc = Namespace + .getNamespace("urn:ietf:params:xml:ns:yang:ietf-acl"); + doc.setRootElement(new Element("rpc", namespaceRpc) + .setAttribute("message-id", "101")); + + /** + * Access list elements of given ACL model. + */ + Element access = new Element("access-list", accessNamespaceRpc); + access.addContent(new Element("acl-name", accessNamespaceRpc) + .setText(accessList.getAclName())); + // access.addContent(accessEntries); + + if (!accessList.getAccessListEntries().isEmpty() + && accessList.getAccessListEntries() != null) { + for (int accessEntryIntVlu = 0; accessEntryIntVlu < accessList + .getAccessListEntries().size(); accessEntryIntVlu++) { + access.addContent(getAccessEntries(accessEntryIntVlu, + accessList, + accessNamespaceRpc)); + } + } + + /** + * edit-config operation for given ACL model. + */ + Element editConfig = new Element("edit-config", namespaceRpc); + editConfig.addContent(new Element("target", namespaceRpc) + .addContent(new Element("running", namespaceRpc))); + editConfig.addContent(new Element("config", Namespace + .getNamespace("urn:ietf:params:xml:ns:netconf:base:1.0")) + .addContent(access)); + + doc.getRootElement().addContent(editConfig); + XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat()); + String outputString = xmlOutputter.outputString(doc); + + return outputString; + } + + /** + * access entries operation for given ACL model. + */ + private Element getAccessEntries(int accessEntryIntVlu, + AccessList accessList, + Namespace accessNamespaceRpc) { + + /** + * Port Number + */ + + int srcPortRangeLower = 0; + int srcPortRangeUpper = 0; + int destPortRangeLower = 0; + int destPortRangeUpper = 0; + + String sourceIpAdd = ""; + String destinationIpAdd = ""; + + /* + * checking accessList is null or not + */ + if (accessList != null) { + /* + * checking list entries are empty or null + */ + if (!accessList.getAccessListEntries().isEmpty() + && accessList.getAccessListEntries() != null) { + AceType aceType = accessList.getAccessListEntries() + .get(accessEntryIntVlu).getMatches().getAceType(); + + if (aceType instanceof AceIp) { + AceIp aceIp = (AceIp) aceType; + SourcePortRange sourcePortRange = aceIp + .getSourcePortRange(); + if (sourcePortRange != null) { + PortNumber lowerPort = sourcePortRange.getLowerPort(); + PortNumber upperPort = sourcePortRange.getUpperPort(); + + if (lowerPort != null) { + srcPortRangeLower = lowerPort.getValue(); + } + if (upperPort != null) { + srcPortRangeUpper = upperPort.getValue(); + } + } + DestinationPortRange destinationPortRange = aceIp + .getDestinationPortRange(); + + if (destinationPortRange != null) { + PortNumber lowerPort = destinationPortRange + .getLowerPort(); + if (lowerPort != null) { + destPortRangeLower = lowerPort.getValue(); + } + + PortNumber upperPort = destinationPortRange + .getUpperPort(); + if (upperPort != null) { + destPortRangeUpper = upperPort.getValue(); + } + + } + + AceIpVersion aceIpVersion = aceIp.getAceIpVersion(); + if (aceIpVersion instanceof AceIpv4) { + AceIpv4 obj = (AceIpv4) aceIpVersion; + destinationIpAdd = obj.getDestinationIpv4Address() + .getValue(); + sourceIpAdd = obj.getSourceIpv4Address().getValue(); + } else if (aceIpVersion instanceof AceIpv6) { + AceIpv6 obj = (AceIpv6) aceIpVersion; + destinationIpAdd = obj.getDestinationIpv6Address() + .getValue(); + sourceIpAdd = obj.getSourceIpv6Address().getValue(); + } + } else if (aceType instanceof AceEth) { + log.debug("Need to add execution loging for Ace Type Ethernet"); + } + } + } + + /** + * Matches elements to define IP address & Port range for given ACL + * model. + */ + Element matchesElement = new Element("matches", accessNamespaceRpc); + if (String.valueOf(srcPortRangeLower) != null + && !String.valueOf(srcPortRangeLower).isEmpty()) { + + matchesElement.addContent(new Element("source-port-range", + accessNamespaceRpc) + .addContent(new Element("lower-port", accessNamespaceRpc) + .setText(String.valueOf(srcPortRangeLower)))); + + matchesElement.addContent(new Element("source-port-range", + accessNamespaceRpc) + .addContent(new Element("upper-port", accessNamespaceRpc) + .setText(String.valueOf(srcPortRangeUpper)))); + + matchesElement.addContent(new Element("destination-port-range", + accessNamespaceRpc) + .addContent(new Element("lower-port", accessNamespaceRpc) + .setText(String.valueOf(destPortRangeLower)))); + + matchesElement.addContent(new Element("destination-port-range", + accessNamespaceRpc) + .addContent(new Element("upper-port", accessNamespaceRpc) + .setText(String.valueOf(destPortRangeUpper)))); + } + + if (destinationIpAdd != null && !destinationIpAdd.isEmpty()) { + matchesElement.addContent(new Element("destination-ipv4-address", + accessNamespaceRpc) + .setText(destinationIpAdd)); + } + if (sourceIpAdd != null && !sourceIpAdd.isEmpty()) { + matchesElement.addContent(new Element("source-ipv4-address", + accessNamespaceRpc) + .setText(sourceIpAdd)); + } + + /** + * Access entries elements for given ACL model. + */ + Element accessEntries = new Element("access-list-entries", + accessNamespaceRpc); + accessEntries.addContent(new Element("rule-name", accessNamespaceRpc) + .setText(accessList.getAccessListEntries() + .get(accessEntryIntVlu).getRuleName())); + accessEntries.addContent(matchesElement); + accessEntries.addContent(new Element("actions", accessNamespaceRpc) + .addContent(new Element("deny", accessNamespaceRpc))); + + return accessEntries; + } +} diff --git a/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/package-info.java b/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/package-info.java new file mode 100644 index 00000000..b095fc9a --- /dev/null +++ b/framework/src/onos/providers/netconf/flow/src/main/java/org/onosproject/provider/netconf/flow/impl/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2014 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. + */ + +/** + * Provider that will accept any flow rules. + */ +package org.onosproject.provider.netconf.flow.impl; + -- cgit 1.2.3-korg