IETF 102 Hackathon
Alternative southbound interface to flow enabled network bridges
This is a new project originally defined in the following post on hackathon@ietf.org https://mailarchive.ietf.org/arch/msg/hackathon/vb27RmJivbwy8UURV_KXh2IzZd0
The project consists of 3 tasks:
- Design and publish draft with YANG model of a flow enabled network bridge.
- Device (server) side model implementation - loadable module for some of the available opensource NETCONF servers implementing the model for a OpenFlow device as a proxy controller with a single node.
- Controller (client) side plug-in implementation - ncflowplugin for ODL interacting with NETCONF mounted nodes implementing the YANG model
that ideally can coexist with openflowplugin.
Progress:
Design and publish draft with YANG model of a flow enabled network bridge.
Done. https://datatracker.ietf.org/doc/draft-vassilev-netmod-network-bridge/
Device (server) side model implementation
Partial. Can be mounted from ODL but the OpenFlow part is not ready. - https://github.com/vlvassilev/yuma123/tree/master/example-modules/ietf-network-bridge
Controller (client) side plug-in implementation - ncflowplugin for ODL
Incomplete.
Walkthrough (tested on Debian)
Build and start netconfd server instance with the ietf-network-bridge* modules loaded listening on port 830:
cd
sudo apt-get install git autoconf gcc libtool libxml2-dev libssh2-1-dev make libncurses5-dev zlib1g-dev libreadline-dev
git clone git://git.code.sf.net/p/yuma123/git yuma123-git
cd yuma123-git
git checkout 328a64829243684da65891851bf22acb88ca16a5
autoreconf -i -f
./configure CFLAGS='-g -O0' CXXFLAGS='-g -O0' --prefix=/usr
make
sudo make install
#Enable the netconf subsystem and restart sshd
echo "Port 830" | sudo tee -a /etc/ssh/sshd_config
echo "Subsystem netconf "/usr/sbin/netconf-subsystem" | sudo tee -a /etc/ssh/sshd_config
sudo /etc/init.d/ssh restart
/usr/sbin/netconfd --module=/usr/share/yuma/modules/ietf/ietf-interfaces@2014-05-08.yang \
--module=/usr/share/yuma/modules/ietf/iana-if-type@2014-05-08.yang \
--module=/usr/share/yuma/modules/ietf-draft/ietf-network-bridge.yang \
--module=/usr/share/yuma/modules/ietf-draft/ietf-network-bridge-flows.yang \
--module=/usr/share/yuma/modules/ietf-draft/ietf-network-bridge-scheduler.yang \
--module=/usr/share/yuma/modules/examples/example-bridge.yang \
--startup=example-modules/ietf-network-bridge/example-bridge-cfg.xml --log-level=debug4 --superuser=${USER}
Validate everything is OK with NETCONF client:
vladimir@lmf:~$ yangcli --server=localhost --ncport=830 --user=${USER}
Warning: line is 82 chars, limit is 72 chars
yangcli-ex.yang:69.1: warning(438): display line length exceeded
yangcli version 2.11-0
libssh2 version 1.7.0
Copyright (c) 2008-2012, Andy Bierman, All Rights Reserved.
Copyright (c) 2013-2017, Vladimir Vassilev, All Rights Reserved.
Type 'help' or 'help <command-name>' to get started
Use the <tab> key for command and value completion
Use the <enter> key to accept the default value in brackets
These escape sequences are available when filling parameter values:
? help
?? full help
?s skip current parameter
?c cancel current command
These assignment statements are available when entering commands:
$<varname> = <expr> Local user variable assignment
$$<varname> = <expr> Global user variable assignment
@<filespec> = <expr> File assignment
Enter string value for leaf <password>
yangcli:connect>
val->res is NO_ERR.
yangcli: Starting NETCONF session for vladimir on localhost
NETCONF session established for vladimir on localhost
Client Session Id: 1
Server Session Id: 3
Server Protocol Capabilities
base:1.0
candidate:1.0
confirmed-commit:1.0
rollback-on-error:1.0
validate:1.0
url:1.0
xpath:1.0
notification:1.0
interleave:1.0
partial-lock:1.0
with-defaults:1.0
base:1.1
validate:1.1
confirmed-commit:1.1
yang-library:1.0
Server Module Capabilities
example-bridge@2018-07-15
iana-crypt-hash@2014-08-06
Features:
crypt-hash-md5
crypt-hash-sha-256
crypt-hash-sha-512
iana-if-type@2014-05-08
ietf-datastores@2018-01-11
ietf-inet-types@2013-07-15
ietf-interfaces@2014-05-08
Features:
arbitrary-names
pre-provisioning
if-mib
ietf-netconf-acm@2012-02-22
ietf-netconf-datastores@2017-08-24
Features:
origin
ietf-netconf-monitoring@2010-10-04
ietf-netconf-notifications@2012-02-06
ietf-netconf-partial-lock@2009-10-19
ietf-netconf-with-defaults@2011-06-01
ietf-network-bridge@2018-07-15
ietf-network-bridge-flows@2018-07-15
ietf-network-bridge-scheduler@2018-07-15
ietf-origin@2018-01-11
ietf-system@2014-08-06
Features:
radius
authentication
local-users
radius-authentication
ntp
ntp-udp-port
timezone-name
dns-udp-tcp-port
ietf-yang-library@2016-06-21
ietf-yang-metadata@2016-08-05
ietf-yang-types@2013-07-15
nc-notifications@2008-07-14
notifications@2008-07-14
yuma-app-common@2012-08-16
yuma-mysession@2010-05-10
yuma-ncx@2012-01-13
yuma-proc@2012-10-10
yuma-time-filter@2012-11-15
yuma-types@2012-06-01
yuma123-netconf-types@2017-06-23
yuma123-system@2017-03-26
Server Enterprise Capabilities
None
Protocol version set to: RFC 6241 (base:1.1)
Default target set to: <candidate>
Save operation mapped to: commit
Default with-defaults behavior: explicit
Additional with-defaults behavior: trim,report-all,report-all-tagged
Getting yang-library module set ...
Current module-set-id: 475799d7bd3d7f8a8c72fc5fcd9ca5a8b2cb7674.
Checking Server Modules...
yangcli vladimir@localhost> xget-config source=running /
RPC Data Reply 2 for session 3:
rpc-reply {
data {
bridge {
ports {
port p0 {
name p0
index 0
class example:default-port
class-instance-index 0
}
port p1 {
name p1
index 1
class example:default-port
class-instance-index 1
}
port p2 {
name p2
index 2
class example:default-port
class-instance-index 2
}
}
default-traffic-class example:best-effort
default-port-class example:best-effort
traffic-classes {
traffic-class example:best-effort
traffic-class example:signaling
traffic-class example:video0
traffic-class example:video1
}
port-classes {
port-class example:default-port
}
scheduler-classes {
scheduler-class example:default-port {
egress-port-class example:default-port
inputs {
input example:best-effort example:default-port {
traffic-class example:best-effort
ingress-port-class example:default-port
gate-controller p
input-class example:pri2
base-index 0
}
input example:signaling example:default-port {
traffic-class example:signaling
ingress-port-class example:default-port
gate-controller r1
input-class example:in
base-index 0
}
input example:video0 example:default-port {
traffic-class example:video0
ingress-port-class example:default-port
gate-controller t
input-class example:timeslot0
base-index 0
}
input example:video1 example:default-port {
traffic-class example:video1
ingress-port-class example:default-port
gate-controller t
input-class example:timeslot1
base-index 0
}
}
gate-controllers {
gate-controller a {
id a
type example:strict-priority-aggregator
inputs {
input example:pri0 {
class example:pri0
instance-count 3
queue-len 2048
}
}
output {
gate-controller r2
input-class example:in
index 0
}
}
gate-controller p {
id p
type example:strict-priority-aggregator
inputs {
input example:pri0 {
class example:pri0
instance-count 1
queue-len 2048
}
input example:pri1 {
class example:pri1
instance-count 1
queue-len 32768
}
input example:pri2 {
class example:pri2
instance-count 3
queue-len 1048576
}
}
}
gate-controller r1 {
id r1
type example:rate-limiter
inputs {
input example:in {
class example:in
instance-count 3
}
}
output {
gate-controller a
input-class example:pri0
index 0
}
interval 10000000
limit 12500
}
gate-controller r2 {
id r2
type example:rate-limiter
inputs {
input example:in {
class example:in
instance-count 1
}
}
output {
gate-controller p
input-class example:pri0
index 0
}
interval 10000000
limit 125000
}
gate-controller t {
id t
type example:cyclic-timeslot-schedule-aggregator
inputs {
input example:timeslot0 {
class example:timeslot0
instance-count 3
queue-len 1048576
}
input example:timeslot1 {
class example:timeslot1
instance-count 3
queue-len 1048576
}
}
output {
gate-controller p
input-class example:pri0
index 2
}
period 10000000
time-slot0-interval 5000000
time-slot1-interval 5000000
}
}
}
}
}
flows {
flow best-effort-to-host0 {
id best-effort-to-host0
match {
ethernet-match {
ethernet-destination {
address 00:01:02:03:00:00
}
}
}
actions {
action 0 {
order 0
output-action {
out-port p0
}
}
}
traffic-class example:best-effort
}
flow best-effort-to-host1 {
id best-effort-to-host1
match {
ethernet-match {
ethernet-destination {
address 00:01:02:03:00:01
}
}
}
actions {
action 0 {
order 0
output-action {
out-port p1
}
}
}
traffic-class example:best-effort
}
flow best-effort-to-host2 {
id best-effort-to-host2
match {
ethernet-match {
ethernet-destination {
address 00:01:02:03:00:02
}
}
}
actions {
action 0 {
order 0
output-action {
out-port p2
}
}
}
traffic-class example:best-effort
}
flow ptp-to-host0 {
id ptp-to-host0
match {
ethernet-match {
ethernet-destination {
address 00:01:02:03:00:00
}
}
}
actions {
action 0 {
order 0
output-action {
out-port p0
}
}
}
traffic-class example:signaling
}
flow ptp-to-host1 {
id ptp-to-host1
match {
ethernet-match {
ethernet-destination {
address 00:01:02:03:00:01
}
}
}
actions {
action 0 {
order 0
output-action {
out-port p1
}
}
}
traffic-class example:signaling
}
flow ptp-to-host2 {
id ptp-to-host2
match {
ethernet-match {
ethernet-destination {
address 00:01:02:03:00:02
}
}
}
actions {
action 0 {
order 0
output-action {
out-port p2
}
}
}
traffic-class example:signaling
}
flow video0 {
id video0
match {
vlan-match {
vlan-id {
vlan-id 10
}
}
}
actions {
action 0 {
order 0
output-action {
out-port p2
}
}
}
traffic-class example:video0
}
flow video1 {
id video1
match {
vlan-match {
vlan-id {
vlan-id 11
}
}
}
actions {
action 0 {
order 0
output-action {
out-port p2
}
}
}
traffic-class example:video1
}
}
interfaces {
interface if0 {
name if0
type ianaift:ethernetCsmacd
port-name p0
}
interface if1 {
name if1
type ianaift:ethernetCsmacd
port-name p1
}
interface if2 {
name if2
type ianaift:ethernetCsmacd
port-name p2
}
}
nacm {
}
}
}
yangcli vladimir@localhost> quit
Build and start ODL mounting the network bridge over NETCONF (change user:tester/pass:tester with the user that started netconfd and pass):
cd
sudo apt-get install -y openjdk-8-jdk
sudo apt-get install -y maven
mkdir ~/.m2
wget -q -O - https://raw.githubusercontent.com/opendaylight/odlparent/master/settings.xml > ~/.m2/settings.xml
export MAVEN_OPTS='-Xmx1048m -XX:MaxPermSize=512m'
#from https://wiki.opendaylight.org/view/GettingStarted:Pulling,_Hacking,_and_Pushing_All_the_Code_from_the_CLI
sudo apt-get install corkscrew
mkdir opendaylight
cd opendaylight
for PROJECT in aaa aalldp alto armoury atrium bgpcep bier capwap cardinal centinel coe controller daexim didm discovery \
dlux dluxapps docs eman faas federation fpc genius groupbasedpolicy honeycomb/vbd integration/distribution \
integration/packaging integration/packaging/ansible-opendaylight integration/packaging/puppet-opendaylight integration/test \
iotdm jsonrpc kafkaproducer l2switch lacp lispflowmapping mdsal messaging4transport natapp nemo netconf netide netvirt \
neutron next nic ocpplugin odlparent of-config ofextensions/circuitsw ofextensions/epc openflowjava openflowplugin opflex \
ovsdb packetcable persistence plugin2oc releng releng/autorelease releng/builder reservation sdninterfaceapp sfc snbi snmp \
snmp4sdn sxp systemmetrics tcpmd5 topoprocessing transportpce tsdr ttp unimgr usc usecplugin vpnservice vtn yang-push \
yangide yangtools; \
do git clone https://git.opendaylight.org/gerrit/${PROJECT}.git ${PROJECT}; \
done
git clone https://git.opendaylight.org/gerrit/p/integration/distribution.git distribution
cd distribution
git checkout tags/release/beryllium-sr4
mvn clean install -Pq
cd distribution-karaf/target/assembly
./bin/start
sleep 30
./bin/client -u karaf 'feature:list --installed'
#install NETCONF support
./bin/client -u karaf 'feature:install odl-netconf-all odl-netconf-ssh odl-netconf-connector-all'
#install GUI support
./bin/client -u karaf 'feature:install odl-dlux-all'
#install topology configuration support
./bin/client -u karaf 'feature:install odl-restconf-all'
./bin/client -u karaf 'feature:install odl-netconf-topology'
#odl-netconf-clustered-topology
./bin/client -u karaf feature:list
cat > myscript.txt << EOF
merge /modules/module[name='ncflow-1'][type='sal-netconf-connector'] -- address=localhost sal-netconf:port=830 tcp-only=false username=tester password=tester sal-netconf:event-executor/type=netty-event-executor sal-netconf:event-executor/name=global-event-executor sal-netconf:binding-registry/type=binding-broker-osgi-registry sal-netconf:binding-registry/name=binding-osgi-broker sal-netconf:dom-registry/type=dom-broker-osgi-registry sal-netconf:dom-registry/name=dom-broker sal-netconf:client-dispatcher/type=netconf-client-dispatcher sal-netconf:client-dispatcher/name=global-netconf-dispatcher sal-netconf:processing-executor/type=threadpool sal-netconf:processing-executor/name=global-netconf-processing-executor sal-netconf:keepalive-executor/type=scheduled-threadpool sal-netconf:keepalive-executor/name=global-netconf-ssh-scheduled-executor
commit
EOF
# If commit is not done in the same session as the merge the changes to candidate are discarded autmatically .. thus the --run-script instead 2 sequential --run-command calls for merge and commit.
yangcli --server=localhost --ncport=1830 --user=admin --password=admin --dump-session=/tmp/yangcli- --keep-session-model-copies-after-compilation=true --batch-mode --run-script=myscript.txt --log-level=debug4
#enable northbound MD-SAL interface - opens port 2830
./bin/client -u karaf 'feature:install odl-netconf-mdsal'
sleep 60
./bin/client -u karaf 'feature:install odl-mdsal-apidocs'
./bin/client -u karaf 'feature:install odl-openflowplugin-flow-services-rest'
./bin/client -u karaf 'feature:install odl-openflowplugin-flow-services-ui'
sleep 30
cat > myscript.txt << EOF
merge /nodes/node[id='ncflow-1']/table[id='0']/flow[id='1'] -- match/in-port=ncflow-1:1 match/ethernet-match/ethernet-type=35063 instructions/instruction[order='0']/apply-actions/action[order='0']/output-action/output-node-connector=2 out_port=2 flow-name=my-ptp-flow
commit
EOF
yangcli --server=localhost --ncport=2830 --user=admin --password=admin --dump-session=/tmp/yangcli- --keep-session-model-copies-after-compilation=true --batch-mode --run-script=myscript.txt --log-level=debug4
Start conventional openflow nodes to join the ncflow node:
mn --topo linear,3 --mac --controller=remote,ip=127.0.0.1,port=6633 --switch ovs,protocols=OpenFlow10
... work remaining to get ncflow appearing as the rest of flow enabled bridges running OpenFlow.