Hi,

We have implemented your comments on the code and I have attached the
updated L2QoS module as a patch.Please have a look at this and revert back
if you need any clarifications.

Also I have attached the sample testplan document as a text file which would
fit under doc directory.

We request you to merge this module with the existing framework.

Thanks & regards,

B.SUJAI
Veryx Technologies Pvt Limited,
Chennai - INDIA 

-------- Original Message --------
Subject:        Re: [Ryu-devel] Addition of layer 2 QoS Module - RYU controller
Date:   Wed, 28 Aug 2013 22:21:15 +0900 (JST)
From:   FUJITA Tomonori <[email protected]>
To:     [email protected]
CC:     [email protected], [email protected]



Thanks for sending the code!

First, please send the code as a patch:

https://github.com/osrg/ryu/blob/master/SubmittingPatches.rst

Second, we don't put word doc into the code. So please convert the
word doc into a format that fit under doc directory.

Lastly there are some comments on the code.

On Wed, 28 Aug 2013 12:00:06 +0530
Sujai Buvaneswaran <[email protected]> wrote:

> # Copyright (C) 2013 Veryx Technologies Pvt Limited.
> #
> # Licensed under the Apache License, Version 2.0 (the "License");
> # you may not use this file except in compliance with the License.
> # You may obtain a copy of the License at
> #
> #    http://www.apache.org/licenses/LICENSE-2.0
> #
> # Unless required by applicable law or agreed to in writing, software
> # distributed under the License is distributed on an "AS IS" BASIS,
> # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> # implied.
> # See the License for the specific language governing permissions and
> # limitations under the License.
>
>     """
>     This module performs L2 learning for an incoming flow, assigns it
>     to a specific egress port queue based on the flow's VLAN Pbit value and
>     adds the flow entry in the switch flow table. The queue assignment will be
>     based on default Pbit-Queue mapping defined by default in the module or
>     overwritten using user defined value Pbit-Queue mapping value. Any flows
>     received without VLAN tag will be assigned to Queue 1.
>       
>     The default Pbit-Queue mapping is {0:8, 1:7, 2:6, 3:5, 4:4, 5:3, 6:2, 
> 7:1} where
>     0 denotes VLAN Pbit and 8 denotes Queue ID.
>     """
>
> import logging
> import struct
> import ast
>
> from oslo.config import cfg
> from ryu.base import app_manager
> from ryu.controller import mac_to_port
> from ryu.controller import ofp_event
> from ryu.controller.handler import MAIN_DISPATCHER
> from ryu.controller.handler import set_ev_cls
> from ryu.ofproto import ofproto_v1_0
> from ryu.lib.mac import haddr_to_str
>
> # User-defined input
> # Below code re-assigns the Pbit-Queue mapping for Queue ID 4 and 5 with Pbit 
> 5 and 6
> CONF = cfg.CONF
> CONF.register_cli_opts([
>     cfg.StrOpt('pcp-queue', default={5:4,6:5},
>                 help='pcp to queue map')
> ])

The above works?

>
> class L2QoS(app_manager.RyuApp):
>     OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION]
>
>     def __init__(self, *args, **kwargs):
>         super(L2QoS, self).__init__(CONF.pcp_queue,*args, **kwargs)
>         self.mac_to_port = {}   # MAC Address table initialization
>         self.pcp_queue = CONF.pcp_queue
>         self.port = self.pcp_queue.keys()
>
>     """
>     This function installs the flow in the OpenFlow switch Flow Table
>     """
>     def add_flow(self, datapath, in_port, dst, vlan_pcp, _eth_type,nw_src, 
> actions):
>         ofproto = datapath.ofproto
>         wildcards = ofproto_v1_0.OFPFW_ALL
>         wildcards &= ~ofproto_v1_0.OFPFW_IN_PORT
>         wildcards &= ~ofproto_v1_0.OFPFW_DL_DST
>         if _eth_type == 33024 :

Please use ofproto/ether.py for ether types.

>            wildcards &= ~ofproto_v1_0.OFPFW_DL_VLAN_PCP
>            wildcards &= ~ofproto_v1_0.OFPFW_NW_SRC_MASK
>            match = datapath.ofproto_parser.OFPMatch(
>             wildcards, in_port, 0, dst,
>             0, vlan_pcp, 0, 0, 0, nw_src, 0, 0, 0)
>         elif _eth_type == 2048 :
>            wildcards &= ~ofproto_v1_0.OFPFW_DL_TYPE
>            wildcards &= ~ofproto_v1_0.OFPFW_NW_SRC_MASK
>            match = datapath.ofproto_parser.OFPMatch(
>             wildcards, in_port, 0, dst,
>             0, 0, _eth_type, 0, 0, nw_src, 0, 0, 0)
>         else :
>            wildcards &= ~ofproto_v1_0.OFPFW_DL_TYPE
>            match = datapath.ofproto_parser.OFPMatch(
>             wildcards, in_port, 0, dst,
>             0, 0, _eth_type, 0, 0, 0, 0, 0, 0)
>
>         mod = datapath.ofproto_parser.OFPFlowMod(
>             datapath=datapath, match=match, cookie=0,
>             command=ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0,
>             priority=ofproto.OFP_DEFAULT_PRIORITY,
>             flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
>         datapath.send_msg(mod)
>
>     @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
>     """
>     This function handles packet-in messages from the switch and performs L2 
> learning and vlan
>     pcp to queue mapping.
>     """
>     def _packet_in_handler(self, ev):
>         msg = ev.msg
>         datapath = msg.datapath
>         ofproto = datapath.ofproto
>
>         dst, src, _eth_type, vlan_pcp = struct.unpack_from('!6s6sHB', 
> buffer(msg.data), 0)
>         vlan_pcp = int(vlan_pcp)/32

Can you use our packet library to parse packets?

>         dpid = datapath.id
>         self.mac_to_port.setdefault(dpid, {})
>         #Learn new MAC Address from packet-in message.
>         self.mac_to_port[dpid][src] = msg.in_port
>         nw_src = 0
>         #Flood the frame if destination MAC is unknown
>         if dst not in self.mac_to_port[dpid] and haddr_to_str(dst) != 
> 'ff:ff:ff:ff:ff:ff':
>             out_port = ofproto.OFPP_FLOOD
>             self.logger.info("Port for %s unknown -- flooding" % 
> haddr_to_str(dst))
>         #Flood the frame if destination MAC is Broadcast
>         elif haddr_to_str(dst) == 'ff:ff:ff:ff:ff:ff':
>             out_port = ofproto.OFPP_FLOOD
>             self.logger.info("Destination address %s is broadcast -- 
> flooding" % haddr_to_str(dst))
>         #Forward the frame based on MAC Address table learnings
>         elif dst in self.mac_to_port[dpid]:
>             out_port = self.mac_to_port[dpid][dst]
>             self.logger.info("packet in %s %s %s %s",
>                              dpid, haddr_to_str(src), haddr_to_str(dst),
>                              msg.in_port)
>             #Assign the flow to Queue ID 1 if the flow is untagged
>             if _eth_type == 2048:
>                q_id = 1
>                vlan_pcp = 0
>                a=struct.unpack_from('!6s6sHBxHBB2xIII', buffer(msg.data), 0)

Ditto.

>                nw_src = a[8]
>             #Assign the flow to the defined Queue ID if the flow is VLAN 
> tagged
>             elif _eth_type == 33024:
>                if self.pcp_queue.keys().count(vlan_pcp) == 0 :
>                   dict = {0:8, 1:7, 2:6, 3:5, 4:4, 5:3, 6:2, 7:1} #Default 
> Pbit to Queue mapping
>                   q_id = dict[vlan_pcp]
>                else :
>                   q_id = self.pcp_queue[vlan_pcp] #Overwrite Pbit to Queue 
> mapping with user defined inputs
>                a=struct.unpack_from('!6s6sHBxHBB2xIII', buffer(msg.data), 0)
>                nw_src = a[9]
>             else :
>                q_id = 1
>                vlan_pcp = 0
>
>         if out_port != ofproto.OFPP_FLOOD:
>            actions = 
> [datapath.ofproto_parser.OFPActionEnqueue(port=out_port,queue_id=q_id)]
>            self.add_flow(datapath, msg.in_port, dst,vlan_pcp, _eth_type, 
> nw_src, actions)
>         elif out_port == ofproto.OFPP_FLOOD:
>            actions = [datapath.ofproto_parser.OFPActionOutput(out_port)]
>         out = datapath.ofproto_parser.OFPPacketOut(
>               datapath=datapath, buffer_id=msg.buffer_id, in_port=msg.in_port,
>               actions=actions)
>         datapath.send_msg(out)
> #         out = 
> datapath.ofproto_parser.OFPQueueGetConfigRequest(datapath=datapath,port=1)
> #         datapath.send_msg(out)
>
>
>     @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
>     """
>     This function handles port status messages from the switch.
>     """
>     def _port_status_handler(self, ev):

We don't need this hander, right?

>         msg = ev.msg
>         reason = msg.reason
>         port_no = msg.desc.port_no
>
>         ofproto = msg.datapath.ofproto
>         if reason == ofproto.OFPPR_ADD:
>             self.logger.info("Port added %s", port_no)
>         elif reason == ofproto.OFPPR_DELETE:
>             self.logger.info("Port Deleted %s", port_no)
>         elif reason == ofproto.OFPPR_MODIFY:
>             self.logger.info("Port Modified %s", port_no)
>         else:
>             self.logger.info("Illegal Port State %s %s", port_no, reason)
>
>





Sample Test Plan for Testing OF Switch - Layer 2 QoS

Overview: This document describes the test plan and test methodology for 
testing OpenFlow QoS support.

Test Environment:

Operating System: Fedora Core 17 or Ubuntu 12.04
OpenFlow Switch: Open vSwitch Version 1.7.3
OpenFlow Controller: Ryu Controller

Test Pre-requisites:

Two Host Pcs
One PC for running Open vSwitch 
One PC for running Ryu Controller
Note: There should be IP connectivity between Open vSwitch PC and Ryu 
Controller PC.

Test Topology:
The testing is done using the topology i.e., OpenFlow switch connected with two 
hosts.
The test oversubscribes a link and then verifies whether traffic is treated as 
dictated by queue configuration. The setup includes the OpenFlow switch under 
testing, and two PCs which run instances of iperf server and clients. 
Instructions below list the test steps.

              RYU
               ^
               |
               |
 h2 --------> s1 --------> h3

s1 – Open vSwitch
h2, h3 – Two host PCs 

This is the topology used to verify the OF Switch QoS support using RYU 
controller – L2QoS Module

Test Configuration:

Configure h2 with a VLAN port and IP address:

vconfig add h2-eth0 100
vconfig set_egress_map h2-eth0.100 0 3
ifconfig h2-eth0 1.0.0.2 netmask 255.255.255.0
ifconfig h2-eth0 up
ifconfig h2-eth0.100 10.0.0.2 netmask 255.255.255.0

Configure h3 with a VLAN port and IP address:

vconfig add h3-eth0 100
vconfig set_egress_map h3-eth0.100 0 3
ifconfig h3-eth0 1.0.0.3 netmask 255.255.255.0
ifconfig h3-eth0 up
ifconfig h3-eth0.100 10.0.0.3 netmask 255.255.255.0

Configure Open vSwitch:
sudo ovs-vsctl add-br br0
sudo ovs-vsctl add-port br0 s1-eth1
sudo ovs-vsctl add-port br0 s1-eth2

Create Queues using the following commands in Open vSwitch
ovs-vsctl -- \

          add-br br0 -- \

           add-port br0 eth2 -- \

           add-port br0 em1 --  \

           set-controller br0 tcp:192.168.12.40:6633 -- \

           set port eth2 qos=@newqos -- \

           --id=@newqos create qos type=linux-htb \

               other-config:max-rate=10000000 \

               queues:1=@queue1 --\

           --id=@queue1 create queue other-config:max-rate=5000000 -- \

           set port em1 qos=@newqos1 -- \

           --id=@newqos1 create qos type=linux-htb \

               other-config:max-rate=10000000 \

               queues:4=@queue4 --\

           --id=@queue4 create queue other-config:max-rate=5000000


Flow installation for the pcp to queue mapping can be done using the RYU 
controller. 

Test Step 1: Verify Flow Table flow add support for flow without VLAN tag (PCP 
= 0):
Ping to 1.0.0.3 :
Console Output on h2 for non-vlan flow (pcp = 0):
PING 1.0.0.3 (1.0.0.3): 56 data bytes
64 bytes from 1.0.0.3: icmp_seq=0 ttl=64 time=125.147 ms
64 bytes from 1.0.0.3: icmp_seq=1 ttl=64 time=0.323 ms
64 bytes from 1.0.0.3: icmp_seq=2 ttl=64 time=0.054 ms
^C--- 1.0.0.3 ping statistics ---
round-trip min/avg/max/stddev = 0.054/25.137/125.147/50.005 ms

Ping to 1.0.0.2 :
Console Output on h3 for non-vlan flow (pcp = 0):
PING 1.0.0.2 (1.0.0.2): 56 data bytes
64 bytes from 1.0.0.2: icmp_seq=0 ttl=64 time=0.506 ms
64 bytes from 1.0.0.2: icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from 1.0.0.2: icmp_seq=2 ttl=64 time=0.068 ms
^C--- 1.0.0.2 ping statistics ---
round-trip min/avg/max/stddev = 0.067/0.157/0.506/0.174 ms

Open vSwitch Flow Table:
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=88.453s, table=0, n_packets=1, n_bytes=98, 
ip,in_port=1,dl_dst=1e:58:70:5d:1e:47,nw_src=1.0.0.2 actions=enqueue:2q1
 cookie=0x0, duration=89.457s, table=0, n_packets=2, n_bytes=196, 
ip,in_port=2,dl_dst=7a:7c:7b:f1:81:47,nw_src=1.0.0.3 actions=enqueue:1q1
 cookie=0x0, duration=84.446s, table=0, n_packets=1, n_bytes=42, 
arp,in_port=2,dl_dst=7a:7c:7b:f1:81:47 actions=enqueue:1q1
 cookie=0x0, duration=84.446s, table=0, n_packets=1, n_bytes=42, 
arp,in_port=1,dl_dst=1e:58:70:5d:1e:47 actions=enqueue:2q1


Test Step 2: Verify Flow Table flow add support for flow with VLAN tag (PCP=3) 
Ping to 10.0.0.3 :
Console Output on h2 for vlan flow (pcp = 3):
PING 10.0.0.3 (10.0.0.3): 56 data bytes
64 bytes from 10.0.0.3: icmp_seq=0 ttl=64 time=84.417 ms
64 bytes from 10.0.0.3: icmp_seq=1 ttl=64 time=0.271 ms
64 bytes from 10.0.0.3: icmp_seq=2 ttl=64 time=0.077 ms
^C--- 10.0.0.3 ping statistics ---
round-trip min/avg/max/stddev = 0.046/16.979/84.417/33.719 ms

Ping to 10.0.0.2 :
Console Output on h3 for vlan flow (pcp = 3):
PING 10.0.0.2 (10.0.0.2): 56 data bytes
64 bytes from 10.0.0.2: icmp_seq=0 ttl=64 time=0.502 ms
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.085 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.080 ms
^C--- 10.0.0.2 ping statistics ---
round-trip min/avg/max/stddev = 0.079/0.166/0.502/0.168 ms

Open vSwitch Flow Table:
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=249.637s, table=0, n_packets=5, n_bytes=442, 
in_port=1,dl_vlan_pcp=3,dl_dst=1e:58:70:5d:1e:47 actions=enqueue:2q4
 cookie=0x0, duration=249.595s, table=0, n_packets=6, n_bytes=488, 
in_port=2,dl_vlan_pcp=3,dl_dst=7a:7c:7b:f1:81:47 actions=enqueue:1q4
 cookie=0x0, duration=422.652s, table=0, n_packets=1, n_bytes=98, 
ip,in_port=1,dl_dst=1e:58:70:5d:1e:47,nw_src=1.0.0.2 actions=enqueue:2q1
 cookie=0x0, duration=423.656s, table=0, n_packets=2, n_bytes=196, 
ip,in_port=2,dl_dst=7a:7c:7b:f1:81:47,nw_src=1.0.0.3 actions=enqueue:1q1
 cookie=0x0, duration=418.645s, table=0, n_packets=1, n_bytes=42, 
arp,in_port=2,dl_dst=7a:7c:7b:f1:81:47 actions=enqueue:1q1
 cookie=0x0, duration=418.645s, table=0, n_packets=1, n_bytes=42, 
arp,in_port=1,dl_dst=1e:58:70:5d:1e:47 actions=enqueue:2q1


Bandwidth limitation can be checked by using iperf. Start iperf server in PC2 
and iperf client in PC1 for measuring the bandwidth.

Test Step 3: Verify bandwidth limitation support for flow without VLAN tag (PCP 
= 0):
Start iperf server using the command below at PC2
iperf -s -p 8011 -u -f m --reportstyle C -i 1 // udp server

Start iperf client using the command below at PC1
iperf -c 1.0.0.3 -p 8011 -i 1 -f m -t 120 -u -b 10000000

Verify that the output at the PC2 is 10Mbits/s(i.e Default queue max bandwidth 
size)

Test Step 4: Verify bandwidth limitation support for flow with VLAN tag (PCP = 
3):
Start iperf server using the command below at PC2
iperf -s -p 8011 -u -f m --reportstyle C -i 1 // udp server

Start iperf client using the command below at PC1
iperf -c 10.0.0.3 -p 8011 -i 1 -f m -t 120 -u -b 10000000

Verify that the output at the PC2 is 5Mbits/s(Queue 4 max bandwidth)

Conclusion:
Sample tests have been executed on Open vSwitch and observed that the switch 
supports en-queuing of flows and the traffic limitation according to the queue 
max bandwidth limitation is inconsistent.
--- L2QoS.py.orig	2013-08-30 14:48:43.000000000 +0530
+++ L2QoS.py	2013-08-30 14:49:11.000000000 +0530
@@ -0,0 +1,168 @@
+# Copyright (C) 2013 Veryx Technologies Pvt Limited.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+    This module performs L2 learning for an incoming flow, assigns it
+    to a specific egress port queue based on the flow's VLAN Pbit value and 
+    adds the flow entry in the switch flow table. The queue assignment will be 
+    based on default Pbit-Queue mapping defined by default in the module or 
+    overwritten using user defined value Pbit-Queue mapping value. Any flows 
+    received without VLAN tag will be assigned to Queue 1.
+    
+    The default Pbit-Queue mapping is {0:8, 1:7, 2:6, 3:5, 4:4, 5:3, 6:2, 7:1} where
+    0 denotes VLAN Pbit and 8 denotes Queue ID.  
+"""
+
+import logging
+import struct
+import ast
+
+from oslo.config import cfg
+from ryu.base import app_manager
+from ryu.controller import mac_to_port
+from ryu.controller import ofp_event
+from ryu.controller.handler import MAIN_DISPATCHER
+from ryu.controller.handler import set_ev_cls
+from ryu.ofproto import ofproto_v1_0
+from ryu.ofproto import ether
+from ryu.lib.mac import haddr_to_str
+from ryu.lib.packet import packet
+from ryu.lib.packet import ethernet
+from ryu.lib.packet import vlan
+
+# User-defined input
+# Below code re-assigns the Pbit-Queue mapping for Queue ID 4 and 5 with Pbit 5 and 6
+CONF = cfg.CONF
+CONF.register_cli_opts([
+    cfg.StrOpt('pcp-queue', default={5:4,6:5},
+                help='pcp to queue map')
+])
+
+
+class L2QoS(app_manager.RyuApp):
+    OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION]
+
+    def __init__(self, *args, **kwargs):
+        super(L2QoS, self).__init__(CONF.pcp_queue,*args, **kwargs)
+        self.mac_to_port = {}   # MAC Address table initialization
+        self.pcp_queue = CONF.pcp_queue
+        self.port = self.pcp_queue.keys()
+
+    """
+    This function installs the flow in the OpenFlow switch Flow Table
+    """
+    def add_flow(self, datapath, in_port, dst, vlan_pcp, _eth_type,nw_src, actions):
+        ofproto = datapath.ofproto
+        wildcards = ofproto_v1_0.OFPFW_ALL
+        wildcards &= ~ofproto_v1_0.OFPFW_IN_PORT
+        wildcards &= ~ofproto_v1_0.OFPFW_DL_DST
+        if _eth_type == ether.ETH_TYPE_8021Q :
+           wildcards &= ~ofproto_v1_0.OFPFW_DL_VLAN_PCP
+           wildcards &= ~ofproto_v1_0.OFPFW_NW_SRC_MASK
+           match = datapath.ofproto_parser.OFPMatch(
+            wildcards, in_port, 0, dst,
+            0, vlan_pcp, 0, 0, 0, nw_src, 0, 0, 0)
+        elif _eth_type == ether.ETH_TYPE_IP :
+           wildcards &= ~ofproto_v1_0.OFPFW_DL_TYPE
+           wildcards &= ~ofproto_v1_0.OFPFW_NW_SRC_MASK
+           match = datapath.ofproto_parser.OFPMatch(
+            wildcards, in_port, 0, dst,
+            0, 0, _eth_type, 0, 0, nw_src, 0, 0, 0)
+        else :
+           wildcards &= ~ofproto_v1_0.OFPFW_DL_TYPE
+           match = datapath.ofproto_parser.OFPMatch(
+            wildcards, in_port, 0, dst,
+            0, 0, _eth_type, 0, 0, 0, 0, 0, 0)
+
+        mod = datapath.ofproto_parser.OFPFlowMod(
+            datapath=datapath, match=match, cookie=0,
+            command=ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0,
+            priority=ofproto.OFP_DEFAULT_PRIORITY,
+            flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
+        datapath.send_msg(mod)
+
+   
+    """
+    This function handles packet-in messages from the switch and performs L2 learning and vlan 
+    pcp to queue mapping
+    """
+    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
+    def _packet_in_handler(self, ev):
+        msg = ev.msg
+        datapath = msg.datapath
+        ofproto = datapath.ofproto
+        pkt = packet.Packet(msg.data)
+        eth = pkt.get_protocols(ethernet.ethernet)[0]
+        dst = eth.dst
+        src = eth.src
+        _eth_type = eth.ethertype
+
+        dpid = datapath.id
+        self.mac_to_port.setdefault(dpid, {})
+        #Learn new MAC Address from packet-in message.
+        self.mac_to_port[dpid][src] = msg.in_port
+        nw_src = 0
+        #Flood the frame if destination MAC is unknown
+        if dst not in self.mac_to_port[dpid] and haddr_to_str(dst) != 'ff:ff:ff:ff:ff:ff': 
+            out_port = ofproto.OFPP_FLOOD
+            self.logger.info("Port for %s unknown -- flooding" % haddr_to_str(dst))
+        #Flood the frame if destination MAC is Broadcast
+        elif haddr_to_str(dst) == 'ff:ff:ff:ff:ff:ff': 
+            out_port = ofproto.OFPP_FLOOD
+            self.logger.info("Destination address %s is broadcast -- flooding" % haddr_to_str(dst))
+        #Forward the frame based on MAC Address table learnings
+        elif dst in self.mac_to_port[dpid]: 
+            out_port = self.mac_to_port[dpid][dst]
+            self.logger.info("packet in %s %s %s %s",
+                             dpid, haddr_to_str(src), haddr_to_str(dst),
+                             msg.in_port)
+            #Assign the flow to Queue ID 1 if the flow is untagged
+            if _eth_type == 2048: 
+               q_id = 1
+               vlan_pcp = 0
+               _eth_type = 0x0800
+               a=struct.unpack_from('!6s6sHBxHBB2xIII', buffer(msg.data), 0)
+               nw_src = a[8]
+            #Assign the flow to the defined Queue ID if the flow is VLAN tagged
+            elif _eth_type == 33024:
+               _eth_type = 0x8100  
+               vlan1q = pkt.get_protocols(vlan.vlan)[0]
+               vlan_pcp = vlan1q.pcp
+               if self.pcp_queue.keys().count(vlan_pcp) == 0 : 
+                  dict = {0:8, 1:7, 2:6, 3:5, 4:4, 5:3, 6:2, 7:1} #Default Pbit to Queue mapping
+                  q_id = dict[vlan_pcp]
+               else :
+                  q_id = self.pcp_queue[vlan_pcp] #Overwrite Pbit to Queue mapping with user defined inputs
+               a=struct.unpack_from('!6s6sHBxHBB2xIII', buffer(msg.data), 0)
+               nw_src = a[9]   
+            else : 
+               q_id = 1
+               vlan_pcp = 0            
+        
+        if out_port != ofproto.OFPP_FLOOD:
+           actions = [datapath.ofproto_parser.OFPActionEnqueue(port=out_port,queue_id=q_id)]
+           self.add_flow(datapath, msg.in_port, dst,vlan_pcp, _eth_type, nw_src, actions)
+        elif out_port == ofproto.OFPP_FLOOD:
+           actions = [datapath.ofproto_parser.OFPActionOutput(out_port)]
+        out = datapath.ofproto_parser.OFPPacketOut(
+              datapath=datapath, buffer_id=msg.buffer_id, in_port=msg.in_port,
+              actions=actions)
+        datapath.send_msg(out)
+#         out = datapath.ofproto_parser.OFPQueueGetConfigRequest(datapath=datapath,port=1)
+#         datapath.send_msg(out)
+
+
+
+
------------------------------------------------------------------------------
Learn the latest--Visual Studio 2012, SharePoint 2013, SQL 2012, more!
Discover the easy way to master current and previous Microsoft technologies
and advance your career. Get an incredible 1,500+ hours of step-by-step
tutorial videos with LearnDevNow. Subscribe today and save!
http://pubads.g.doubleclick.net/gampad/clk?id=58040911&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to