├── .gitignore
├── LICENSE
├── README.md
├── acl
├── config
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ └── resources
│ │ └── initial
│ │ └── 51-acl-config.xml
├── implementation
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── org
│ │ │ └── sdnhub
│ │ │ └── odl
│ │ │ └── tutorial
│ │ │ └── acl
│ │ │ └── impl
│ │ │ ├── TutorialACL.java
│ │ │ ├── TutorialACLModule.java
│ │ │ └── TutorialACLModuleFactory.java
│ │ └── yang
│ │ └── acl-impl.yang
├── model
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ └── yang
│ │ └── acl.yang
└── pom.xml
├── commons
├── parent
│ └── pom.xml
└── utils
│ ├── pom.xml
│ └── src
│ └── main
│ └── java
│ └── org
│ └── sdnhub
│ └── odl
│ └── tutorial
│ └── utils
│ ├── GenericTransactionUtils.java
│ ├── PacketParsingUtils.java
│ ├── inventory
│ └── InventoryUtils.java
│ └── openflow13
│ ├── ActionUtils.java
│ ├── InstructionUtils.java
│ └── MatchUtils.java
├── distribution
├── karaf-branding
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ └── resources
│ │ └── org
│ │ └── apache
│ │ └── karaf
│ │ └── branding
│ │ └── branding.properties
├── opendaylight-karaf
│ └── pom.xml
└── pom.xml
├── features
├── pom.xml
└── src
│ └── main
│ └── resources
│ └── features.xml
├── learning-switch
├── config
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ └── resources
│ │ └── initial
│ │ └── 49-learning-switch-config.xml
├── implementation
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── org
│ │ │ └── sdnhub
│ │ │ └── odl
│ │ │ └── tutorial
│ │ │ └── learningswitch
│ │ │ └── impl
│ │ │ ├── TutorialL2Forwarding.java
│ │ │ ├── TutorialL2Forwarding.single_switch.solution
│ │ │ ├── TutorialLearningSwitchModule.java
│ │ │ └── TutorialLearningSwitchModuleFactory.java
│ │ └── yang
│ │ └── learning-switch-impl.yang
└── pom.xml
├── netconf-exercise
├── base_datastore.xml
├── config
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ └── resources
│ │ └── initial
│ │ └── 51-netconf-exercise-config.xml
├── implementation
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── org
│ │ │ └── sdnhub
│ │ │ └── odl
│ │ │ └── tutorial
│ │ │ └── netconf
│ │ │ └── exercise
│ │ │ └── impl
│ │ │ ├── MyRouterOrchestrator.java
│ │ │ ├── TutorialNetconfExerciseModule.java
│ │ │ └── TutorialNetconfExerciseModuleFactory.java
│ │ └── yang
│ │ └── netconf-exercise.yang
├── model
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ └── yang
│ │ └── router.yang
├── netconf-postman.json
├── pom.xml
├── register_netconf_device.sh
├── router.yang
├── spawn_router.sh
└── unregister_netconf_device.sh
├── pom.xml
└── tapapp
├── config
├── pom.xml
└── src
│ └── main
│ └── resources
│ └── initial
│ └── 50-tapapp-config.xml
├── implementation
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── org
│ │ └── sdnhub
│ │ └── odl
│ │ └── tutorial
│ │ └── tapapp
│ │ └── impl
│ │ ├── TutorialTapAppModule.java
│ │ ├── TutorialTapAppModuleFactory.java
│ │ ├── TutorialTapProvider.bidirectional.solution
│ │ ├── TutorialTapProvider.java
│ │ └── TutorialTapProvider.unidirectional.solution
│ └── yang
│ └── tapapp-impl.yang
├── model
├── pom.xml
└── src
│ └── main
│ └── yang
│ └── tap.yang
├── pom.xml
└── postman-resources
└── tapapp-postman.json
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | target/
3 | *.class
4 | *.iml
5 | **/target
6 | **/bin
7 | dist
8 | **/logs
9 | products
10 | repository
11 | workspace
12 | *~
13 | target
14 | .classpath
15 | .project
16 | .settings
17 | MANIFEST.MF
18 |
19 | # Package Files #
20 | *.jar
21 | *.war
22 | *.ear
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SDNHub Opendaylight Tutorial
2 | ============================
3 | This is the OpenDaylight project source code used by the [our tutorial](http://sdnhub.org/tutorials/opendaylight/).
4 |
5 | # Directory Organization
6 | * pom.xml: The POM in the main directory specifies all the sub-POMs to build
7 | * commons/parent: contains the parent pom.xml with all properties defined for the subprojects.
8 | * commons/utils: contains custom utilities built for OpenFlow programming
9 | * learning-switch: contains the tutorial L2 hub / switch
10 | * tapapp: contains the traffic monitoring tap application
11 | * features: defines the two features "sdnhub-tutorial-learning-switch", * "sdnhub-tutorial-tapapp" that can be loaded in Karaf
12 | * distribution/karaf-branding: contains karaf branner for SDN Hub
13 | * distribution/opendaylight-karaf: contains packaging relevant pom to * generate a running directory
14 |
15 | # HOW TO BUILD
16 | In order to build it's required to have JDK 1.8+ and Maven 3.2+.
17 | The following commands are used to build and run.
18 | ```
19 | $ mvn clean install
20 | $ cd distribution/opendaylight-karaf/target/assembly
21 | $ ./bin/karaf
22 | karaf>feature:install sdnhub-XYZ
23 | ```
24 |
--------------------------------------------------------------------------------
/acl/config/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.sdnhub.odl.tutorial
7 | commons
8 | 1.2.0-SNAPSHOT
9 | ../../commons/parent/pom.xml
10 |
11 |
12 | org.sdnhub.odl.tutorial.acl
13 | acl-config
14 | 1.0.0-SNAPSHOT
15 | SDN Hub tutorial Project ACL application Config
16 |
17 | jar
18 |
19 |
20 |
21 | org.codehaus.mojo
22 | build-helper-maven-plugin
23 | ${build.plugins.plugin.version}
24 |
25 |
26 | attach-artifacts
27 |
28 | attach-artifact
29 |
30 | package
31 |
32 |
33 |
34 | ${project.build.directory}/classes/initial/${acl.configfile}
35 | xml
36 | config
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/acl/config/src/main/resources/initial/51-acl-config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | prefix:acl-impl
9 | acl-impl
10 |
11 |
12 | binding:binding-notification-service
13 | binding-notification-broker
14 |
15 |
16 | binding:binding-async-data-broker
17 | binding-data-broker
18 |
19 |
20 | binding:binding-rpc-registry
21 | binding-rpc-broker
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | urn:sdnhub:odl:tutorial:acl:acl-impl?module=acl-impl&revision=2015-07-22
30 | urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl?module=openflow-provider-impl&revision=2014-03-26
31 |
32 |
33 |
--------------------------------------------------------------------------------
/acl/implementation/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.sdnhub.odl.tutorial.acl
6 | acl-parent
7 | 0.1.0-SNAPSHOT
8 |
9 |
10 | acl-impl
11 | SDN Hub tutorial project ACL application Impl
12 | 1.0.0-SNAPSHOT
13 | bundle
14 |
15 |
16 |
17 | org.sdnhub.odl.tutorial
18 | utils
19 | ${utils.version}
20 |
21 |
22 | org.sdnhub.odl.tutorial.acl
23 | acl-model
24 | ${acl.version}
25 |
26 |
27 | org.opendaylight.openflowplugin.model
28 | model-flow-service
29 | ${openflowplugin.version}
30 |
31 |
32 |
33 |
34 |
35 | org.opendaylight.yangtools
36 | yang-maven-plugin
37 | ${yangtools.version}
38 |
39 |
40 |
41 | generate-sources
42 |
43 |
44 | src/main/yang
45 |
46 |
47 | org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
48 | ${codeGeneratorPath}
49 |
50 |
51 | org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
52 | ${configCodeGeneratorPath}
53 |
54 | urn:sdnhub:odl:tutorial:acl:acl-impl==org.sdnhub.odl.tutorial.acl.impl
55 | urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
56 |
57 |
58 |
59 | org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl
60 | ${project.build.directory}/site/models
61 |
62 |
63 | true
64 |
65 |
66 |
67 |
68 |
69 | org.opendaylight.mdsal
70 | maven-sal-api-gen-plugin
71 | ${maven-sal-api-gen-plugin.version}
72 | jar
73 |
74 |
75 | org.opendaylight.controller
76 | yang-jmx-generator-plugin
77 | ${yang.jmx.version}
78 |
79 |
80 |
81 |
82 | org.apache.felix
83 | maven-bundle-plugin
84 | 2.4.0
85 | true
86 |
87 |
88 | *
89 | utils
90 |
91 | ${project.basedir}/META-INF
92 |
93 |
94 |
96 |
97 | org.codehaus.mojo
98 | build-helper-maven-plugin
99 | 1.8
100 |
101 |
102 | add-source
103 |
104 | add-source
105 |
106 | generate-sources
107 |
108 |
109 | src/main/yang
110 | ${codeGeneratorPath}
111 | ${configCodeGeneratorPath}
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | maven-clean-plugin
120 |
121 |
122 |
123 | ${codeGeneratorPath}
124 |
125 | **
126 |
127 |
128 |
129 | ${configCodeGeneratorPath}
130 |
131 | **
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/acl/implementation/src/main/java/org/sdnhub/odl/tutorial/acl/impl/TutorialACL.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 SDN Hub
3 |
4 | Licensed under the GNU GENERAL PUBLIC LICENSE, Version 3.
5 | You may not use this file except in compliance with this License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.gnu.org/licenses/gpl-3.0.txt
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 | implied.
14 |
15 | *
16 | */
17 |
18 | package org.sdnhub.odl.tutorial.acl.impl;
19 |
20 | import java.nio.ByteBuffer;
21 | import java.util.List;
22 | import java.util.Map;
23 |
24 | import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 | import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
26 | import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
27 | import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
28 | import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 | import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
30 | import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
31 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
32 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
33 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
34 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
35 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
36 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
37 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
38 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
39 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
40 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
41 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
42 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
43 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
44 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
45 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
46 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
47 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
48 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
49 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
50 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
51 | import org.opendaylight.yang.gen.v1.urn.sdnhub.odl.tutorial.acl.rev150722.AclSpec;
52 | import org.opendaylight.yang.gen.v1.urn.sdnhub.odl.tutorial.acl.rev150722.acl.spec.Acl;
53 | import org.opendaylight.yangtools.concepts.ListenerRegistration;
54 | import org.opendaylight.yangtools.concepts.Registration;
55 | import org.opendaylight.yangtools.yang.binding.DataObject;
56 | import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
57 | import org.sdnhub.odl.tutorial.utils.GenericTransactionUtils;
58 | import org.sdnhub.odl.tutorial.utils.PacketParsingUtils;
59 | import org.sdnhub.odl.tutorial.utils.inventory.InventoryUtils;
60 | import org.sdnhub.odl.tutorial.utils.openflow13.MatchUtils;
61 | import org.slf4j.Logger;
62 | import org.slf4j.LoggerFactory;
63 |
64 | import com.google.common.base.Preconditions;
65 | import com.google.common.collect.Lists;
66 |
67 | public class TutorialACL implements AutoCloseable, DataChangeListener, PacketProcessingListener {
68 | private final Logger LOG = LoggerFactory.getLogger(this.getClass());
69 | private final static long FLOOD_PORT_NUMBER = 0xfffffffbL;
70 |
71 | //Members related to MD-SAL operations
72 | private List registrations;
73 | private DataBroker dataBroker;
74 | private PacketProcessingService packetProcessingService;
75 |
76 | public TutorialACL(DataBroker dataBroker, NotificationProviderService notificationService, RpcProviderRegistry rpcProviderRegistry) {
77 | //Store the data broker for reading/writing from inventory store
78 | this.dataBroker = dataBroker;
79 |
80 | //Get access to the packet processing service for making RPC calls later
81 | this.packetProcessingService = rpcProviderRegistry.getRpcService(PacketProcessingService.class);
82 |
83 | //List used to track notification (both data change and YANG-defined) listener registrations
84 | this.registrations = registerDataChangeListeners();
85 |
86 | //Register this object for receiving notifications when there are PACKET_INs
87 | registrations.add(notificationService.registerNotificationListener(this));
88 | }
89 |
90 | @Override
91 | public void close() throws Exception {
92 | for (Registration registration : registrations) {
93 | registration.close();
94 | }
95 | registrations.clear();
96 | }
97 |
98 | private List registerDataChangeListeners() {
99 | Preconditions.checkNotNull(dataBroker);
100 | List registrations = Lists.newArrayList();
101 | try {
102 | //Register listener for config updates and topology
103 | InstanceIdentifier aclSpecIID = InstanceIdentifier.builder(AclSpec.class)
104 | .build();
105 | ListenerRegistration registration = dataBroker.registerDataChangeListener(
106 | LogicalDatastoreType.CONFIGURATION,
107 | aclSpecIID, this, AsyncDataBroker.DataChangeScope.SUBTREE);
108 | LOG.debug("DataChangeListener registered with MD-SAL for path {}", aclSpecIID);
109 | registrations.add(registration);
110 |
111 | } catch (Exception e) {
112 | LOG.error("Exception reached {}", e);
113 | }
114 | return registrations;
115 | }
116 |
117 | @Override
118 | public void onDataChanged(AsyncDataChangeEvent, DataObject> change) {
119 | LOG.debug("Data changed: {} created, {} updated, {} removed",
120 | change.getCreatedData().size(), change.getUpdatedData().size(), change.getRemovedPaths().size());
121 |
122 | DataObject dataObject;
123 |
124 | // Iterate over any created nodes or interfaces
125 | for (Map.Entry, DataObject> entry : change.getCreatedData().entrySet()) {
126 | dataObject = entry.getValue();
127 | if (dataObject instanceof Acl) {
128 | programACL((Acl)dataObject);
129 | }
130 | }
131 | }
132 |
133 | @Override
134 | public void onPacketReceived(PacketReceived notification) {
135 | NodeConnectorRef ingressNodeConnectorRef = notification.getIngress();
136 | NodeRef ingressNodeRef = InventoryUtils.getNodeRef(ingressNodeConnectorRef);
137 | // NodeConnectorId ingressNodeConnectorId = InventoryUtils.getNodeConnectorId(ingressNodeConnectorRef);
138 | NodeId ingressNodeId = InventoryUtils.getNodeId(ingressNodeConnectorRef);
139 |
140 | // Useful to create it beforehand
141 | NodeConnectorId floodNodeConnectorId = InventoryUtils.getNodeConnectorId(ingressNodeId, FLOOD_PORT_NUMBER);
142 | NodeConnectorRef floodNodeConnectorRef = InventoryUtils.getNodeConnectorRef(floodNodeConnectorId);
143 |
144 | //Ignore LLDP packets, or you will be in big trouble
145 | byte[] etherTypeRaw = PacketParsingUtils.extractEtherType(notification.getPayload());
146 | int etherType = (0x0000ffff & ByteBuffer.wrap(etherTypeRaw).getShort());
147 | if (etherType == 0x88cc) {
148 | return;
149 | }
150 |
151 | // Flood packet
152 | packetOut(ingressNodeRef, floodNodeConnectorRef, notification.getPayload());
153 | }
154 |
155 | private void packetOut(NodeRef egressNodeRef, NodeConnectorRef egressNodeConnectorRef, byte[] payload) {
156 | Preconditions.checkNotNull(packetProcessingService);
157 | LOG.debug("Flooding packet of size {} out of port {}", payload.length, egressNodeConnectorRef);
158 |
159 | //Construct input for RPC call to packet processing service
160 | TransmitPacketInput input = new TransmitPacketInputBuilder()
161 | .setPayload(payload)
162 | .setNode(egressNodeRef)
163 | .setEgress(egressNodeConnectorRef)
164 | .build();
165 | packetProcessingService.transmitPacket(input);
166 | }
167 |
168 | private void programACL(Acl acl) {
169 | /* Programming a flow involves:
170 | * 1. Creating a Flow object that has a match and drop packets to destination address,
171 | * 2. Adding Flow object as an augmentation to the Node object in the inventory.
172 | * 3. FlowProgrammer module of OpenFlowPlugin will pick up this data change and eventually program the switch.
173 | */
174 |
175 | NodeId nodeId = acl.getNode();
176 |
177 | //Creating match object
178 | MatchBuilder matchBuilder = new MatchBuilder();
179 | MatchUtils.createDstL3IPv4Match(matchBuilder, acl.getIpAddr());
180 |
181 | /*
182 | * Create Flow
183 | */
184 | String flowId = "L3_ACL_Rule_" + acl.getDestination();
185 | FlowBuilder flowBuilder = new FlowBuilder();
186 | flowBuilder.setMatch(matchBuilder.build());
187 | flowBuilder.setId(new FlowId(flowId));
188 | FlowKey key = new FlowKey(new FlowId(flowId));
189 | flowBuilder.setBarrier(true);
190 | flowBuilder.setTableId((short)0);
191 | flowBuilder.setKey(key);
192 | flowBuilder.setPriority(32768);
193 | flowBuilder.setFlowName(flowId);
194 | flowBuilder.setHardTimeout(0);
195 | flowBuilder.setIdleTimeout(0);
196 |
197 | /* Perform transaction to store rule
198 | *
199 | */
200 | InstanceIdentifier flowIID = InstanceIdentifier.builder(Nodes.class)
201 | .child(Node.class, new NodeKey(nodeId))
202 | .augmentation(FlowCapableNode.class)
203 | .child(Table.class, new TableKey(flowBuilder.getTableId()))
204 | .child(Flow.class, flowBuilder.getKey())
205 | .build();
206 | GenericTransactionUtils.writeData(dataBroker, LogicalDatastoreType.CONFIGURATION, flowIID, flowBuilder.build(), true);
207 | LOG.debug("Programming ACL rule to block destination: {}",acl.getIpAddr());
208 |
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/acl/implementation/src/main/java/org/sdnhub/odl/tutorial/acl/impl/TutorialACLModule.java:
--------------------------------------------------------------------------------
1 | package org.sdnhub.odl.tutorial.acl.impl;
2 |
3 | import org.opendaylight.controller.md.sal.binding.api.DataBroker;
4 | import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
5 | import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | public class TutorialACLModule extends org.sdnhub.odl.tutorial.acl.impl.AbstractTutorialACLModule {
10 | private final Logger LOG = LoggerFactory.getLogger(this.getClass());
11 | public TutorialACLModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
12 | super(identifier, dependencyResolver);
13 | }
14 |
15 | public TutorialACLModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.sdnhub.odl.tutorial.acl.impl.TutorialACLModule oldModule, java.lang.AutoCloseable oldInstance) {
16 | super(identifier, dependencyResolver, oldModule, oldInstance);
17 | }
18 |
19 | @Override
20 | public void customValidation() {
21 | // add custom validation form module attributes here.
22 | }
23 |
24 | @Override
25 | public java.lang.AutoCloseable createInstance() {
26 | //Get all MD-SAL provider objects
27 | DataBroker dataBroker = getDataBrokerDependency();
28 | RpcProviderRegistry rpcRegistry = getRpcRegistryDependency();
29 | NotificationProviderService notificationService = getNotificationServiceDependency();
30 |
31 | TutorialACL tutorialACL = new TutorialACL(dataBroker, notificationService, rpcRegistry);
32 | LOG.info("Tutorial Access Control List (instance {}) initialized.", tutorialACL);
33 | return tutorialACL;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/acl/implementation/src/main/java/org/sdnhub/odl/tutorial/acl/impl/TutorialACLModuleFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Generated file
3 | *
4 | * Generated from: yang module name: acl-impl yang module local name: acl-impl
5 | * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
6 | * Generated at: Sun Jul 26 00:55:52 PDT 2015
7 | *
8 | * Do not modify this file unless it is present under src/main directory
9 | */
10 | package org.sdnhub.odl.tutorial.acl.impl;
11 | public class TutorialACLModuleFactory extends org.sdnhub.odl.tutorial.acl.impl.AbstractTutorialACLModuleFactory {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/acl/implementation/src/main/yang/acl-impl.yang:
--------------------------------------------------------------------------------
1 | module acl-impl {
2 | yang-version 1;
3 | namespace "urn:sdnhub:odl:tutorial:acl:acl-impl";
4 | prefix "acl-impl";
5 |
6 | import config { prefix config; revision-date 2013-04-05; }
7 | import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
8 |
9 | description
10 | "This module contains the base YANG definitions for acl-impl.";
11 |
12 | revision "2015-07-22" {
13 | description
14 | "Initial revision.";
15 | }
16 |
17 | // This is the definition of the service implementation as a module identity
18 | identity acl-impl {
19 | base config:module-type;
20 |
21 | // Specifies the prefix for generated java classes.
22 | config:java-name-prefix TutorialACL;
23 | }
24 |
25 | // Augments the 'configuration' choice node under modules/module
26 | augment "/config:modules/config:module/config:configuration" {
27 | case acl-impl {
28 | when "/config:modules/config:module/config:type = 'acl-impl'";
29 |
30 | //wires in the data-broker service
31 | container data-broker {
32 | uses config:service-ref {
33 | refine type {
34 | mandatory true;
35 | config:required-identity mdsal:binding-async-data-broker;
36 | }
37 | }
38 | }
39 | container notification-service {
40 | uses config:service-ref {
41 | refine type {
42 | mandatory false;
43 | config:required-identity mdsal:binding-notification-service;
44 | }
45 | }
46 | }
47 | container rpc-registry {
48 | uses config:service-ref {
49 | refine type {
50 | mandatory true;
51 | config:required-identity mdsal:binding-rpc-registry;
52 | }
53 | }
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/acl/model/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.sdnhub.odl.tutorial
6 | commons
7 | 1.2.0-SNAPSHOT
8 | ../../commons/parent/
9 |
10 |
11 | org.sdnhub.odl.tutorial.acl
12 | acl-model
13 | 1.0.0-SNAPSHOT
14 | bundle
15 | SDN Hub tutorial project ACL application Model
16 |
17 |
18 |
19 | org.opendaylight.controller.model
20 | model-inventory
21 | ${controller-model.version}
22 |
23 |
24 |
25 |
26 |
27 |
28 | org.apache.felix
29 | maven-bundle-plugin
30 | true
31 |
32 |
33 | ${project.groupId}.${project.artifactId}
34 | org.opendaylight.yangtools.yang.binding.annotations, *
35 | ${project.basedir}/META-INF
36 |
37 |
38 |
39 |
40 | org.opendaylight.yangtools
41 | yang-maven-plugin
42 | ${yangtools.version}
43 |
44 |
45 | org.opendaylight.mdsal
46 | maven-sal-api-gen-plugin
47 | ${maven-sal-api-gen-plugin.version}
48 | jar
49 |
50 |
51 | org.opendaylight.mdsal
52 | yang-binding
53 | ${yang-binding.version}
54 | jar
55 |
56 |
57 |
58 |
59 |
60 | generate-sources
61 |
62 |
63 | src/main/yang
64 |
65 |
66 | org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
67 | ${codeGeneratorPath}
68 |
69 |
70 | org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl
71 | target/site/models
72 |
73 |
74 | org.opendaylight.yangtools.yang.wadl.generator.maven.WadlGenerator
75 | target/site/models
76 |
77 |
78 | true
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | maven-clean-plugin
87 |
88 |
89 |
90 | ${codeGeneratorPath}
91 |
92 | **
93 |
94 |
95 |
96 | ${codeGeneratorPath}
97 |
98 | **
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/acl/model/src/main/yang/acl.yang:
--------------------------------------------------------------------------------
1 | module acl {
2 | yang-version 1;
3 | namespace "urn:sdnhub:odl:tutorial:acl";
4 | prefix acl;
5 |
6 | import opendaylight-inventory {prefix inv; revision-date 2013-08-19;}
7 | import yang-ext {prefix ext; revision-date "2013-07-09";}
8 | import ietf-yang-types { prefix yang; revision-date 2010-09-24; }
9 | import ietf-inet-types { prefix inet; }
10 | description "ACL configuration";
11 |
12 | revision "2015-07-22" {
13 | description "Initial version.";
14 | }
15 |
16 | typedef port-number {
17 | type uint32;
18 | }
19 |
20 | container acl-spec {
21 | list acl {
22 | key "destination";
23 | leaf destination {
24 | type string;
25 | }
26 | leaf node {
27 | mandatory true;
28 | type leafref {
29 | path "/inv:nodes/inv:node/inv:id";
30 | }
31 | }
32 | leaf ip-addr {
33 | type inet:ipv4-prefix;
34 | }
35 | leaf port {
36 | type port-number;
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/acl/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | org.sdnhub.odl.tutorial
9 | commons
10 | 1.2.0-SNAPSHOT
11 | ../commons/parent/
12 |
13 |
14 | org.sdnhub.odl.tutorial.acl
15 | acl-parent
16 | 0.1.0-SNAPSHOT
17 | pom
18 |
19 |
20 | model
21 | implementation
22 | config
23 |
24 |
25 |
--------------------------------------------------------------------------------
/commons/parent/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | 3.0
7 |
8 |
9 | org.opendaylight.odlparent
10 | odlparent
11 | 1.6.1-Beryllium-SR1
12 |
13 |
14 |
15 | org.sdnhub.odl.tutorial
16 | commons
17 | SDN Hub Tutorial project common properties
18 | 1.2.0-SNAPSHOT
19 | pom
20 | http://sdnhub.org/tutorials/opendaylight
21 |
22 |
23 |
24 | http://nexus.opendaylight.org/content
25 | UTF-8
26 | 1.7
27 | 1.7
28 | true
29 | true
30 | src/main/yang-gen-code
31 | src/main/yang-gen-config
32 |
33 |
34 | 1.0.0-SNAPSHOT
35 | 1.0.0-SNAPSHOT
36 | 1.0.0-SNAPSHOT
37 | 1.0.0-SNAPSHOT
38 | 1.0.0-SNAPSHOT
39 | 1.0.0-SNAPSHOT
40 | 1.0.0-SNAPSHOT
41 | 1.0.0-SNAPSHOT
42 |
43 |
44 | 49-learning-switch-config.xml
45 | 50-tapapp-config.xml
46 | 51-acl-config.xml
47 | 51-netconf-exercise-config.xml
48 |
49 |
50 | 0.8.1-Beryllium-SR1
51 | 0.8.1-Beryllium-SR1
52 | 0.8.1-Beryllium-SR1
53 | 0.4.1-Beryllium-SR1
54 | 0.4.1-Beryllium-SR1
55 | 1.3.1-Beryllium-SR1
56 | 2013.10.21.8.1-Beryllium-SR1
57 | 2010.09.24.8.1-Beryllium-SR1
58 | 2010.09.24.8.1-Beryllium-SR1
59 | 2013.09.07.8.1-Beryllium-SR1
60 | 1.3.1-Beryllium-SR1
61 |
62 |
63 | 0.2.1-Beryllium-SR1
64 | 1.3.1-Beryllium-SR1
65 |
66 |
67 | 3.0.3
68 | 1.9.1
69 | 1.6.1-Beryllium-SR1
70 |
71 |
72 | 0.3.1-Beryllium-SR1
73 | 0.3.1-Beryllium-SR1
74 | 0.3.1-Beryllium-SR1
75 | 1.0.1-Beryllium-SR1
76 | 1.3.1-Beryllium-SR1
77 | 1.3.1-Beryllium-SR1
78 | 0.2.1-Beryllium-SR1
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | org.apache.maven.plugins
87 | maven-compiler-plugin
88 |
89 | ${java.version.source}
90 | ${java.version.target}
91 | ${java.version.source}
92 | ${java.version.target}
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | opendaylight-release
103 | opendaylight-release
104 | http://nexus.opendaylight.org/content/repositories/opendaylight.release/
105 |
106 | true
107 |
108 |
109 | false
110 |
111 |
112 |
113 |
114 | opendaylight-snapshot
115 | opendaylight-snapshot
116 | http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/
117 |
118 | false
119 |
120 |
121 | true
122 |
123 |
124 |
125 |
126 |
127 |
128 | opendaylight-release
129 | opendaylight-release
130 | http://nexus.opendaylight.org/content/repositories/opendaylight.release/
131 |
132 | false
133 |
134 |
135 | true
136 |
137 |
138 |
139 | opendaylight-snapshot
140 | opendaylight-snapshot
141 | http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/
142 |
143 | true
144 |
145 |
146 | false
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 | org.opendaylight.mdsal.model
155 | ietf-yang-types
156 | ${ietf-yang-types.version}
157 |
158 |
159 | org.opendaylight.mdsal.model
160 | ietf-inet-types
161 | ${ietf-inet-types.version}
162 |
163 |
164 | org.opendaylight.mdsal.model
165 | yang-ext
166 | ${yang-ext.version}
167 |
168 |
169 | org.opendaylight.yangtools
170 | yang-common
171 | ${yangtools.version}
172 |
173 |
174 | org.opendaylight.mdsal
175 | yang-binding
176 | ${yang-binding.version}
177 |
178 |
179 | org.opendaylight.controller
180 | config-api
181 | ${config-api.version}
182 |
183 |
184 | org.opendaylight.controller
185 | sal-binding-config
186 | ${sal-binding.version}
187 |
188 |
189 | org.opendaylight.controller
190 | sal-binding-api
191 | ${sal-binding.version}
192 |
193 |
194 |
195 |
--------------------------------------------------------------------------------
/commons/utils/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.sdnhub.odl.tutorial
6 | commons
7 | 1.2.0-SNAPSHOT
8 | ../../commons/parent/
9 |
10 |
11 | org.sdnhub.odl.tutorial
12 | utils
13 | SDN Hub tutorial project common utils
14 | 1.0.0-SNAPSHOT
15 | bundle
16 |
17 |
18 |
19 |
20 | org.opendaylight.openflowplugin
21 | openflowplugin-api
22 | ${openflowplugin.version}
23 |
24 |
25 |
26 |
27 |
28 |
29 | org.apache.felix
30 | maven-bundle-plugin
31 | 2.4.0
32 | true
33 |
34 |
35 |
36 | false
37 |
38 |
39 | org.sdnhub.odl.tutorial.utils
40 |
41 |
42 | ${project.basedir}/META-INF
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/commons/utils/src/main/java/org/sdnhub/odl/tutorial/utils/GenericTransactionUtils.java:
--------------------------------------------------------------------------------
1 | package org.sdnhub.odl.tutorial.utils;
2 |
3 | import java.util.concurrent.ExecutionException;
4 |
5 | import org.opendaylight.controller.md.sal.binding.api.DataBroker;
6 | import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
7 | import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
8 | import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
9 | import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
10 | import org.opendaylight.yangtools.yang.binding.DataObject;
11 | import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
12 | import org.slf4j.Logger;
13 | import org.slf4j.LoggerFactory;
14 |
15 | import com.google.common.base.Optional;
16 | import com.google.common.base.Preconditions;
17 | import com.google.common.util.concurrent.CheckedFuture;
18 |
19 | public final class GenericTransactionUtils {
20 | static final Logger logger = LoggerFactory.getLogger(GenericTransactionUtils.class);
21 |
22 | public static boolean writeData(DataBroker dataBroker, LogicalDatastoreType logicalDatastoreType,
23 | InstanceIdentifier iid, T dataObject, boolean isAdd) {
24 | Preconditions.checkNotNull(dataBroker);
25 | WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
26 | if (isAdd) {
27 | if (dataObject == null) {
28 | logger.warn("Invalid attempt to add a non-existent object to path {}", iid);
29 | return false;
30 | }
31 | modification.merge(logicalDatastoreType, iid, dataObject, true /*createMissingParents*/);
32 | }
33 | else {
34 | modification.delete(LogicalDatastoreType.CONFIGURATION, iid);
35 | }
36 | CheckedFuture commitFuture = modification.submit();
37 | try {
38 | commitFuture.checkedGet();
39 | logger.debug("Transaction success for {} of object {}", (isAdd) ? "add" : "delete", dataObject);
40 | return true;
41 | } catch (Exception e) {
42 | logger.error("Transaction failed with error {} for {} of object {}", e.getMessage(), (isAdd) ? "add" : "delete", dataObject);
43 | modification.cancel();
44 | return false;
45 | }
46 | }
47 |
48 | public static T readData(DataBroker dataBroker, LogicalDatastoreType dataStoreType, InstanceIdentifier iid) {
49 | Preconditions.checkNotNull(dataBroker);
50 | ReadOnlyTransaction readTransaction = dataBroker.newReadOnlyTransaction();
51 | try {
52 | Optional optionalData = readTransaction.read(dataStoreType, iid).get();
53 | if (optionalData.isPresent()) {
54 | return (T)optionalData.get();
55 | }
56 | } catch (ExecutionException | InterruptedException e) {
57 | logger.error("Read transaction for identifier {} failed with error {}", iid, e.getMessage());
58 | readTransaction.close();
59 | }
60 | return null;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/commons/utils/src/main/java/org/sdnhub/odl/tutorial/utils/PacketParsingUtils.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
3 | *
4 | * This program and the accompanying materials are made available under the
5 | * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 | * and is available at http://www.eclipse.org/legal/epl-v10.html
7 | */
8 |
9 | package org.sdnhub.odl.tutorial.utils;
10 |
11 | import java.util.Arrays;
12 |
13 | import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
14 |
15 | /**
16 | *
17 | */
18 | public abstract class PacketParsingUtils {
19 |
20 | /**
21 | * size of MAC address in octets (6*8 = 48 bits)
22 | */
23 | private static final int MAC_ADDRESS_SIZE = 6;
24 |
25 | /**
26 | * start position of destination MAC address in array
27 | */
28 | private static final int DST_MAC_START_POSITION = 0;
29 |
30 | /**
31 | * end position of destination MAC address in array
32 | */
33 | private static final int DST_MAC_END_POSITION = 6;
34 |
35 | /**
36 | * start position of source MAC address in array
37 | */
38 | private static final int SRC_MAC_START_POSITION = 6;
39 |
40 | /**
41 | * end position of source MAC address in array
42 | */
43 | private static final int SRC_MAC_END_POSITION = 12;
44 |
45 | /**
46 | * start position of ethernet type in array
47 | */
48 | private static final int ETHER_TYPE_START_POSITION = 12;
49 |
50 | /**
51 | * end position of ethernet type in array
52 | */
53 | private static final int ETHER_TYPE_END_POSITION = 14;
54 |
55 | private PacketParsingUtils() {
56 | //prohibite to instantiate this class
57 | }
58 |
59 | /**
60 | * @param payload
61 | * @return destination MAC address
62 | */
63 | public static byte[] extractDstMac(final byte[] payload) {
64 | return Arrays.copyOfRange(payload, DST_MAC_START_POSITION, DST_MAC_END_POSITION);
65 | }
66 |
67 | /**
68 | * @param payload
69 | * @return source MAC address
70 | */
71 | public static byte[] extractSrcMac(final byte[] payload) {
72 | return Arrays.copyOfRange(payload, SRC_MAC_START_POSITION, SRC_MAC_END_POSITION);
73 | }
74 |
75 | /**
76 | * @param payload
77 | * @return source MAC address
78 | */
79 | public static byte[] extractEtherType(final byte[] payload) {
80 | return Arrays.copyOfRange(payload, ETHER_TYPE_START_POSITION, ETHER_TYPE_END_POSITION);
81 | }
82 |
83 | /**
84 | * @param rawMac
85 | * @return {@link MacAddress} wrapping string value, baked upon binary MAC
86 | * address
87 | */
88 | public static MacAddress rawMacToMac(final byte[] rawMac) {
89 | MacAddress mac = null;
90 | if (rawMac != null && rawMac.length == MAC_ADDRESS_SIZE) {
91 | StringBuilder sb = new StringBuilder();
92 | for (byte octet : rawMac) {
93 | sb.append(String.format(":%02X", octet));
94 | }
95 | mac = new MacAddress(sb.substring(1));
96 | }
97 | return mac;
98 | }
99 |
100 | public static String rawMacToString(byte[] rawMac) {
101 | if (rawMac != null && rawMac.length == 6) {
102 | StringBuffer sb = new StringBuffer();
103 | for (byte octet : rawMac) {
104 | sb.append(String.format(":%02X", octet));
105 | }
106 | return sb.substring(1);
107 | }
108 | return null;
109 | }
110 |
111 | public static byte[] stringMacToRawMac(String address) {
112 | String[] elements = address.split(":");
113 | if (elements.length != MAC_ADDRESS_SIZE) {
114 | throw new IllegalArgumentException(
115 | "Specified MAC Address must contain 12 hex digits" +
116 | " separated pairwise by :'s.");
117 | }
118 |
119 | byte[] addressInBytes = new byte[MAC_ADDRESS_SIZE];
120 | for (int i = 0; i < MAC_ADDRESS_SIZE; i++) {
121 | String element = elements[i];
122 | addressInBytes[i] = (byte)Integer.parseInt(element, 16);
123 | }
124 | return addressInBytes;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/commons/utils/src/main/java/org/sdnhub/odl/tutorial/utils/inventory/InventoryUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 SDN Hub
3 |
4 | Licensed under the GNU GENERAL PUBLIC LICENSE, Version 3.
5 | You may not use this file except in compliance with this License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.gnu.org/licenses/gpl-3.0.txt
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 | implied.
14 |
15 | *
16 | */
17 | package org.sdnhub.odl.tutorial.utils.inventory;
18 |
19 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
20 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
21 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
22 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
23 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
24 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
25 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
26 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
27 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
28 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
29 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
30 | import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 |
32 | public final class InventoryUtils {
33 | public static final String OPENFLOW_NODE_PREFIX = "openflow:";
34 |
35 | public static NodeRef getNodeRef(NodeId nodeId) {
36 | return new NodeRef(InstanceIdentifier.builder(Nodes.class)
37 | .child(Node.class, new NodeKey(nodeId))
38 | .build());
39 | }
40 |
41 | public static NodeRef getNodeRef(NodeConnectorRef nodeConnectorRef) {
42 | InstanceIdentifier nodeIID = nodeConnectorRef.getValue()
43 | .firstIdentifierOf(Node.class);
44 | return new NodeRef(nodeIID);
45 | }
46 |
47 | public static NodeBuilder getNodeBuilder(NodeId nodeId) {
48 | NodeBuilder builder = new NodeBuilder()
49 | .setId(nodeId)
50 | .setKey(new NodeKey(nodeId));
51 | return builder;
52 | }
53 |
54 | public static NodeBuilder getNodeBuilder(String dpid) {
55 | String nodeName = OPENFLOW_NODE_PREFIX + dpid;
56 | NodeBuilder builder = new NodeBuilder();
57 | builder.setId(new NodeId(nodeName));
58 | builder.setKey(new NodeKey(builder.getId()));
59 | return builder;
60 | }
61 |
62 | public static NodeId getNodeId(NodeConnectorRef nodeConnectorRef) {
63 | return nodeConnectorRef.getValue()
64 | .firstKeyOf(Node.class, NodeKey.class)
65 | .getId();
66 | }
67 |
68 | public static NodeId getNodeId(NodeConnectorId nodeConnectorId) {
69 | if (nodeConnectorId == null)
70 | return null;
71 | String[] tokens = nodeConnectorId.getValue().split(":");
72 | if (tokens.length == 3)
73 | return new NodeId(OPENFLOW_NODE_PREFIX + Long.parseLong(tokens[1]));
74 | else
75 | return null;
76 | }
77 |
78 | public static NodeConnectorId getNodeConnectorId(NodeId nodeId, long portNumber) {
79 | if (nodeId == null)
80 | return null;
81 | String nodeConnectorIdStr = nodeId.getValue() + ":" + portNumber;
82 | return new NodeConnectorId(nodeConnectorIdStr);
83 | }
84 |
85 | public static NodeConnectorRef getNodeConnectorRef(NodeConnectorId nodeConnectorId) {
86 | NodeId nodeId = getNodeId(nodeConnectorId);
87 | return new NodeConnectorRef(InstanceIdentifier.builder(Nodes.class)
88 | .child(Node.class, new NodeKey(nodeId))
89 | .child(NodeConnector.class, new NodeConnectorKey(nodeConnectorId))
90 | .build());
91 | }
92 |
93 | public static NodeConnectorBuilder getNodeConnectorBuilder(NodeConnectorId nodeConnectorId) {
94 | NodeConnectorBuilder builder = new NodeConnectorBuilder()
95 | .setId(nodeConnectorId)
96 | .setKey(new NodeConnectorKey(nodeConnectorId));
97 | return builder;
98 | }
99 |
100 | public static NodeConnectorId getNodeConnectorId(NodeConnectorRef nodeConnectorRef) {
101 | return nodeConnectorRef.getValue()
102 | .firstKeyOf(NodeConnector.class, NodeConnectorKey.class)
103 | .getId();
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/commons/utils/src/main/java/org/sdnhub/odl/tutorial/utils/openflow13/ActionUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Red Hat, Inc.
3 | *
4 | * This program and the accompanying materials are made available under the
5 | * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 | * and is available at http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | */
9 | package org.sdnhub.odl.tutorial.utils.openflow13;
10 |
11 | import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
12 | import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
13 | import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
14 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
15 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DecMplsTtlCaseBuilder;
16 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DecNwTtlCaseBuilder;
17 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder;
18 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
19 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
20 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder;
21 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsActionCaseBuilder;
22 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
23 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder;
24 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCaseBuilder;
25 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCaseBuilder;
26 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder;
27 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetMplsTtlActionCaseBuilder;
28 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCaseBuilder;
29 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCaseBuilder;
30 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTtlActionCaseBuilder;
31 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.mpls.ttl._case.DecMplsTtlBuilder;
32 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtlBuilder;
33 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder;
34 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
35 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
36 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.mpls.action._case.PushMplsActionBuilder;
37 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
38 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
39 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder;
40 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.dst.action._case.SetDlDstActionBuilder;
41 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.src.action._case.SetDlSrcActionBuilder;
42 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder;
43 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.mpls.ttl.action._case.SetMplsTtlActionBuilder;
44 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
45 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
46 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.ttl.action._case.SetNwTtlActionBuilder;
47 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
48 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
49 | import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.ProtocolMatchFieldsBuilder;
50 | import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
51 | import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
52 | import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
53 |
54 | import com.google.common.net.InetAddresses;
55 |
56 | import java.math.BigInteger;
57 |
58 | public final class ActionUtils {
59 | public static Action dropAction() {
60 | return new DropActionCaseBuilder()
61 | .setDropAction(new DropActionBuilder()
62 | .build())
63 | .build();
64 | }
65 |
66 | public static Action outputAction(NodeConnectorId id) {
67 | return new OutputActionCaseBuilder()
68 | .setOutputAction(new OutputActionBuilder()
69 | .setOutputNodeConnector(new Uri(id.getValue()))
70 | .build())
71 | .build();
72 | }
73 |
74 | public static Action groupAction(Long id) {
75 | return new GroupActionCaseBuilder()
76 | .setGroupAction(new GroupActionBuilder()
77 | .setGroupId(id)
78 | .build())
79 | .build();
80 | }
81 |
82 | public static Action pushVlanAction(Integer ethernetType) {
83 | return new PushVlanActionCaseBuilder()
84 | .setPushVlanAction(new PushVlanActionBuilder()
85 | .setEthernetType(ethernetType)
86 | .build())
87 | .build();
88 | }
89 |
90 | public static Action popVlanAction() {
91 | return new PopVlanActionCaseBuilder()
92 | .setPopVlanAction(new PopVlanActionBuilder()
93 | .build())
94 | .build();
95 | }
96 |
97 | public static Action setVlanVidAction(Integer vlanId) {
98 | VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
99 | VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
100 | vlanIdBuilder.setVlanId(new VlanId(vlanId));
101 | vlanIdBuilder.setVlanIdPresent(true);
102 | vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
103 | SetFieldBuilder setFieldBuilder = new SetFieldBuilder()
104 | .setVlanMatch((vlanMatchBuilder.build()));
105 |
106 | return new SetFieldCaseBuilder()
107 | .setSetField(setFieldBuilder.build())
108 | .build();
109 | }
110 |
111 | public static Action pushMplsAction(Integer ethernetType) {
112 | return new PushMplsActionCaseBuilder()
113 | .setPushMplsAction(new PushMplsActionBuilder()
114 | .setEthernetType(ethernetType)
115 | .build())
116 | .build();
117 | }
118 |
119 | public static Action popMplsAction(Integer payloadEthernetType) {
120 | return new PopMplsActionCaseBuilder()
121 | .setPopMplsAction(new PopMplsActionBuilder()
122 | .setEthernetType(payloadEthernetType)
123 | .build())
124 | .build();
125 | }
126 |
127 | public static Action setMplsLabelBosAction(Long label, boolean bos) {
128 | ProtocolMatchFieldsBuilder matchFieldsBuilder = new ProtocolMatchFieldsBuilder()
129 | .setMplsLabel(label)
130 | .setMplsBos((short) (bos?1:0));
131 | SetFieldBuilder setFieldBuilder = new SetFieldBuilder()
132 | .setProtocolMatchFields(matchFieldsBuilder.build());
133 | return new SetFieldCaseBuilder()
134 | .setSetField(setFieldBuilder.build())
135 | .build();
136 | }
137 |
138 | public static Action setDlSrcAction(MacAddress mac) {
139 | return new SetDlSrcActionCaseBuilder()
140 | .setSetDlSrcAction(new SetDlSrcActionBuilder()
141 | .setAddress(mac)
142 | .build())
143 | .build();
144 | }
145 |
146 | public static Action setDlDstAction(MacAddress mac) {
147 | return new SetDlDstActionCaseBuilder()
148 | .setSetDlDstAction(new SetDlDstActionBuilder()
149 | .setAddress(mac)
150 | .build())
151 | .build();
152 | }
153 |
154 | public static Action setNwSrcAction(Address ip) {
155 | return new SetNwSrcActionCaseBuilder()
156 | .setSetNwSrcAction(new SetNwSrcActionBuilder()
157 | .setAddress(ip)
158 | .build())
159 | .build();
160 | }
161 |
162 | public static Action setNwDstAction(Address ip) {
163 | return new SetNwDstActionCaseBuilder()
164 | .setSetNwDstAction(new SetNwDstActionBuilder()
165 | .setAddress(ip)
166 | .build())
167 | .build();
168 | }
169 |
170 | public static Action SetNwTtlAction(Short ttlValue) {
171 | return new SetNwTtlActionCaseBuilder()
172 | .setSetNwTtlAction(new SetNwTtlActionBuilder()
173 | .setNwTtl(ttlValue)
174 | .build())
175 | .build();
176 | }
177 |
178 | public static Action decNwTtlAction() {
179 | return new DecNwTtlCaseBuilder()
180 | .setDecNwTtl(new DecNwTtlBuilder()
181 | .build())
182 | .build();
183 | }
184 |
185 | public static Action decMplsTtlAction() {
186 | return new DecMplsTtlCaseBuilder()
187 | .setDecMplsTtl(new DecMplsTtlBuilder()
188 | .build())
189 | .build();
190 | }
191 |
192 | public static Action SetMplsTtlAction(Short ttlValue) {
193 | return new SetMplsTtlActionCaseBuilder()
194 | .setSetMplsTtlAction(new SetMplsTtlActionBuilder()
195 | .setMplsTtl(ttlValue)
196 | .build())
197 | .build();
198 | }
199 |
200 | public static Action setTunnelIdAction(BigInteger tunnelId) {
201 |
202 | SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
203 |
204 | // Build the Set Tunnel Field Action
205 | TunnelBuilder tunnel = new TunnelBuilder();
206 | tunnel.setTunnelId(tunnelId);
207 | setFieldBuilder.setTunnel(tunnel.build());
208 |
209 | return new SetFieldCaseBuilder()
210 | .setSetField(setFieldBuilder.build())
211 | .build();
212 | }
213 |
214 | /**
215 | * Accepts a MAC address and returns the corresponding long, where the
216 | * MAC bytes are set on the lower order bytes of the long.
217 | * @param macAddress
218 | * @return a long containing the mac address bytes
219 | */
220 | public static long toLong(byte[] macAddress) {
221 | long mac = 0;
222 | for (int i = 0; i < 6; i++) {
223 | long t = (macAddress[i] & 0xffL) << ((5-i)*8);
224 | mac |= t;
225 | }
226 | return mac;
227 | }
228 |
229 | /**
230 | * Accepts a MAC address of the form 00:aa:11:bb:22:cc, case does not
231 | * matter, and returns the corresponding long, where the MAC bytes are set
232 | * on the lower order bytes of the long.
233 | *
234 | * @param macAddress
235 | * in String format
236 | * @return a long containing the mac address bytes
237 | */
238 | public static long toLong(MacAddress macAddress) {
239 | return toLong(toMACAddress(macAddress.getValue()));
240 | }
241 |
242 | /**
243 | * Accepts a MAC address of the form 00:aa:11:bb:22:cc, case does not
244 | * matter, and returns a corresponding byte[].
245 | * @param macAddress
246 | * @return
247 | */
248 | public static byte[] toMACAddress(String macAddress) {
249 | final String HEXES = "0123456789ABCDEF";
250 | byte[] address = new byte[6];
251 | String[] macBytes = macAddress.split(":");
252 | if (macBytes.length != 6)
253 | throw new IllegalArgumentException(
254 | "Specified MAC Address must contain 12 hex digits" +
255 | " separated pairwise by :'s.");
256 | for (int i = 0; i < 6; ++i) {
257 | address[i] = (byte) ((HEXES.indexOf(macBytes[i].toUpperCase()
258 | .charAt(0)) << 4) | HEXES.indexOf(macBytes[i].toUpperCase()
259 | .charAt(1)));
260 | }
261 | return address;
262 | }
263 | }
264 |
--------------------------------------------------------------------------------
/distribution/karaf-branding/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | org.sdnhub.odl.tutorial.distribution
5 | distribution-parent
6 | 0.1.0-SNAPSHOT
7 |
8 | 4.0.0
9 | karaf-branding
10 | 1.0.0-SNAPSHOT
11 | bundle
12 | SDN Hub tutorial project Karaf branding
13 |
14 |
15 |
16 | org.apache.felix
17 | maven-bundle-plugin
18 | 2.4.0
19 | true
20 |
21 |
22 | ${project.artifactId}
23 | *
24 | !*
25 | org.apache.karaf.branding
26 | *;public-context:=false
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/distribution/karaf-branding/src/main/resources/org/apache/karaf/branding/branding.properties:
--------------------------------------------------------------------------------
1 | welcome = \
2 | \u001B[36m _____ _____ _ _ _ _ _ \u001B[0m\r\n\
3 | \u001B[36m / ____| __ \\| \\ | | | | | | | | \u001B[0m\r\n\
4 | \u001B[36m | (___ | | | | \\| | | |__| |_ _| |__ \u001B[0m\r\n\
5 | \u001B[36m \\___ \\| | | | . ` | | __ | | | | '_ \\ \u001B[0m\r\n\
6 | \u001B[36m ____) | |__| | |\\ | | | | | |_| | |_) |\u001B[0m\r\n\
7 | \u001B[36m |_____/|_____/|_| \\_| |_| |_|\\__,_|_.__/ \u001B[0m\r\n\
8 | \r\n\
9 | Hit '\u001B[1m\u001B[0m' for a list of available commands\r\n\
10 | and '\u001B[1m[cmd] --help\u001B[0m' for help on a specific command.\r\n\
11 | Hit '\u001B[1m\u001B[0m' or type '\u001B[1msystem:shutdown\u001B[0m' or '\u001B[1mlogout\u001B[0m' to shutdown OpenDaylight.\r\n
12 | prompt = \u001B[36mopendaylight-user\u001B[0m\u001B[1m@\u001B[0m\u001B[34m${APPLICATION}\u001B[0m>
13 |
--------------------------------------------------------------------------------
/distribution/opendaylight-karaf/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.sdnhub.odl.tutorial.distribution
6 | distribution-parent
7 | 0.1.0-SNAPSHOT
8 |
9 | packaging
10 | 1.0.0-SNAPSHOT
11 | pom
12 | SDN Hub tutorial project distribution packaging
13 |
14 | 3.2
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | org.apache.karaf.features
23 | framework
24 | ${karaf.version}
25 | kar
26 |
27 |
28 | org.apache.karaf.features
29 | standard
30 | ${karaf.version}
31 | features
32 | xml
33 | runtime
34 |
35 |
36 |
37 |
38 | org.opendaylight.controller
39 | opendaylight-karaf-resources
40 | ${opendaylight-karaf-resources.version}
41 |
42 |
43 | org.sdnhub.odl.tutorial.distribution
44 | karaf-branding
45 | ${karaf-branding.version}
46 |
47 |
48 |
49 |
50 | org.sdnhub.odl.tutorial
51 | features
52 | ${feature.odl.tutorial.version}
53 | features
54 | xml
55 | runtime
56 |
57 |
58 |
59 |
60 | org.opendaylight.l2switch
61 | features-l2switch
62 | ${feature.l2switch.version}
63 | features
64 | xml
65 | runtime
66 |
67 |
68 |
69 | org.opendaylight.dlux
70 | features-dlux
71 | ${feature.dlux.version}
72 | features
73 | xml
74 | runtime
75 |
76 |
77 |
78 | org.opendaylight.aaa
79 | features-aaa
80 | ${feature.aaa.version}
81 | features
82 | xml
83 | runtime
84 |
85 |
86 |
87 | org.opendaylight.aaa
88 | features-aaa-authz
89 | ${feature.aaa.version}
90 | features
91 | xml
92 | runtime
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | org.eclipse.m2e
101 | lifecycle-mapping
102 | 1.0.0
103 |
104 |
105 |
106 |
107 |
108 | org.apache.felix
109 | maven-bundle-plugin
110 | [0,)
111 |
112 | cleanVersions
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | org.apache.maven.plugins
122 | maven-dependency-plugin
123 | [0,)
124 |
125 | copy
126 | unpack
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 | org.apache.karaf.tooling
136 | karaf-maven-plugin
137 | [0,)
138 |
139 | commands-generate-help
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 | org.fusesource.scalate
149 | maven-scalate-plugin
150 | [0,)
151 |
152 | sitegen
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 | org.apache.servicemix.tooling
162 | depends-maven-plugin
163 | [0,)
164 |
165 | generate-depends-file
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 | maven-resources-plugin
181 | 2.6
182 |
183 |
184 | copy-resources
185 |
186 | prepare-package
187 |
188 | copy-resources
189 |
190 |
191 | ${basedir}/target/assembly
192 |
193 |
194 | src/main/assembly
195 |
196 |
197 | true
198 |
199 |
200 |
201 |
202 |
203 | org.apache.karaf.tooling
204 | karaf-maven-plugin
205 | true
206 |
207 |
208 |
209 | standard
210 | sdnhub-tutorial-tapapp
211 |
212 |
213 |
214 |
215 |
216 | populate-system
217 | generate-resources
218 |
219 | features-add-to-repository
220 |
221 |
222 |
223 | mvn:org.apache.karaf.features/standard/${karaf.version}/xml/features
224 |
225 |
226 | standard
227 | config
228 | package
229 | kar
230 | ssh
231 | management
232 | war
233 |
234 | target/assembly/system
235 |
236 |
237 |
238 | process-resources
239 |
240 | install-kars
241 |
242 | process-resources
243 |
244 |
245 | package
246 |
247 | instance-create-archive
248 |
249 |
250 |
251 |
252 |
253 | org.apache.maven.plugins
254 | maven-checkstyle-plugin
255 | ${checkstyle.version}
256 |
257 | **\/target\/,**\/bin\/,**\/target-ide\/,**\/configuration\/initial\/
258 |
259 |
260 |
261 | org.apache.maven.plugins
262 | maven-dependency-plugin
263 | 2.8
264 |
265 |
266 | copy
267 |
268 | copy
269 |
270 |
271 | generate-resources
272 |
273 |
274 |
275 | org.sdnhub.odl.tutorial.distribution
276 | karaf-branding
277 | ${karaf.branding.version}
278 | target/assembly/lib
279 | karaf-branding-${karaf.branding.version}.jar
280 |
281 |
282 |
283 |
284 |
285 | unpack-karaf-resources
286 |
287 | unpack-dependencies
288 |
289 | prepare-package
290 |
291 | ${project.build.directory}/assembly
292 | org.opendaylight.controller
293 | opendaylight-karaf-resources
294 | META-INF\/**
295 | true
296 | false
297 |
298 |
299 |
300 | copy-dependencies
301 | prepare-package
302 |
303 | copy-dependencies
304 |
305 |
306 | ${project.build.directory}/assembly/system
307 | distribution.vtn-coordinator
308 | false
309 | true
310 | true
311 | true
312 | true
313 | true
314 |
315 |
316 |
317 | copy-externalapps
318 | prepare-package
319 |
320 | copy-dependencies
321 |
322 |
323 | ${project.build.directory}/assembly/externalapps
324 | distribution.vtn-coordinator
325 | false
326 | true
327 | true
328 | true
329 |
330 |
331 |
332 |
333 |
334 | org.apache.maven.plugins
335 | maven-antrun-plugin
336 |
337 |
338 | prepare-package
339 |
340 | run
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
--------------------------------------------------------------------------------
/distribution/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | org.sdnhub.odl.tutorial
9 | commons
10 | 1.2.0-SNAPSHOT
11 | ../commons/parent/
12 |
13 |
14 | org.sdnhub.odl.tutorial.distribution
15 | distribution-parent
16 | 0.1.0-SNAPSHOT
17 | pom
18 |
19 |
20 | karaf-branding
21 | opendaylight-karaf
22 |
23 |
24 |
--------------------------------------------------------------------------------
/features/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.sdnhub.odl.tutorial
6 | commons
7 | 1.2.0-SNAPSHOT
8 | ../commons/parent
9 |
10 | features
11 | SDN Hub tutorial project features
12 | 1.0.0-SNAPSHOT
13 | jar
14 |
15 | features.xml
16 |
17 |
18 |
19 |
20 | org.opendaylight.netconf
21 | features-restconf
22 | ${feature.restconf.version}
23 | features
24 | xml
25 |
26 |
27 | org.opendaylight.controller
28 | features-mdsal
29 | ${feature.mdsal.version}
30 | features
31 | xml
32 |
33 |
34 | org.opendaylight.openflowplugin
35 | features-openflowplugin
36 | ${feature.openflowplugin.version}
37 | features
38 | xml
39 |
40 |
41 | org.opendaylight.netconf
42 | features-netconf-connector
43 | ${feature.netconf.connector.version}
44 | features
45 | xml
46 |
47 |
48 |
49 |
50 | org.sdnhub.odl.tutorial.tapapp
51 | tapapp-config
52 | ${tapapp.version}
53 | xml
54 | config
55 |
56 |
57 | org.sdnhub.odl.tutorial.tapapp
58 | tapapp-model
59 | ${tapapp.version}
60 |
61 |
62 | org.sdnhub.odl.tutorial.tapapp
63 | tapapp-impl
64 | ${tapapp.version}
65 |
66 |
67 |
68 | org.sdnhub.odl.tutorial.learning-switch
69 | learning-switch-config
70 | ${learning-switch.version}
71 | xml
72 | config
73 |
74 |
75 | org.sdnhub.odl.tutorial.learning-switch
76 | learning-switch-impl
77 | ${learning-switch.version}
78 |
79 |
80 |
81 | org.sdnhub.odl.tutorial.acl
82 | acl-config
83 | ${acl.version}
84 | xml
85 | config
86 |
87 |
88 | org.sdnhub.odl.tutorial.acl
89 | acl-impl
90 | ${acl.version}
91 |
92 |
93 | org.sdnhub.odl.tutorial.acl
94 | acl-model
95 | ${acl.version}
96 |
97 |
98 |
99 | org.sdnhub.odl.tutorial.netconf-exercise
100 | netconf-exercise-config
101 | ${netconf-exercise.version}
102 | xml
103 | config
104 |
105 |
106 | org.sdnhub.odl.tutorial.netconf-exercise
107 | netconf-exercise-model
108 | ${netconf-exercise.version}
109 |
110 |
111 | org.sdnhub.odl.tutorial.netconf-exercise
112 | netconf-exercise-impl
113 | ${netconf-exercise.version}
114 |
115 |
116 |
117 |
118 |
119 | true
120 | src/main/resources
121 |
122 |
123 |
124 |
125 | org.apache.maven.plugins
126 | maven-resources-plugin
127 |
128 |
129 | filter
130 |
131 | resources
132 |
133 | generate-resources
134 |
135 |
136 |
137 |
138 | org.codehaus.mojo
139 | build-helper-maven-plugin
140 |
141 |
142 | attach-artifacts
143 |
144 | attach-artifact
145 |
146 | package
147 |
148 |
149 |
150 | ${project.build.directory}/classes/${features.file}
151 | xml
152 | features
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 | org.apache.maven.plugins
161 | maven-surefire-plugin
162 |
163 | ${skip.karaf}
164 |
165 | org.opendaylight.controller
166 | opendaylight-karaf-empty
167 | ${opendaylight-karaf-empty.version}
168 |
169 |
172 |
173 |
174 |
175 |
176 |
177 |
--------------------------------------------------------------------------------
/features/src/main/resources/features.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | mvn:org.opendaylight.controller/features-mdsal/${feature.mdsal.version}/xml/features
4 | mvn:org.opendaylight.netconf/features-restconf/${feature.restconf.version}/xml/features
5 | mvn:org.opendaylight.netconf/features-netconf-connector/${feature.netconf.connector.version}/xml/features
6 | mvn:org.opendaylight.openflowplugin/features-openflowplugin/${feature.openflowplugin.version}/xml/features
7 |
8 |
9 | odl-mdsal-broker
10 | odl-netconf-connector-all
11 | mvn:org.sdnhub.odl.tutorial.netconf-exercise/netconf-exercise-impl/${netconf-exercise.version}
12 | mvn:org.sdnhub.odl.tutorial.netconf-exercise/netconf-exercise-model/${netconf-exercise.version}
13 | mvn:org.sdnhub.odl.tutorial.netconf-exercise/netconf-exercise-config/${netconf-exercise.version}/xml/config
14 |
15 |
16 |
17 | odl-openflowplugin-southbound
18 | odl-openflowplugin-flow-services
19 | odl-mdsal-broker
20 | mvn:org.sdnhub.odl.tutorial.tapapp/tapapp-impl/${tapapp.version}
21 | mvn:org.sdnhub.odl.tutorial.tapapp/tapapp-model/${tapapp.version}
22 | mvn:org.sdnhub.odl.tutorial.tapapp/tapapp-config/${tapapp.version}/xml/config
23 |
24 |
25 |
26 | odl-openflowplugin-southbound
27 | odl-openflowplugin-flow-services
28 | odl-mdsal-broker
29 | mvn:org.sdnhub.odl.tutorial.learning-switch/learning-switch-impl/${learning-switch.version}
30 | mvn:org.sdnhub.odl.tutorial.learning-switch/learning-switch-config/${learning-switch.version}/xml/config
31 |
32 |
33 |
34 | odl-openflowplugin-southbound
35 | odl-openflowplugin-flow-services
36 | odl-mdsal-broker
37 | mvn:org.sdnhub.odl.tutorial.acl/acl-impl/${acl.version}
38 | mvn:org.sdnhub.odl.tutorial.acl/acl-model/${acl.version}
39 | mvn:org.sdnhub.odl.tutorial.acl/acl-config/${acl.version}/xml/config
40 |
41 |
42 |
--------------------------------------------------------------------------------
/learning-switch/config/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.sdnhub.odl.tutorial
7 | commons
8 | 1.2.0-SNAPSHOT
9 | ../../commons/parent/pom.xml
10 |
11 |
12 | org.sdnhub.odl.tutorial.learning-switch
13 | learning-switch-config
14 | 1.0.0-SNAPSHOT
15 | SDN Hub tutorial project Learning Switch Config
16 |
17 | jar
18 |
19 |
20 |
21 | org.codehaus.mojo
22 | build-helper-maven-plugin
23 | ${build.plugins.plugin.version}
24 |
25 |
26 | attach-artifacts
27 |
28 | attach-artifact
29 |
30 | package
31 |
32 |
33 |
34 | ${project.build.directory}/classes/initial/${learning-switch.configfile}
35 | xml
36 | config
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/learning-switch/config/src/main/resources/initial/49-learning-switch-config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | prefix:learning-switch-impl
9 | learning-switch-impl
10 |
11 |
12 | binding:binding-notification-service
13 | binding-notification-broker
14 |
15 |
16 | binding:binding-async-data-broker
17 | binding-data-broker
18 |
19 |
20 | binding:binding-rpc-registry
21 | binding-rpc-broker
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | urn:sdnhub:odl:tutorial:learning-switch:learning-switch-impl?module=learning-switch-impl&revision=2015-06-05
30 | urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl?module=openflow-provider-impl&revision=2014-03-26
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/learning-switch/implementation/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.sdnhub.odl.tutorial.learning-switch
6 | learning-switch-parent
7 | 0.1.0-SNAPSHOT
8 |
9 |
10 | learning-switch-impl
11 | SDN Hub tutorial project learning switch Impl
12 | 1.0.0-SNAPSHOT
13 | bundle
14 |
15 |
16 |
17 | org.sdnhub.odl.tutorial
18 | utils
19 | ${utils.version}
20 |
21 |
22 | org.opendaylight.openflowplugin.model
23 | model-flow-service
24 | ${openflowplugin.version}
25 |
26 |
27 |
28 |
29 |
30 | org.opendaylight.yangtools
31 | yang-maven-plugin
32 | ${yangtools.version}
33 |
34 |
35 |
36 | generate-sources
37 |
38 |
39 | src/main/yang
40 |
41 |
42 | org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
43 | ${codeGeneratorPath}
44 |
45 |
46 | org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
47 | ${configCodeGeneratorPath}
48 |
49 | urn:sdnhub:odl:tutorial:learning-switch:learning-switch-impl==org.sdnhub.odl.tutorial.learningswitch.impl
50 | urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
51 |
52 |
53 |
54 | org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl
55 | ${project.build.directory}/site/models
56 |
57 |
58 | true
59 |
60 |
61 |
62 |
63 |
64 | org.opendaylight.mdsal
65 | maven-sal-api-gen-plugin
66 | ${maven-sal-api-gen-plugin.version}
67 | jar
68 |
69 |
70 | org.opendaylight.controller
71 | yang-jmx-generator-plugin
72 | ${yang.jmx.version}
73 |
74 |
75 |
76 |
77 | org.apache.felix
78 | maven-bundle-plugin
79 | 2.4.0
80 | true
81 |
82 |
83 | *
84 | utils
85 |
86 | ${project.basedir}/META-INF
87 |
88 |
89 |
91 |
92 | org.codehaus.mojo
93 | build-helper-maven-plugin
94 | 1.8
95 |
96 |
97 | add-source
98 |
99 | add-source
100 |
101 | generate-sources
102 |
103 |
104 | src/main/yang
105 | ${codeGeneratorPath}
106 | ${configCodeGeneratorPath}
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | maven-clean-plugin
115 |
116 |
117 |
118 | ${codeGeneratorPath}
119 |
120 | **
121 |
122 |
123 |
124 | ${configCodeGeneratorPath}
125 |
126 | **
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
--------------------------------------------------------------------------------
/learning-switch/implementation/src/main/java/org/sdnhub/odl/tutorial/learningswitch/impl/TutorialL2Forwarding.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 SDN Hub
3 |
4 | Licensed under the GNU GENERAL PUBLIC LICENSE, Version 3.
5 | You may not use this file except in compliance with this License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.gnu.org/licenses/gpl-3.0.txt
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 | implied.
14 |
15 | *
16 | */
17 |
18 | package org.sdnhub.odl.tutorial.learningswitch.impl;
19 |
20 | import java.nio.ByteBuffer;
21 | import java.util.HashMap;
22 | import java.util.List;
23 | import java.util.Map;
24 |
25 | import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 | import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 | import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
28 | import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
29 | import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
30 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
31 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
32 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
33 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
34 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
35 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
36 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
37 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
38 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
39 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
40 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
41 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
42 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
43 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
44 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
45 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
46 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
47 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
48 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
49 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
50 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
51 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
52 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
53 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
54 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
55 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
56 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
57 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
58 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
59 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
60 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
61 | import org.opendaylight.yangtools.concepts.Registration;
62 | import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
63 | import org.sdnhub.odl.tutorial.utils.GenericTransactionUtils;
64 | import org.sdnhub.odl.tutorial.utils.PacketParsingUtils;
65 | import org.sdnhub.odl.tutorial.utils.inventory.InventoryUtils;
66 | import org.sdnhub.odl.tutorial.utils.openflow13.MatchUtils;
67 | import org.slf4j.Logger;
68 | import org.slf4j.LoggerFactory;
69 |
70 | import com.google.common.base.Preconditions;
71 | import com.google.common.collect.Lists;
72 |
73 | public class TutorialL2Forwarding implements AutoCloseable, PacketProcessingListener {
74 | private final Logger LOG = LoggerFactory.getLogger(this.getClass());
75 | private final static long FLOOD_PORT_NUMBER = 0xfffffffbL;
76 |
77 | //Members specific to this class
78 | private Map macTable = new HashMap ();
79 | private String function = "hub";
80 |
81 | //Members related to MD-SAL operations
82 | private List registrations;
83 | private DataBroker dataBroker;
84 | private PacketProcessingService packetProcessingService;
85 |
86 | public TutorialL2Forwarding(DataBroker dataBroker, NotificationProviderService notificationService, RpcProviderRegistry rpcProviderRegistry) {
87 | //Store the data broker for reading/writing from inventory store
88 | this.dataBroker = dataBroker;
89 |
90 | //Get access to the packet processing service for making RPC calls later
91 | this.packetProcessingService = rpcProviderRegistry.getRpcService(PacketProcessingService.class);
92 |
93 | //List used to track notification (both data change and YANG-defined) listener registrations
94 | this.registrations = Lists.newArrayList();
95 |
96 | //Register this object for receiving notifications when there are PACKET_INs
97 | registrations.add(notificationService.registerNotificationListener(this));
98 | }
99 |
100 | @Override
101 | public void close() throws Exception {
102 | for (Registration registration : registrations) {
103 | registration.close();
104 | }
105 | registrations.clear();
106 | }
107 |
108 | @Override
109 | public void onPacketReceived(PacketReceived notification) {
110 | LOG.trace("Received packet notification {}", notification.getMatch());
111 |
112 | NodeConnectorRef ingressNodeConnectorRef = notification.getIngress();
113 | NodeRef ingressNodeRef = InventoryUtils.getNodeRef(ingressNodeConnectorRef);
114 | NodeConnectorId ingressNodeConnectorId = InventoryUtils.getNodeConnectorId(ingressNodeConnectorRef);
115 | NodeId ingressNodeId = InventoryUtils.getNodeId(ingressNodeConnectorRef);
116 |
117 | // Useful to create it beforehand
118 | NodeConnectorId floodNodeConnectorId = InventoryUtils.getNodeConnectorId(ingressNodeId, FLOOD_PORT_NUMBER);
119 | NodeConnectorRef floodNodeConnectorRef = InventoryUtils.getNodeConnectorRef(floodNodeConnectorId);
120 |
121 | /*
122 | * Logic:
123 | * 0. Ignore LLDP packets
124 | * 1. If behaving as "hub", perform a PACKET_OUT with FLOOD action
125 | * 2. Else if behaving as "learning switch",
126 | * 2.1. Extract MAC addresses
127 | * 2.2. Update MAC table with source MAC address
128 | * 2.3. Lookup in MAC table for the target node connector of dst_mac
129 | * 2.3.1 If found,
130 | * 2.3.1.1 perform FLOW_MOD for that dst_mac through the target node connector
131 | * 2.3.1.2 perform PACKET_OUT of this packet to target node connector
132 | * 2.3.2 If not found, perform a PACKET_OUT with FLOOD action
133 | */
134 |
135 | //Ignore LLDP packets, or you will be in big trouble
136 | byte[] etherTypeRaw = PacketParsingUtils.extractEtherType(notification.getPayload());
137 | int etherType = (0x0000ffff & ByteBuffer.wrap(etherTypeRaw).getShort());
138 | if (etherType == 0x88cc) {
139 | return;
140 | }
141 |
142 | // Hub implementation
143 | if (function.equals("hub")) {
144 |
145 | //flood packet (1)
146 | packetOut(ingressNodeRef, floodNodeConnectorRef, notification.getPayload());
147 | } else {
148 | //TODO: Extract payload
149 |
150 | //TODO: Extract MAC address (2.1)
151 | byte[] payload = notification.getPayload();
152 | byte[] dstMacRaw = PacketParsingUtils.extractDstMac(payload);
153 | byte[] srcMacRaw = PacketParsingUtils.extractSrcMac(payload);
154 |
155 | String srcMac = PacketParsingUtils.rawMacToString(srcMacRaw);
156 | String dstMac = PacketParsingUtils.rawMacToString(dstMacRaw);
157 |
158 | //TODO: Learn source MAC address (2.2)
159 |
160 | //TODO: Lookup destination MAC address in table (2.3)
161 | NodeConnectorId egressNodeConnectorId = null;
162 |
163 | //TODO: If found (2.3.1)
164 | if (egressNodeConnectorId != null) {
165 | //TODO: 2.3.1.1 perform FLOW_MOD for that dst_mac through the target node connector
166 | //TODO: 2.3.1.2 perform PACKET_OUT of this packet to target node connector
167 | } else {
168 | //2.3.2 Flood packet
169 | packetOut(ingressNodeRef, floodNodeConnectorRef, payload);
170 | }
171 | }
172 | }
173 |
174 | private void packetOut(NodeRef egressNodeRef, NodeConnectorRef egressNodeConnectorRef, byte[] payload) {
175 | Preconditions.checkNotNull(packetProcessingService);
176 | LOG.debug("Flooding packet of size {} out of port {}", payload.length, egressNodeConnectorRef);
177 |
178 | //Construct input for RPC call to packet processing service
179 | TransmitPacketInput input = new TransmitPacketInputBuilder()
180 | .setPayload(payload)
181 | .setNode(egressNodeRef)
182 | .setEgress(egressNodeConnectorRef)
183 | .build();
184 | packetProcessingService.transmitPacket(input);
185 | }
186 |
187 | private void programL2Flow(NodeId nodeId, String dstMac, NodeConnectorId ingressNodeConnectorId, NodeConnectorId egressNodeConnectorId) {
188 |
189 | /* Programming a flow involves:
190 | * 1. Creating a Flow object that has a match and a list of instructions,
191 | * 2. Adding Flow object as an augmentation to the Node object in the inventory.
192 | * 3. FlowProgrammer module of OpenFlowPlugin will pick up this data change and eventually program the switch.
193 | */
194 |
195 | //Creating match object
196 | MatchBuilder matchBuilder = new MatchBuilder();
197 | //MatchUtils.createEthDstMatch(matchBuilder, ..., null);
198 | //MatchUtils.createInPortMatch(matchBuilder, ...);
199 |
200 | /*
201 | * Instructions List Stores Individual Instructions
202 | InstructionsBuilder isb = new InstructionsBuilder();
203 | List instructions = Lists.newArrayList();
204 | InstructionBuilder ib = new InstructionBuilder();
205 | ApplyActionsBuilder aab = new ApplyActionsBuilder();
206 | ActionBuilder ab = new ActionBuilder();
207 | List actionList = Lists.newArrayList();
208 | */
209 |
210 | /*
211 | * Set output action
212 | OutputActionBuilder output = new OutputActionBuilder();
213 | output.setOutputNodeConnector(egressNodeConnectorId);
214 | output.setMaxLength(65535); //Send full packet and No buffer
215 | ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
216 | ab.setOrder(0);
217 | ab.setKey(new ActionKey(0));
218 | actionList.add(ab.build());
219 | */
220 |
221 | /*
222 | * Create Apply Actions Instruction
223 | aab.setAction(actionList);
224 | ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
225 | ib.setOrder(0);
226 | ib.setKey(new InstructionKey(0));
227 | instructions.add(ib.build());
228 | */
229 |
230 | /*
231 | * Create Flow
232 | String flowId = "L2_Rule_" + dstMac;
233 | FlowBuilder flowBuilder = new FlowBuilder();
234 | flowBuilder.setMatch(matchBuilder.build());
235 | flowBuilder.setId(new FlowId(flowId));
236 | FlowKey key = new FlowKey(new FlowId(flowId));
237 | flowBuilder.setBarrier(true);
238 | flowBuilder.setTableId((short)0);
239 | flowBuilder.setKey(key);
240 | flowBuilder.setPriority(32768);
241 | flowBuilder.setFlowName(flowId);
242 | flowBuilder.setHardTimeout(0);
243 | flowBuilder.setIdleTimeout(0);
244 | flowBuilder.setInstructions(isb.setInstruction(instructions).build());
245 | */
246 |
247 | /* Perform transaction to store rule
248 | *
249 | InstanceIdentifier flowIID = InstanceIdentifier.builder(Nodes.class)
250 | .child(Node.class, new NodeKey(nodeId))
251 | .augmentation(FlowCapableNode.class)
252 | .child(Table.class, new TableKey(flowBuilder.getTableId()))
253 | .child(Flow.class, flowBuilder.getKey())
254 | .build();
255 | GenericTransactionUtils.writeData(dataBroker, LogicalDatastoreType.CONFIGURATION, flowIID, flowBuilder.build(), true);
256 | */
257 | }
258 | }
259 |
--------------------------------------------------------------------------------
/learning-switch/implementation/src/main/java/org/sdnhub/odl/tutorial/learningswitch/impl/TutorialL2Forwarding.single_switch.solution:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 SDN Hub
3 |
4 | Licensed under the GNU GENERAL PUBLIC LICENSE, Version 3.
5 | You may not use this file except in compliance with this License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.gnu.org/licenses/gpl-3.0.txt
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 | implied.
14 |
15 | *
16 | */
17 |
18 | package org.sdnhub.odl.tutorial.learningswitch.impl;
19 |
20 | import java.nio.ByteBuffer;
21 | import java.util.HashMap;
22 | import java.util.List;
23 | import java.util.Map;
24 |
25 | import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 | import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 | import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
28 | import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
29 | import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
30 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
31 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
32 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
33 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
34 | import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
35 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
36 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
37 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
38 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
39 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
40 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
41 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
42 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
43 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
44 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
45 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
46 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
47 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
48 | import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
49 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
50 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
51 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
52 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
53 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
54 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
55 | import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
56 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
57 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
58 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
59 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
60 | import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
61 | import org.opendaylight.yangtools.concepts.Registration;
62 | import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
63 | import org.sdnhub.odl.tutorial.utils.GenericTransactionUtils;
64 | import org.sdnhub.odl.tutorial.utils.PacketParsingUtils;
65 | import org.sdnhub.odl.tutorial.utils.inventory.InventoryUtils;
66 | import org.sdnhub.odl.tutorial.utils.openflow13.MatchUtils;
67 | import org.slf4j.Logger;
68 | import org.slf4j.LoggerFactory;
69 |
70 | import com.google.common.base.Preconditions;
71 | import com.google.common.collect.Lists;
72 |
73 | public class TutorialL2Forwarding implements AutoCloseable, PacketProcessingListener {
74 | private final Logger LOG = LoggerFactory.getLogger(this.getClass());
75 | private final static long FLOOD_PORT_NUMBER = 0xfffffffbL;
76 |
77 | //Members specific to this class
78 | private Map macTable = new HashMap ();
79 | private String function = "hub";
80 |
81 | //Members related to MD-SAL operations
82 | private List registrations;
83 | private DataBroker dataBroker;
84 | private PacketProcessingService packetProcessingService;
85 |
86 | public TutorialL2Forwarding(DataBroker dataBroker, NotificationProviderService notificationService, RpcProviderRegistry rpcProviderRegistry) {
87 | //Store the data broker for reading/writing from inventory store
88 | this.dataBroker = dataBroker;
89 |
90 | //Get access to the packet processing service for making RPC calls later
91 | this.packetProcessingService = rpcProviderRegistry.getRpcService(PacketProcessingService.class);
92 |
93 | //List used to track notification (both data change and YANG-defined) listener registrations
94 | this.registrations = Lists.newArrayList();
95 |
96 | //Register this object for receiving notifications when there are PACKET_INs
97 | registrations.add(notificationService.registerNotificationListener(this));
98 | }
99 |
100 | @Override
101 | public void close() throws Exception {
102 | for (Registration registration : registrations) {
103 | registration.close();
104 | }
105 | registrations.clear();
106 | }
107 |
108 | @Override
109 | public void onPacketReceived(PacketReceived notification) {
110 | LOG.trace("Received packet notification {}", notification.getMatch());
111 |
112 | NodeConnectorRef ingressNodeConnectorRef = notification.getIngress();
113 | NodeRef ingressNodeRef = InventoryUtils.getNodeRef(ingressNodeConnectorRef);
114 | NodeConnectorId ingressNodeConnectorId = InventoryUtils.getNodeConnectorId(ingressNodeConnectorRef);
115 | NodeId ingressNodeId = InventoryUtils.getNodeId(ingressNodeConnectorRef);
116 |
117 | // Useful to create it beforehand
118 | NodeConnectorId floodNodeConnectorId = InventoryUtils.getNodeConnectorId(ingressNodeId, FLOOD_PORT_NUMBER);
119 | NodeConnectorRef floodNodeConnectorRef = InventoryUtils.getNodeConnectorRef(floodNodeConnectorId);
120 |
121 | /*
122 | * Logic:
123 | * 0. Ignore LLDP packets
124 | * 1. If behaving as "hub", perform a PACKET_OUT with FLOOD action
125 | * 2. Else if behaving as "learning switch",
126 | * 2.1. Extract MAC addresses
127 | * 2.2. Update MAC table with source MAC address
128 | * 2.3. Lookup in MAC table for the target node connector of dst_mac
129 | * 2.3.1 If found,
130 | * 2.3.1.1 perform FLOW_MOD for that dst_mac through the target node connector
131 | * 2.3.1.2 perform PACKET_OUT of this packet to target node connector
132 | * 2.3.2 If not found, perform a PACKET_OUT with FLOOD action
133 | */
134 |
135 | //Ignore LLDP packets, or you will be in big trouble
136 | byte[] etherTypeRaw = PacketParsingUtils.extractEtherType(notification.getPayload());
137 | int etherType = (0x0000ffff & ByteBuffer.wrap(etherTypeRaw).getShort());
138 | if (etherType == 0x88cc) {
139 | return;
140 | }
141 |
142 | // Hub implementation
143 | if (function.equals("hub")) {
144 |
145 | //flood packet (1)
146 | packetOut(ingressNodeRef, floodNodeConnectorRef, notification.getPayload());
147 | } else {
148 | byte[] payload = notification.getPayload();
149 | byte[] dstMacRaw = PacketParsingUtils.extractDstMac(payload);
150 | byte[] srcMacRaw = PacketParsingUtils.extractSrcMac(payload);
151 |
152 | //Extract MAC addresses (2.1)
153 | String srcMac = PacketParsingUtils.rawMacToString(srcMacRaw);
154 | String dstMac = PacketParsingUtils.rawMacToString(dstMacRaw);
155 |
156 | //Learn source MAC address (2.2)
157 | this.macTable.put(srcMac, ingressNodeConnectorId);
158 |
159 | //Lookup destination MAC address in table (2.3)
160 | NodeConnectorId egressNodeConnectorId = this.macTable.get(dstMac) ;
161 |
162 | //If found (2.3.1)
163 | if (egressNodeConnectorId != null) {
164 | programL2Flow(ingressNodeId, dstMac, ingressNodeConnectorId, egressNodeConnectorId);
165 | NodeConnectorRef egressNodeConnectorRef = InventoryUtils.getNodeConnectorRef(egressNodeConnectorId);
166 | packetOut(ingressNodeRef, egressNodeConnectorRef, payload);
167 | } else {
168 | //2.3.2 Flood packet
169 | packetOut(ingressNodeRef, floodNodeConnectorRef, payload);
170 | }
171 | }
172 | }
173 |
174 | private void packetOut(NodeRef egressNodeRef, NodeConnectorRef egressNodeConnectorRef, byte[] payload) {
175 | Preconditions.checkNotNull(packetProcessingService);
176 | LOG.debug("Flooding packet of size {} out of port {}", payload.length, egressNodeConnectorRef);
177 |
178 | //Construct input for RPC call to packet processing service
179 | TransmitPacketInput input = new TransmitPacketInputBuilder()
180 | .setPayload(payload)
181 | .setNode(egressNodeRef)
182 | .setEgress(egressNodeConnectorRef)
183 | .build();
184 | packetProcessingService.transmitPacket(input);
185 | }
186 |
187 | private void programL2Flow(NodeId nodeId, String dstMac, NodeConnectorId ingressNodeConnectorId, NodeConnectorId egressNodeConnectorId) {
188 |
189 | /* Programming a flow involves:
190 | * 1. Creating a Flow object that has a match and a list of instructions,
191 | * 2. Adding Flow object as an augmentation to the Node object in the inventory.
192 | * 3. FlowProgrammer module of OpenFlowPlugin will pick up this data change and eventually program the switch.
193 | */
194 |
195 | //Creating match object
196 | MatchBuilder matchBuilder = new MatchBuilder();
197 | MatchUtils.createEthDstMatch(matchBuilder, new MacAddress(dstMac), null);
198 | MatchUtils.createInPortMatch(matchBuilder, ingressNodeConnectorId);
199 |
200 | // Instructions List Stores Individual Instructions
201 | InstructionsBuilder isb = new InstructionsBuilder();
202 | List instructions = Lists.newArrayList();
203 | InstructionBuilder ib = new InstructionBuilder();
204 | ApplyActionsBuilder aab = new ApplyActionsBuilder();
205 | ActionBuilder ab = new ActionBuilder();
206 | List actionList = Lists.newArrayList();
207 |
208 | // Set output action
209 | OutputActionBuilder output = new OutputActionBuilder();
210 | output.setOutputNodeConnector(egressNodeConnectorId);
211 | output.setMaxLength(65535); //Send full packet and No buffer
212 | ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
213 | ab.setOrder(0);
214 | ab.setKey(new ActionKey(0));
215 | actionList.add(ab.build());
216 |
217 | // Create Apply Actions Instruction
218 | aab.setAction(actionList);
219 | ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
220 | ib.setOrder(0);
221 | ib.setKey(new InstructionKey(0));
222 | instructions.add(ib.build());
223 |
224 | // Create Flow
225 | FlowBuilder flowBuilder = new FlowBuilder();
226 | flowBuilder.setMatch(matchBuilder.build());
227 |
228 | String flowId = "L2_Rule_" + dstMac;
229 | flowBuilder.setId(new FlowId(flowId));
230 | FlowKey key = new FlowKey(new FlowId(flowId));
231 | flowBuilder.setBarrier(true);
232 | flowBuilder.setTableId((short)0);
233 | flowBuilder.setKey(key);
234 | flowBuilder.setPriority(32768);
235 | flowBuilder.setFlowName(flowId);
236 | flowBuilder.setHardTimeout(0);
237 | flowBuilder.setIdleTimeout(0);
238 | flowBuilder.setInstructions(isb.setInstruction(instructions).build());
239 |
240 | InstanceIdentifier flowIID = InstanceIdentifier.builder(Nodes.class)
241 | .child(Node.class, new NodeKey(nodeId))
242 | .augmentation(FlowCapableNode.class)
243 | .child(Table.class, new TableKey(flowBuilder.getTableId()))
244 | .child(Flow.class, flowBuilder.getKey())
245 | .build();
246 | GenericTransactionUtils.writeData(dataBroker, LogicalDatastoreType.CONFIGURATION, flowIID, flowBuilder.build(), true);
247 | }
248 | }
249 |
--------------------------------------------------------------------------------
/learning-switch/implementation/src/main/java/org/sdnhub/odl/tutorial/learningswitch/impl/TutorialLearningSwitchModule.java:
--------------------------------------------------------------------------------
1 | package org.sdnhub.odl.tutorial.learningswitch.impl;
2 |
3 | import org.opendaylight.controller.md.sal.binding.api.DataBroker;
4 | import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
5 | import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | public class TutorialLearningSwitchModule extends org.sdnhub.odl.tutorial.learningswitch.impl.AbstractTutorialLearningSwitchModule {
10 | private final Logger LOG = LoggerFactory.getLogger(this.getClass());
11 |
12 | public TutorialLearningSwitchModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
13 | super(identifier, dependencyResolver);
14 | }
15 |
16 | public TutorialLearningSwitchModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.sdnhub.odl.tutorial.learningswitch.impl.TutorialLearningSwitchModule oldModule, java.lang.AutoCloseable oldInstance) {
17 | super(identifier, dependencyResolver, oldModule, oldInstance);
18 | }
19 |
20 | @Override
21 | public void customValidation() {
22 | // add custom validation form module attributes here.
23 | }
24 |
25 | @Override
26 | public java.lang.AutoCloseable createInstance() {
27 | //Get all MD-SAL provider objects
28 | DataBroker dataBroker = getDataBrokerDependency();
29 | RpcProviderRegistry rpcRegistry = getRpcRegistryDependency();
30 | NotificationProviderService notificationService = getNotificationServiceDependency();
31 |
32 | TutorialL2Forwarding tutorialL2Forwarding = new TutorialL2Forwarding(dataBroker, notificationService, rpcRegistry);
33 | LOG.info("Tutorial Learning Switch (instance {}) initialized.", tutorialL2Forwarding);
34 | return tutorialL2Forwarding;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/learning-switch/implementation/src/main/java/org/sdnhub/odl/tutorial/learningswitch/impl/TutorialLearningSwitchModuleFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Generated file
3 | *
4 | * Generated from: yang module name: learning-switch-impl yang module local name: learning-switch-impl
5 | * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
6 | * Generated at: Fri Jun 05 11:08:20 PDT 2015
7 | *
8 | * Do not modify this file unless it is present under src/main directory
9 | */
10 | package org.sdnhub.odl.tutorial.learningswitch.impl;
11 | public class TutorialLearningSwitchModuleFactory extends org.sdnhub.odl.tutorial.learningswitch.impl.AbstractTutorialLearningSwitchModuleFactory {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/learning-switch/implementation/src/main/yang/learning-switch-impl.yang:
--------------------------------------------------------------------------------
1 | module learning-switch-impl {
2 | yang-version 1;
3 | namespace "urn:sdnhub:odl:tutorial:learning-switch:learning-switch-impl";
4 | prefix "learning-switch-impl";
5 |
6 | import config { prefix config; revision-date 2013-04-05; }
7 | import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
8 |
9 | description
10 | "This module contains the base YANG definitions for learning-switch-impl.";
11 |
12 | revision "2015-06-05" {
13 | description
14 | "Initial revision.";
15 | }
16 |
17 | // This is the definition of the service implementation as a module identity
18 | identity learning-switch-impl {
19 | base config:module-type;
20 |
21 | // Specifies the prefix for generated java classes.
22 | config:java-name-prefix TutorialLearningSwitch;
23 | }
24 |
25 | // Augments the 'configuration' choice node under modules/module.
26 | augment "/config:modules/config:module/config:configuration" {
27 | case learning-switch-impl {
28 | when "/config:modules/config:module/config:type = 'learning-switch-impl'";
29 |
30 | //wires in the data-broker service
31 | container data-broker {
32 | uses config:service-ref {
33 | refine type {
34 | mandatory true;
35 | config:required-identity mdsal:binding-async-data-broker;
36 | }
37 | }
38 | }
39 | container notification-service {
40 | uses config:service-ref {
41 | refine type {
42 | mandatory false;
43 | config:required-identity mdsal:binding-notification-service;
44 | }
45 | }
46 | }
47 | container rpc-registry {
48 | uses config:service-ref {
49 | refine type {
50 | mandatory true;
51 | config:required-identity mdsal:binding-rpc-registry;
52 | }
53 | }
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/learning-switch/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | org.sdnhub.odl.tutorial
9 | commons
10 | 1.2.0-SNAPSHOT
11 | ../commons/parent/
12 |
13 |
14 | org.sdnhub.odl.tutorial.learning-switch
15 | learning-switch-parent
16 | 0.1.0-SNAPSHOT
17 | pom
18 |
19 |
20 | implementation
21 | config
22 |
23 |
24 |
--------------------------------------------------------------------------------
/netconf-exercise/base_datastore.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/netconf-exercise/config/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.sdnhub.odl.tutorial
7 | commons
8 | 1.2.0-SNAPSHOT
9 | ../../commons/parent/pom.xml
10 |
11 |
12 | org.sdnhub.odl.tutorial.netconf-exercise
13 | netconf-exercise-config
14 | 1.0.0-SNAPSHOT
15 | SDN Hub tutorial Project Netconf exercise Config
16 |
17 | jar
18 |
19 |
20 |
21 | org.codehaus.mojo
22 | build-helper-maven-plugin
23 | ${build.plugins.plugin.version}
24 |
25 |
26 | attach-artifacts
27 |
28 | attach-artifact
29 |
30 | package
31 |
32 |
33 |
34 | ${project.build.directory}/classes/initial/${netconf-exercise.configfile}
35 | xml
36 | config
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/netconf-exercise/config/src/main/resources/initial/51-netconf-exercise-config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | prefix:netconf-exercise-impl
9 | netconf-exercise-impl
10 |
11 |
12 | binding:binding-broker-osgi-registry
13 | binding-osgi-broker
14 |
15 |
16 |
17 | binding:binding-notification-service
18 | binding-notification-broker
19 |
20 |
21 | binding:binding-async-data-broker
22 | binding-data-broker
23 |
24 |
25 | binding:binding-rpc-registry
26 | binding-rpc-broker
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | urn:sdnhub:odl:tutorial:netconf-exercise:netconf-exercise-impl?module=netconf-exercise-impl&revision=2015-08-31
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/netconf-exercise/implementation/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.sdnhub.odl.tutorial.netconf-exercise
6 | netconf-exercise-parent
7 | 0.1.0-SNAPSHOT
8 |
9 |
10 | netconf-exercise-impl
11 | SDN Hub tutorial project Netconf exercise Impl
12 | 1.0.0-SNAPSHOT
13 | bundle
14 |
15 |
16 |
17 | org.opendaylight.netconf
18 | sal-netconf-connector
19 | ${sal-netconf-connector.version}
20 |
21 |
22 | org.opendaylight.controller.model
23 | model-topology
24 | ${controller-model.version}
25 |
26 |
27 | org.sdnhub.odl.tutorial
28 | utils
29 | ${utils.version}
30 |
31 |
32 | org.sdnhub.odl.tutorial.netconf-exercise
33 | netconf-exercise-model
34 | ${netconf-exercise.version}
35 |
36 |
37 |
38 |
39 |
40 | org.opendaylight.yangtools
41 | yang-maven-plugin
42 | ${yangtools.version}
43 |
44 |
45 |
46 | generate-sources
47 |
48 |
49 | src/main/yang
50 |
51 |
52 | org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
53 | ${codeGeneratorPath}
54 |
55 |
56 | org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
57 | ${configCodeGeneratorPath}
58 |
59 | urn:sdnhub:odl:tutorial:netconf-exercise:netconf-exercise-impl==org.sdnhub.odl.tutorial.netconf.exercise.impl
60 | urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
61 |
62 |
63 |
64 | org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl
65 | ${project.build.directory}/site/models
66 |
67 |
68 | true
69 |
70 |
71 |
72 |
73 |
74 | org.opendaylight.mdsal
75 | maven-sal-api-gen-plugin
76 | ${maven-sal-api-gen-plugin.version}
77 | jar
78 |
79 |
80 | org.opendaylight.controller
81 | yang-jmx-generator-plugin
82 | ${yang.jmx.version}
83 |
84 |
85 |
86 |
87 | org.apache.felix
88 | maven-bundle-plugin
89 | 2.4.0
90 | true
91 |
92 |
93 | *
94 | utils
95 |
96 | ${project.basedir}/META-INF
97 |
98 |
99 |
101 |
102 | org.codehaus.mojo
103 | build-helper-maven-plugin
104 | 1.8
105 |
106 |
107 | add-source
108 |
109 | add-source
110 |
111 | generate-sources
112 |
113 |
114 | src/main/yang
115 | ${codeGeneratorPath}
116 | ${configCodeGeneratorPath}
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | maven-clean-plugin
125 |
126 |
127 |
128 | ${codeGeneratorPath}
129 |
130 | **
131 |
132 |
133 |
134 | ${configCodeGeneratorPath}
135 |
136 | **
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/netconf-exercise/implementation/src/main/java/org/sdnhub/odl/tutorial/netconf/exercise/impl/MyRouterOrchestrator.java:
--------------------------------------------------------------------------------
1 | package org.sdnhub.odl.tutorial.netconf.exercise.impl;
2 |
3 | import java.util.List;
4 | import java.util.Map;
5 | import java.util.concurrent.Executors;
6 | import java.util.concurrent.ScheduledExecutorService;
7 | import java.util.concurrent.TimeUnit;
8 |
9 | import org.opendaylight.controller.md.sal.binding.api.DataBroker;
10 | import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
11 | import org.opendaylight.controller.md.sal.binding.api.MountPoint;
12 | import org.opendaylight.controller.md.sal.binding.api.MountPointService;
13 | import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
14 | import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
15 | import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 | import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
17 | import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
18 | import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
19 | import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
20 | import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
21 | import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
22 | import org.opendaylight.yang.gen.v1.urn.sdnhub.odl.tutorial.router.rev150728.Interfaces;
23 | import org.opendaylight.yang.gen.v1.urn.sdnhub.odl.tutorial.router.rev150728.InterfacesBuilder;
24 | import org.opendaylight.yang.gen.v1.urn.sdnhub.odl.tutorial.router.rev150728.InterfacesKey;
25 | import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
26 | import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
27 | import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
28 | import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
29 | import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
30 | import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
31 | import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
32 | import org.opendaylight.yangtools.concepts.Registration;
33 | import org.opendaylight.yangtools.yang.binding.DataObject;
34 | import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 | import org.sdnhub.odl.tutorial.utils.GenericTransactionUtils;
36 | import org.slf4j.Logger;
37 | import org.slf4j.LoggerFactory;
38 |
39 | import com.google.common.base.Optional;
40 | import com.google.common.collect.Lists;
41 |
42 | public class MyRouterOrchestrator implements BindingAwareProvider, AutoCloseable, DataChangeListener {
43 | private final Logger LOG = LoggerFactory.getLogger(this.getClass());
44 |
45 | //Members related to MD-SAL operations
46 | private List registrations = Lists.newArrayList();
47 | private MountPointService mountService;
48 |
49 | public MyRouterOrchestrator(BindingAwareBroker bindingAwareBroker, DataBroker dataBroker, NotificationProviderService notificationService, RpcProviderRegistry rpcProviderRegistry) {
50 | //Register this object as a provider for receiving session context
51 | bindingAwareBroker.registerProvider(this);
52 |
53 | //Register this object as listener for changes in netconf topology
54 | InstanceIdentifier netconfTopoIID = InstanceIdentifier.builder(NetworkTopology.class)
55 | .child(Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName())))
56 | .build();
57 | registrations.add(dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, netconfTopoIID.child(Node.class), this, DataChangeScope.SUBTREE));
58 | }
59 |
60 | @Override
61 | public void onSessionInitiated(ProviderContext session) {
62 | // Get the mount service provider
63 | this.mountService = session.getSALService(MountPointService.class);
64 | }
65 |
66 | public void close() throws Exception {
67 | for (Registration registration : registrations) {
68 | registration.close();
69 | }
70 | registrations.clear();
71 | }
72 |
73 | @Override
74 | public void onDataChanged(AsyncDataChangeEvent, DataObject> change) {
75 | LOG.debug("Data changed: {} created, {} updated, {} removed",
76 | change.getCreatedData().size(), change.getUpdatedData().size(), change.getRemovedPaths().size());
77 |
78 | DataObject dataObject;
79 |
80 | // Iterate over any created nodes
81 | for (Map.Entry, DataObject> entry : change.getCreatedData().entrySet()) {
82 | dataObject = entry.getValue();
83 | if (dataObject instanceof Node) {
84 | LOG.debug("ADDED Path {}, Object {}", entry.getKey(), dataObject);
85 | NodeId nodeId = entry.getKey().firstKeyOf(Node.class, NodeKey.class).getNodeId();
86 | final String routerName = nodeId.getValue();
87 |
88 | //Add interface configs 2 seconds later to give the mount point time to settle down
89 | final ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);
90 | exec.schedule(new Runnable(){
91 | @Override
92 | public void run(){
93 | //Configure interfaces for each router we care about
94 | if (routerName.equals("router1")) {
95 | configureRouterInterface(routerName, "eth0", "10.10.1.1/24");
96 | configureRouterInterface(routerName, "eth1", "100.100.100.1/24");
97 | } else if (routerName.equals("router2")) {
98 | configureRouterInterface(routerName, "eth0", "10.10.1.2/24");
99 | configureRouterInterface(routerName, "eth1", "100.100.100.2/24");
100 | }
101 | }
102 | }, 2, TimeUnit.SECONDS);
103 | }
104 | }
105 |
106 | // Iterate over any deleted nodes
107 | Map, DataObject> originalData = change.getOriginalData();
108 | for (InstanceIdentifier> path : change.getRemovedPaths()) {
109 | dataObject = originalData.get(path);
110 | if (dataObject instanceof Node) {
111 | LOG.debug("REMOVED Path {}, Object {}", path, dataObject);
112 | }
113 | }
114 |
115 | //FIXME: Handle relevant updates
116 | }
117 |
118 | /*
119 | * In this method, we write data to a data store location referenced by the REST URL
120 | /restconf/config/network-topology:network-topology/topology/topology-netconf
121 | /node//yang-ext:mount
122 | /router:interfaces/
123 | *
124 | */
125 | private void configureRouterInterface(String routerName, String interfaceName, String subnetPrefix) {
126 | LOG.debug("Configuring interface {} for {}", interfaceName, routerName);
127 |
128 | //Step 1: Get access to mount point
129 | InstanceIdentifier netconfNodeIID = InstanceIdentifier.builder(NetworkTopology.class)
130 | .child(Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName())))
131 | .child(Node.class, new NodeKey(new NodeId(routerName)))
132 | .build();
133 | final Optional netconfNodeOptional = mountService.getMountPoint(netconfNodeIID);
134 |
135 | //Step 2: Write to the mount point
136 | if (netconfNodeOptional.isPresent()) {
137 |
138 | //Step 2.1: access data broker within this mount point
139 | MountPoint netconfNode = netconfNodeOptional.get();
140 | DataBroker netconfNodeDataBroker = netconfNode.getService(DataBroker.class).get();
141 |
142 | //Step 2.2: construct data and the relative iid
143 | InterfacesBuilder builder = new InterfacesBuilder()
144 | .setId(interfaceName)
145 | .setKey(new InterfacesKey(interfaceName))
146 | .setIpAddress(subnetPrefix);
147 | InstanceIdentifier interfacesIID = InstanceIdentifier
148 | .builder(Interfaces.class, builder.getKey())
149 | .build();
150 |
151 | //Step 2.3: write to the config data store
152 | GenericTransactionUtils.writeData(netconfNodeDataBroker, LogicalDatastoreType.CONFIGURATION, interfacesIID, builder.build(), true);
153 |
154 | } else {
155 | LOG.warn("Mount point not ready for {}", routerName);
156 | }
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/netconf-exercise/implementation/src/main/java/org/sdnhub/odl/tutorial/netconf/exercise/impl/TutorialNetconfExerciseModule.java:
--------------------------------------------------------------------------------
1 | package org.sdnhub.odl.tutorial.netconf.exercise.impl;
2 |
3 | import org.opendaylight.controller.md.sal.binding.api.DataBroker;
4 | import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
5 | import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
6 | import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import com.google.common.base.Preconditions;
11 |
12 | public class TutorialNetconfExerciseModule extends AbstractTutorialNetconfExerciseModule {
13 | private final Logger LOG = LoggerFactory.getLogger(this.getClass());
14 |
15 | public TutorialNetconfExerciseModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
16 | super(identifier, dependencyResolver);
17 | }
18 |
19 | public TutorialNetconfExerciseModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, AbstractTutorialNetconfExerciseModule oldModule, java.lang.AutoCloseable oldInstance) {
20 | super(identifier, dependencyResolver, oldModule, oldInstance);
21 | }
22 |
23 | @Override
24 | public void customValidation() {
25 | // add custom validation form module attributes here.
26 | }
27 |
28 | @Override
29 | public java.lang.AutoCloseable createInstance() {
30 | BindingAwareBroker bindingAwareBroker = getBindingAwareBrokerDependency();
31 | DataBroker dataBrokerService = getDataBrokerDependency();
32 | RpcProviderRegistry rpcProviderRegistry = getRpcRegistryDependency();
33 | NotificationProviderService notificationService = getNotificationServiceDependency();
34 |
35 | Preconditions.checkNotNull(bindingAwareBroker);
36 | Preconditions.checkNotNull(dataBrokerService);
37 | Preconditions.checkNotNull(rpcProviderRegistry);
38 | Preconditions.checkNotNull(notificationService);
39 |
40 | MyRouterOrchestrator orchestrator = new MyRouterOrchestrator(bindingAwareBroker, dataBrokerService, notificationService, rpcProviderRegistry);
41 | LOG.info("Tutorial NetconfExercise (instance {}) initialized.", orchestrator);
42 | return orchestrator;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/netconf-exercise/implementation/src/main/java/org/sdnhub/odl/tutorial/netconf/exercise/impl/TutorialNetconfExerciseModuleFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Generated file
3 | *
4 | * Generated from: yang module name: netconf-exercise-impl yang module local name: netconf-exercise-impl
5 | * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
6 | * Generated at: Mon Aug 31 22:01:26 PDT 2015
7 | *
8 | * Do not modify this file unless it is present under src/main directory
9 | */
10 | package org.sdnhub.odl.tutorial.netconf.exercise.impl;
11 | public class TutorialNetconfExerciseModuleFactory extends org.sdnhub.odl.tutorial.netconf.exercise.impl.AbstractTutorialNetconfExerciseModuleFactory {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/netconf-exercise/implementation/src/main/yang/netconf-exercise.yang:
--------------------------------------------------------------------------------
1 | module netconf-exercise-impl {
2 | yang-version 1;
3 | namespace "urn:sdnhub:odl:tutorial:netconf-exercise:netconf-exercise-impl";
4 | prefix "netconf-exercise-impl";
5 |
6 | import config { prefix config; revision-date 2013-04-05; }
7 | import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
8 |
9 | description
10 | "This module contains the base YANG definitions for netconf-exercise-impl.";
11 |
12 | revision "2015-08-31" {
13 | description
14 | "Initial revision.";
15 | }
16 |
17 | // This is the definition of the service implementation as a module identity
18 | identity netconf-exercise-impl {
19 | base config:module-type;
20 |
21 | // Specifies the prefix for generated java classes.
22 | config:java-name-prefix TutorialNetconfExercise;
23 | }
24 |
25 | // Augments the 'configuration' choice node under modules/module.
26 | augment "/config:modules/config:module/config:configuration" {
27 | case netconf-exercise-impl {
28 | when "/config:modules/config:module/config:type = 'netconf-exercise-impl'";
29 |
30 | //wires in the data-broker service
31 | container binding-aware-broker {
32 | uses config:service-ref {
33 | refine type {
34 | mandatory true;
35 | config:required-identity mdsal:binding-broker-osgi-registry;
36 | }
37 | }
38 | }
39 | container data-broker {
40 | uses config:service-ref {
41 | refine type {
42 | mandatory true;
43 | config:required-identity mdsal:binding-async-data-broker;
44 | }
45 | }
46 | }
47 | container notification-service {
48 | uses config:service-ref {
49 | refine type {
50 | mandatory false;
51 | config:required-identity mdsal:binding-notification-service;
52 | }
53 | }
54 | }
55 | container rpc-registry {
56 | uses config:service-ref {
57 | refine type {
58 | mandatory true;
59 | config:required-identity mdsal:binding-rpc-registry;
60 | }
61 | }
62 | }
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/netconf-exercise/model/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.sdnhub.odl.tutorial
6 | commons
7 | 1.2.0-SNAPSHOT
8 | ../../commons/parent/
9 |
10 |
11 | org.sdnhub.odl.tutorial.netconf-exercise
12 | netconf-exercise-model
13 | 1.0.0-SNAPSHOT
14 | bundle
15 | SDN Hub tutorial project Netconf exercise Model
16 |
17 |
18 |
19 | org.opendaylight.controller.model
20 | model-inventory
21 | ${controller-model.version}
22 |
23 |
24 |
25 |
26 |
27 |
28 | org.apache.felix
29 | maven-bundle-plugin
30 | true
31 |
32 |
33 | ${project.groupId}.${project.artifactId}
34 | org.opendaylight.yangtools.yang.binding.annotations, *
35 | ${project.basedir}/META-INF
36 |
37 |
38 |
39 |
40 | org.opendaylight.yangtools
41 | yang-maven-plugin
42 | ${yangtools.version}
43 |
44 |
45 | org.opendaylight.mdsal
46 | maven-sal-api-gen-plugin
47 | ${maven-sal-api-gen-plugin.version}
48 | jar
49 |
50 |
51 | org.opendaylight.mdsal
52 | yang-binding
53 | ${yang-binding.version}
54 | jar
55 |
56 |
57 |
58 |
59 |
60 | generate-sources
61 |
62 |
63 | src/main/yang
64 |
65 |
66 | org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
67 | ${codeGeneratorPath}
68 |
69 |
70 | org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl
71 | target/site/models
72 |
73 |
74 | org.opendaylight.yangtools.yang.wadl.generator.maven.WadlGenerator
75 | target/site/models
76 |
77 |
78 | true
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | maven-clean-plugin
87 |
88 |
89 |
90 | ${codeGeneratorPath}
91 |
92 | **
93 |
94 |
95 |
96 | ${codeGeneratorPath}
97 |
98 | **
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/netconf-exercise/model/src/main/yang/router.yang:
--------------------------------------------------------------------------------
1 | module router {
2 | yang-version 1;
3 | namespace "urn:sdnhub:odl:tutorial:router";
4 | prefix router;
5 |
6 | description "Router configuration";
7 |
8 | revision "2015-07-28" {
9 | description "Initial version.";
10 | }
11 |
12 | list interfaces {
13 | key id;
14 | leaf id {
15 | type string;
16 | }
17 | leaf ip-address {
18 | type string;
19 | }
20 | }
21 |
22 | container router {
23 | list ospf {
24 | key process-id;
25 | leaf process-id {
26 | type uint32;
27 | }
28 | list networks {
29 | key subnet-ip;
30 | leaf subnet-ip {
31 | type string;
32 | }
33 | leaf area-id {
34 | type uint32;
35 | }
36 | }
37 | }
38 |
39 | list bgp {
40 | key as-number;
41 | leaf as-number {
42 | type uint32;
43 | }
44 | leaf router-id {
45 | type string;
46 | }
47 | list neighbors {
48 | key as-number;
49 | leaf as-number {
50 | type uint32;
51 | }
52 | leaf peer-ip {
53 | type string;
54 | }
55 | }
56 | }
57 | }
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/netconf-exercise/netconf-postman.json:
--------------------------------------------------------------------------------
1 | {"id":"efe2e7b1-360c-c0e6-d5b2-b38def604ca5","name":"Tutorial-Netconf","timestamp":1433658588597,"order":["4ec1b204-ab62-a115-242c-bf39ca711729","c74dc865-f03a-4c0d-7dad-6342d4eff400","7becffb0-1fb7-f0fa-f025-90319d1f24fd","917e2fc1-72f5-7069-22be-0091eddda31d","f43b3dfb-870b-19c7-a2a9-21b526863ada","496d5f49-fb91-d884-65ed-d567f84cb35d","f1852aea-aefe-b0f2-6420-f66e12cff2be","7c93f30f-acb7-8380-b084-14e5c8f6a373","f0452bd6-9c0e-ee13-a918-79cf1f7730a5"],"requests":[{"collectionId":"efe2e7b1-360c-c0e6-d5b2-b38def604ca5","id":"496d5f49-fb91-d884-65ed-d567f84cb35d","name":"Configure router2 interface eth0","description":"","url":"http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/router2/yang-ext:mount/router:interfaces/eth0","method":"PUT","headers":"Content-Type: application/xml\n","data":"\neth0\n10.10.1.2/24\n\n","dataMode":"raw","timestamp":0,"responses":[],"version":2},{"collectionId":"efe2e7b1-360c-c0e6-d5b2-b38def604ca5","id":"4ec1b204-ab62-a115-242c-bf39ca711729","name":"Get all discovered netconf devices","description":"","url":"http://localhost:8181/restconf/operational/network-topology:network-topology/topology/topology-netconf/","method":"GET","headers":"Content-Type: application/xml\n","data":"","dataMode":"raw","timestamp":0,"responses":[],"version":2},{"collectionId":"efe2e7b1-360c-c0e6-d5b2-b38def604ca5","id":"7becffb0-1fb7-f0fa-f025-90319d1f24fd","name":"Configure router1 interface eth1","description":"","url":"http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/router1/yang-ext:mount/router:interfaces/eth1","method":"PUT","headers":"Content-Type: application/xml\n","data":"\neth1\n100.100.100.1/24\n\n","dataMode":"raw","timestamp":0,"responses":[],"version":2},{"collectionId":"efe2e7b1-360c-c0e6-d5b2-b38def604ca5","id":"7c93f30f-acb7-8380-b084-14e5c8f6a373","name":"Configure router2 OSPF + BGP","description":"","url":"http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/router2/yang-ext:mount/router:router","method":"PUT","headers":"Content-Type: application/xml\n","data":"\n \n 1\n \n 200.200.200.0/24\n 20\n \n \n \n 2000\n 10.10.1.2\n \n 1000\n 10.10.1.1\n \n \n","dataMode":"raw","timestamp":0,"version":2},{"collectionId":"efe2e7b1-360c-c0e6-d5b2-b38def604ca5","id":"917e2fc1-72f5-7069-22be-0091eddda31d","name":"Configure router1 OSPF + BGP","description":"","url":"http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/router1/yang-ext:mount/router:router","method":"PUT","headers":"Content-Type: application/xml\n","data":"\n \n 1\n \n 100.100.100.0/24\n 10\n \n \n \n 1000\n 10.10.1.1\n \n 2000\n 10.10.1.2\n \n \n","dataMode":"raw","timestamp":0,"version":2},{"collectionId":"efe2e7b1-360c-c0e6-d5b2-b38def604ca5","id":"c74dc865-f03a-4c0d-7dad-6342d4eff400","name":"Configure router1 interface eth0","description":"","url":"http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/router1/yang-ext:mount/router:interfaces/eth0","method":"PUT","headers":"Content-Type: application/xml\n","data":"\neth0\n10.10.1.1/24\n\n","dataMode":"raw","timestamp":0,"responses":[],"version":2},{"collectionId":"efe2e7b1-360c-c0e6-d5b2-b38def604ca5","id":"f0452bd6-9c0e-ee13-a918-79cf1f7730a5","name":"Get configurations of router2","description":"","url":"http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/router2/yang-ext:mount/","method":"GET","headers":"Content-Type: application/xml\n","data":"","dataMode":"raw","timestamp":0,"responses":[],"version":2},{"collectionId":"efe2e7b1-360c-c0e6-d5b2-b38def604ca5","id":"f1852aea-aefe-b0f2-6420-f66e12cff2be","name":"Configure router2 interface eth1","description":"","url":"http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/router2/yang-ext:mount/router:interfaces/eth1","method":"PUT","headers":"Content-Type: application/xml\n","data":"\neth1\n200.200.200.1/24\n\n","dataMode":"raw","timestamp":0,"responses":[],"version":2},{"collectionId":"efe2e7b1-360c-c0e6-d5b2-b38def604ca5","id":"f43b3dfb-870b-19c7-a2a9-21b526863ada","name":"Get configurations of router1","description":"","url":"http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/router1/yang-ext:mount/","method":"GET","headers":"Content-Type: application/xml\n","data":"","dataMode":"raw","timestamp":0,"responses":[],"version":2}]}
2 |
--------------------------------------------------------------------------------
/netconf-exercise/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | org.sdnhub.odl.tutorial
9 | commons
10 | 1.2.0-SNAPSHOT
11 | ../commons/parent/
12 |
13 |
14 | org.sdnhub.odl.tutorial.netconf-exercise
15 | netconf-exercise-parent
16 | 0.1.0-SNAPSHOT
17 | pom
18 |
19 |
20 | model
21 | implementation
22 | config
23 |
24 |
25 |
--------------------------------------------------------------------------------
/netconf-exercise/register_netconf_device.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if [ $# -ne 2 ]
3 | then
4 | echo "Usage: register_netconf_device "
5 | exit 0
6 | fi
7 |
8 | DEVICE_NAME=$1
9 | IP_ADDRESS=$2
10 | USERNAME=root
11 | PASSWORD=root
12 | PORT=830
13 | CONTROLLER_IP=localhost
14 |
15 | ######## Perform CURL call to push new device to the ODL netconf connector
16 |
17 | curl -H "Content-Type: application/xml" -u admin:admin -X PUT -d "
18 |
19 | prefix:sal-netconf-connector
20 | $DEVICE_NAME
21 | $IP_ADDRESS
22 | $PORT
23 | $USERNAME
24 | $PASSWORD
25 | false
26 |
27 | prefix:netty-event-executor
28 | global-event-executor
29 |
30 |
31 | prefix:binding-broker-osgi-registry
32 | binding-osgi-broker
33 |
34 |
35 | prefix:dom-broker-osgi-registry
36 | dom-broker
37 |
38 |
39 | prefix:netconf-client-dispatcher
40 | global-netconf-dispatcher
41 |
42 |
43 | prefix:threadpool
44 | global-netconf-processing-executor
45 |
46 | " http://${CONTROLLER_IP}:8181/restconf/config/opendaylight-inventory:nodes/node/controller-config/yang-ext:mount/config:modules/module/odl-sal-netconf-connector-cfg:sal-netconf-connector/$DEVICE_NAME
47 |
--------------------------------------------------------------------------------
/netconf-exercise/router.yang:
--------------------------------------------------------------------------------
1 | module router {
2 | yang-version 1;
3 | namespace "urn:sdnhub:odl:tutorial:router";
4 | prefix router;
5 |
6 | description "Router configuration";
7 |
8 | revision "2015-07-28" {
9 | description "Initial version.";
10 | }
11 |
12 | list interfaces {
13 | key id;
14 | leaf id {
15 | type string;
16 | }
17 | leaf ip-address {
18 | type string;
19 | }
20 | }
21 |
22 | container router {
23 | list ospf {
24 | key process-id;
25 | leaf process-id {
26 | type uint32;
27 | }
28 | list networks {
29 | key subnet-ip;
30 | leaf subnet-ip {
31 | type string;
32 | }
33 | leaf area-id {
34 | type uint32;
35 | }
36 | }
37 | }
38 |
39 | list bgp {
40 | key as-number;
41 | leaf as-number {
42 | type uint32;
43 | }
44 | leaf router-id {
45 | type string;
46 | }
47 | list neighbors {
48 | key as-number;
49 | leaf as-number {
50 | type uint32;
51 | }
52 | leaf peer-ip {
53 | type string;
54 | }
55 | }
56 | }
57 | }
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/netconf-exercise/spawn_router.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if [ $# -ne 1 ]
3 | then
4 | echo "Usage: spawn_router "
5 | exit 0
6 | fi
7 |
8 | ######## Spin up containers
9 | DEVICE_NAME=$1
10 | sudo docker rm -f $DEVICE_NAME
11 | DOCKER_ID=`sudo docker run --name $DEVICE_NAME -dit sdnhub/netopeer /bin/bash`
12 | echo $DOCKER_ID
13 | echo "Spawned container with IP `sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' $DEVICE_NAME`"
14 |
15 | ######## Start netconf server with custom YANG model
16 | sudo cp base_datastore.xml /var/lib/docker/aufs/mnt/${DOCKER_ID}/usr/local/etc/netopeer/cfgnetopeer/datastore.xml
17 | sudo cp router.yang /var/lib/docker/aufs/mnt/${DOCKER_ID}/root/router.yang
18 | sudo docker exec $DEVICE_NAME pyang -f yin /root/router.yang -o /root/router.yin
19 | sudo docker exec $DEVICE_NAME netopeer-manager add --name router --model router.yin --datastore /usr/local/etc/netopeer/cfgnetopeer/router.xml
20 | sudo docker exec $DEVICE_NAME netopeer-server -d
21 |
--------------------------------------------------------------------------------
/netconf-exercise/unregister_netconf_device.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if [ $# -ne 1 ]
3 | then
4 | echo "Usage: unregister_netconf_device "
5 | exit 0
6 | fi
7 |
8 | DEVICE_NAME=$1
9 | CONTROLLER_IP=localhost
10 |
11 | curl -u admin:admin -X DELETE http://${CONTROLLER_IP}:8181/restconf/config/opendaylight-inventory:nodes/node/controller-config/yang-ext:mount/config:modules/module/odl-sal-netconf-connector-cfg:sal-netconf-connector/$DEVICE_NAME
12 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | org.sdnhub.odl.tutorial
7 | commons
8 | 1.2.0-SNAPSHOT
9 | commons/parent
10 |
11 |
12 | main
13 | 0.6.0-SNAPSHOT
14 | pom
15 | http://sdnhub.org/tutorials/opendaylight
16 |
17 | commons/parent
18 | commons/utils
19 | learning-switch
20 | tapapp
21 | acl
22 | netconf-exercise
23 | features
24 | distribution
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/tapapp/config/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.sdnhub.odl.tutorial
7 | commons
8 | 1.2.0-SNAPSHOT
9 | ../../commons/parent/pom.xml
10 |
11 |
12 | org.sdnhub.odl.tutorial.tapapp
13 | tapapp-config
14 | 1.0.0-SNAPSHOT
15 | SDN Hub tutorial Project Tap application Config
16 |
17 | jar
18 |
19 |
20 |
21 | org.codehaus.mojo
22 | build-helper-maven-plugin
23 | ${build.plugins.plugin.version}
24 |
25 |
26 | attach-artifacts
27 |
28 | attach-artifact
29 |
30 | package
31 |
32 |
33 |
34 | ${project.build.directory}/classes/initial/${tapapp.configfile}
35 | xml
36 | config
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/tapapp/config/src/main/resources/initial/50-tapapp-config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | prefix:tapapp-impl
9 | tapapp-impl
10 |
11 |
12 | binding:binding-notification-service
13 | binding-notification-broker
14 |
15 |
16 | binding:binding-async-data-broker
17 | binding-data-broker
18 |
19 |
20 | binding:binding-rpc-registry
21 | binding-rpc-broker
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | urn:sdnhub:odl:tutorial:tapapp:tapapp-impl?module=tapapp-impl&revision=2015-06-04
30 | urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl?module=openflow-provider-impl&revision=2014-03-26
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/tapapp/implementation/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.sdnhub.odl.tutorial.tapapp
6 | tapapp-parent
7 | 0.1.0-SNAPSHOT
8 |
9 |
10 | tapapp-impl
11 | SDN Hub tutorial project Tap application Impl
12 | 1.0.0-SNAPSHOT
13 | bundle
14 |
15 |
16 |
17 | org.sdnhub.odl.tutorial
18 | utils
19 | ${utils.version}
20 |
21 |
22 | org.sdnhub.odl.tutorial.tapapp
23 | tapapp-model
24 | ${tapapp.version}
25 |
26 |
27 | org.opendaylight.openflowplugin.model
28 | model-flow-service
29 | ${openflowplugin.version}
30 |
31 |
32 |
33 |
34 |
35 | org.opendaylight.yangtools
36 | yang-maven-plugin
37 | ${yangtools.version}
38 |
39 |
40 |
41 | generate-sources
42 |
43 |
44 | src/main/yang
45 |
46 |
47 | org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
48 | ${codeGeneratorPath}
49 |
50 |
51 | org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
52 | ${configCodeGeneratorPath}
53 |
54 | urn:sdnhub:odl:tutorial:tapapp:tapapp-impl==org.sdnhub.odl.tutorial.tapapp.impl
55 | urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
56 |
57 |
58 |
59 | org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl
60 | ${project.build.directory}/site/models
61 |
62 |
63 | true
64 |
65 |
66 |
67 |
68 |
69 | org.opendaylight.mdsal
70 | maven-sal-api-gen-plugin
71 | ${maven-sal-api-gen-plugin.version}
72 | jar
73 |
74 |
75 | org.opendaylight.controller
76 | yang-jmx-generator-plugin
77 | ${yang.jmx.version}
78 |
79 |
80 |
81 |
82 | org.apache.felix
83 | maven-bundle-plugin
84 | 2.4.0
85 | true
86 |
87 |
88 | *
89 | utils
90 |
91 | ${project.basedir}/META-INF
92 |
93 |
94 |
96 |
97 | org.codehaus.mojo
98 | build-helper-maven-plugin
99 | 1.8
100 |
101 |
102 | add-source
103 |
104 | add-source
105 |
106 | generate-sources
107 |
108 |
109 | src/main/yang
110 | ${codeGeneratorPath}
111 | ${configCodeGeneratorPath}
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | maven-clean-plugin
120 |
121 |
122 |
123 | ${codeGeneratorPath}
124 |
125 | **
126 |
127 |
128 |
129 | ${configCodeGeneratorPath}
130 |
131 | **
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/tapapp/implementation/src/main/java/org/sdnhub/odl/tutorial/tapapp/impl/TutorialTapAppModule.java:
--------------------------------------------------------------------------------
1 | package org.sdnhub.odl.tutorial.tapapp.impl;
2 |
3 | import org.opendaylight.controller.md.sal.binding.api.DataBroker;
4 | import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
5 | import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import com.google.common.base.Preconditions;
10 |
11 | public class TutorialTapAppModule extends AbstractTutorialTapAppModule {
12 | private final Logger LOG = LoggerFactory.getLogger(this.getClass());
13 |
14 | public TutorialTapAppModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
15 | super(identifier, dependencyResolver);
16 | }
17 |
18 | public TutorialTapAppModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, AbstractTutorialTapAppModule oldModule, java.lang.AutoCloseable oldInstance) {
19 | super(identifier, dependencyResolver, oldModule, oldInstance);
20 | }
21 |
22 | @Override
23 | public void customValidation() {
24 | // add custom validation form module attributes here.
25 | }
26 |
27 | @Override
28 | public java.lang.AutoCloseable createInstance() {
29 | DataBroker dataBrokerService = getDataBrokerDependency();
30 | RpcProviderRegistry rpcProviderRegistry = getRpcRegistryDependency();
31 | NotificationProviderService notificationService = getNotificationServiceDependency();
32 |
33 | Preconditions.checkNotNull(dataBrokerService);
34 | Preconditions.checkNotNull(rpcProviderRegistry);
35 | Preconditions.checkNotNull(notificationService);
36 |
37 | TutorialTapProvider tapProvider = new TutorialTapProvider(dataBrokerService, notificationService, rpcProviderRegistry);
38 | LOG.info("Tutorial TapApp (instance {}) initialized.", tapProvider);
39 | return tapProvider;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tapapp/implementation/src/main/java/org/sdnhub/odl/tutorial/tapapp/impl/TutorialTapAppModuleFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Generated file
3 | *
4 | * Generated from: yang module name: tapapp-impl yang module local name: tapapp-impl
5 | * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
6 | * Generated at: Fri Jun 05 14:58:22 PDT 2015
7 | *
8 | * Do not modify this file unless it is present under src/main directory
9 | */
10 | package org.sdnhub.odl.tutorial.tapapp.impl;
11 | public class TutorialTapAppModuleFactory extends AbstractTutorialTapAppModuleFactory {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/tapapp/implementation/src/main/yang/tapapp-impl.yang:
--------------------------------------------------------------------------------
1 | module tapapp-impl {
2 | yang-version 1;
3 | namespace "urn:sdnhub:odl:tutorial:tapapp:tapapp-impl";
4 | prefix "tapapp-impl";
5 |
6 | import config { prefix config; revision-date 2013-04-05; }
7 | import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
8 |
9 | description
10 | "This module contains the base YANG definitions for tapapp-impl.";
11 |
12 | revision "2015-06-04" {
13 | description
14 | "Initial revision.";
15 | }
16 |
17 | // This is the definition of the service implementation as a module identity
18 | identity tapapp-impl {
19 | base config:module-type;
20 |
21 | // Specifies the prefix for generated java classes.
22 | config:java-name-prefix TutorialTapApp;
23 | }
24 |
25 | // Augments the 'configuration' choice node under modules/module.
26 | augment "/config:modules/config:module/config:configuration" {
27 | case tapapp-impl {
28 | when "/config:modules/config:module/config:type = 'tapapp-impl'";
29 |
30 | //wires in the data-broker service
31 | container data-broker {
32 | uses config:service-ref {
33 | refine type {
34 | mandatory true;
35 | config:required-identity mdsal:binding-async-data-broker;
36 | }
37 | }
38 | }
39 | container notification-service {
40 | uses config:service-ref {
41 | refine type {
42 | mandatory false;
43 | config:required-identity mdsal:binding-notification-service;
44 | }
45 | }
46 | }
47 | container rpc-registry {
48 | uses config:service-ref {
49 | refine type {
50 | mandatory true;
51 | config:required-identity mdsal:binding-rpc-registry;
52 | }
53 | }
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/tapapp/model/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.sdnhub.odl.tutorial
6 | commons
7 | 1.2.0-SNAPSHOT
8 | ../../commons/parent/
9 |
10 |
11 | org.sdnhub.odl.tutorial.tapapp
12 | tapapp-model
13 | 1.0.0-SNAPSHOT
14 | bundle
15 | SDN Hub tutorial project Tap application Model
16 |
17 |
18 |
19 | org.opendaylight.controller.model
20 | model-inventory
21 | ${controller-model.version}
22 |
23 |
24 |
25 |
26 |
27 |
28 | org.apache.felix
29 | maven-bundle-plugin
30 | true
31 |
32 |
33 | ${project.groupId}.${project.artifactId}
34 | org.opendaylight.yangtools.yang.binding.annotations, *
35 | ${project.basedir}/META-INF
36 |
37 |
38 |
39 |
40 | org.opendaylight.yangtools
41 | yang-maven-plugin
42 | ${yangtools.version}
43 |
44 |
45 | org.opendaylight.mdsal
46 | maven-sal-api-gen-plugin
47 | ${maven-sal-api-gen-plugin.version}
48 | jar
49 |
50 |
51 | org.opendaylight.mdsal
52 | yang-binding
53 | ${yang-binding.version}
54 | jar
55 |
56 |
57 |
58 |
59 |
60 | generate-sources
61 |
62 |
63 | src/main/yang
64 |
65 |
66 | org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
67 | ${codeGeneratorPath}
68 |
69 |
70 | org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl
71 | target/site/models
72 |
73 |
74 | org.opendaylight.yangtools.yang.wadl.generator.maven.WadlGenerator
75 | target/site/models
76 |
77 |
78 | true
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | maven-clean-plugin
87 |
88 |
89 |
90 | ${codeGeneratorPath}
91 |
92 | **
93 |
94 |
95 |
96 | ${codeGeneratorPath}
97 |
98 | **
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/tapapp/model/src/main/yang/tap.yang:
--------------------------------------------------------------------------------
1 | module tap {
2 | yang-version 1;
3 | namespace "urn:sdnhub:tutorial:odl:tap";
4 | prefix tap;
5 |
6 | import opendaylight-inventory {prefix inv; revision-date 2013-08-19;}
7 | import yang-ext {prefix ext; revision-date "2013-07-09";}
8 | import ietf-yang-types { prefix yang; revision-date 2010-09-24; }
9 | import ietf-inet-types { prefix inet; }
10 | description "Tap configuration";
11 |
12 | revision "2015-06-01" {
13 | description "Initial version.";
14 | }
15 |
16 | typedef port-number {
17 | type uint32;
18 | }
19 |
20 |
21 | typedef field-type {
22 | type enumeration {
23 | enum source;
24 | enum destination;
25 | enum both;
26 | }
27 | }
28 |
29 | typedef traffic-type {
30 | type enumeration {
31 | enum ARP;
32 | enum DNS;
33 | enum HTTP;
34 | enum HTTPS;
35 | enum TCP;
36 | enum UDP;
37 | enum DHCP;
38 | enum ICMP;
39 | }
40 | }
41 |
42 | grouping tap-grouping {
43 | leaf node {
44 | mandatory true;
45 | type leafref {
46 | path "/inv:nodes/inv:node/inv:id";
47 | }
48 | }
49 | leaf-list src-node-connector {
50 | min-elements 1;
51 | type leafref {
52 | path "/inv:nodes/inv:node/inv:node-connector/inv:id";
53 | }
54 | }
55 | leaf-list sink-node-connector {
56 | min-elements 1;
57 | type leafref {
58 | path "/inv:nodes/inv:node/inv:node-connector/inv:id";
59 | }
60 | }
61 | container mac-address-match {
62 | leaf type {
63 | type field-type;
64 | }
65 | leaf value {
66 | type yang:mac-address;
67 | }
68 | }
69 | container ip-address-match {
70 | leaf type {
71 | type field-type;
72 | }
73 | leaf value {
74 | type inet:ipv4-prefix;
75 | }
76 | }
77 | leaf traffic-match {
78 | type traffic-type;
79 | }
80 | }
81 |
82 | container tap-spec {
83 | list tap {
84 | key "id";
85 | leaf id {
86 | type string;
87 | }
88 | uses tap-grouping;
89 | }
90 | }
91 |
92 | augment /tap-spec/tap {
93 | ext:augment-identifier "ProtocolInfo";
94 | leaf dl-type {
95 | type uint16;
96 | }
97 | leaf nw-proto {
98 | type uint8;
99 | }
100 | leaf tp-src {
101 | type uint16;
102 | }
103 | leaf tp-dst {
104 | type uint16;
105 | }
106 | }
107 | }
108 |
109 |
--------------------------------------------------------------------------------
/tapapp/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | org.sdnhub.odl.tutorial
9 | commons
10 | 1.2.0-SNAPSHOT
11 | ../commons/parent/
12 |
13 |
14 | org.sdnhub.odl.tutorial.tapapp
15 | tapapp-parent
16 | 0.1.0-SNAPSHOT
17 | pom
18 |
19 |
20 | model
21 | implementation
22 | config
23 |
24 |
25 |
--------------------------------------------------------------------------------
/tapapp/postman-resources/tapapp-postman.json:
--------------------------------------------------------------------------------
1 | {"id":"86c494e7-4a55-577d-da29-0baf1b37bed9","name":"Tutorial-TapApp","timestamp":1433658588597,"requests":[{"collectionId":"86c494e7-4a55-577d-da29-0baf1b37bed9","id":"1af34405-9f90-0296-4c5a-6b62051d3e01","name":"Tap 1 deletion","description":"","url":"http://localhost:8181/restconf/config/tap:tap-spec/tap/1","method":"DELETE","headers":"Content-Type: application/xml\n","data":"\n 1\n","dataMode":"raw","timestamp":0,"responses":[],"version":2},{"collectionId":"86c494e7-4a55-577d-da29-0baf1b37bed9","id":"5ebac46d-4ee5-ba70-d1d4-546247d6792b","name":"Tap 2 addition","description":"","url":"http://localhost:8181/restconf/config/tap:tap-spec/tap/2","method":"PUT","headers":"Content-Type: application/xml\n","data":"\n 2\n openflow:1\n \n openflow:1:2\n \n \n openflow:1:1\n \n DNS\n","dataMode":"raw","timestamp":0,"version":2},{"collectionId":"86c494e7-4a55-577d-da29-0baf1b37bed9","id":"6fc7a059-5afe-b941-78f6-70ab4cc1dfed","name":"Tap 1 addition","description":"","url":"http://localhost:8181/restconf/config/tap:tap-spec","method":"PUT","headers":"Content-Type: application/xml\n","data":"\n \n 1\n openflow:1\n \n openflow:1:1\n \n \n openflow:1:2\n \n HTTP\n \n","dataMode":"raw","timestamp":0,"version":2},{"collectionId":"86c494e7-4a55-577d-da29-0baf1b37bed9","id":"9c108ce8-269f-3916-9614-044cc9f2f32a","name":"Get all configured Taps","description":"","url":"http://localhost:8181/restconf/config/tap:tap-spec","method":"GET","headers":"Content-Type: application/xml\n","data":"","dataMode":"raw","timestamp":0,"version":2,"time":1438192927149},{"collectionId":"86c494e7-4a55-577d-da29-0baf1b37bed9","id":"e63dbd8b-b311-cb73-0ead-d44fd7fbaa42","name":"Tap 2 deletion","description":"","url":"http://localhost:8181/restconf/config/tap:tap-spec/tap/2","method":"DELETE","headers":"Content-Type: application/xml\n","data":"\n 2\n","dataMode":"raw","timestamp":0,"version":2}],"order":["9c108ce8-269f-3916-9614-044cc9f2f32a","6fc7a059-5afe-b941-78f6-70ab4cc1dfed","1af34405-9f90-0296-4c5a-6b62051d3e01","5ebac46d-4ee5-ba70-d1d4-546247d6792b","e63dbd8b-b311-cb73-0ead-d44fd7fbaa42"]}
2 |
--------------------------------------------------------------------------------