On Thu, Oct 25, 2012 at 11:14:34PM -0700, Ben Pfaff wrote:
> On Thu, Oct 25, 2012 at 05:12:21PM -0700, Ben Pfaff wrote:
> > It passes a few tests; I've only tried a few.
> >
> > Now that I look at it, there are some bugs here that will prevent
> > traffic from actually passing through, but they are not fundamental to
> > the approach. I'm mostly passing this along in case anyone wants to
> > comment on the idea; I've already spent more time on it than I should
> > have.
>
> I'm attaching updated dummy.py and start-sandbox scripts. With these
> versions, the command
Well, I meant to attach them. Here they are.
#! /bin/sh
set -ex
srcdir=$HOME/nicira/ovs
builddir=$srcdir/_build
PATH=$builddir/ovsdb:$builddir/vswitchd:$builddir/utilities:$PATH
cd $builddir
rm -rf sandbox
mkdir sandbox
cd sandbox
OVS_RUNDIR=`pwd`; export OVS_RUNDIR
OVS_LOGDIR=`pwd`; export OVS_LOGDIR
OVS_DBDIR=`pwd`; export OVS_DBDIR
OVS_SYSCONFDIR=`pwd`; export OVS_SYSCONFDIR
trap 'kill `cat *.pid`' 0 1 2 3 13 14 15
touch .conf.db.~lock~
rm -f conf.db
ovsdb-tool create conf.db $srcdir/vswitchd/vswitch.ovsschema
ovsdb-server --detach --no-chdir --pidfile --log-file
--remote=punix:$OVS_RUNDIR/db.sock
ovs-vsctl --no-wait init
ovs-vswitchd --detach --no-chdir --pidfile --log-file --enable-dummy
--disable-system -vvconn -vnetdev_dummy
ovs-vsctl --no-wait \
-- add-br br0 \
-- set bridge br0 datapath-type=dummy fail-mode=secure
for port in p1 p2 p3 p4; do
ovs-vsctl --no-wait \
-- add-port br0 $port \
-- set interface $port type=dummy \
options:pstream=punix:$OVS_RUNDIR/$port
done
ovs-vsctl \
-- set-controller br0 tcp:127.0.0.1 \
-- set controller br0 connection-mode=out-of-band max-backoff=1000
read line
"""
Dummy platform
This platform uses Open vSwitch dummy interfaces.
"""
import logging
import os
import select
import socket
import struct
import sys
import time
from threading import Thread
from threading import Lock
RCV_TIMEOUT = 10000
RUN_DIR = os.environ.get("OVS_RUNDIR", "/var/run/openvswitch")
class DataPlanePortUnix(Thread):
"""
Class defining a port monitoring object that uses Unix domain
sockets for ports, intended for connecting to Open vSwitch "dummy"
netdevs.
"""
def __init__(self, interface_name, port_number, parent, max_pkts=1024):
"""
Set up a port monitor object
@param interface_name The name of the physical interface like eth1
@param port_number The port number associated with this port
@param parent The controlling dataplane object; for pkt wait CV
@param max_pkts Maximum number of pkts to keep in queue
"""
Thread.__init__(self)
self.interface_name = interface_name
self.max_pkts = max_pkts
self.packets_total = 0
self.packets = []
self.packets_discarded = 0
self.port_number = port_number
self.txq = []
self.txq_lock = Lock()
logname = "dp-" + interface_name
self.logger = logging.getLogger(logname)
try:
self.socket = DataPlanePortUnix.interface_open(interface_name)
except:
self.logger.info("Could not open socket")
raise
self.logger.info("Opened port monitor (class %s)", type(self).__name__)
self.parent = parent
@staticmethod
def interface_open(interface_name):
"""
Open a Unix domain socket interface.
@param interface_name port name as a string such as 'eth1'
@retval s socket
"""
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.settimeout(RCV_TIMEOUT)
s.setblocking(0)
s.connect("%s/%s" % (RUN_DIR, interface_name))
return s
def run(self):
"""
Activity function for class
"""
self.running = True
rxbuf = ""
while self.running:
try:
self.txq_lock.acquire()
if self.txq:
wlist = [self.socket]
else:
wlist = []
self.txq_lock.release()
rout, wout, eout = select.select([self.socket], wlist, [], 1)
except:
print sys.exc_info()
self.logger.error("Select error, exiting")
break
if not self.running:
break
if wout:
self.txq_lock.acquire()
if self.txq:
retval = self.socket.send(self.txq[0])
if retval > 0:
self.txq[0] = self.txq[0][retval:]
if len(self.txq[0]) == 0:
self.txq = self.txq[1:]
self.txq_lock.release()
if rout:
if len(rxbuf) < 2:
n = 2 - len(rxbuf)
else:
frame_len = struct.unpack('>h', rxbuf[:2])[0]
n = (2 + frame_len) - len(rxbuf)
data = self.socket.recv(n)
rxbuf += data
if len(data) == n and len(rxbuf) > 2:
rcvtime = time.clock()
self.logger.debug("Pkt len " + str(len(rxbuf)) +
" in at " + str(rcvtime) + " on port " +
str(self.port_number))
# Enqueue packet
with self.parent.pkt_sync:
if len(self.packets) >= self.max_pkts:
# Queue full, throw away oldest
self.packets.pop(0)
self.packets_discarded += 1
self.logger.debug("Discarding oldest packet to make room")
self.packets.append((rxbuf[2:], rcvtime))
self.packets_total += 1
self.parent.pkt_sync.notify_all()
rxbuf = ''
self.logger.info("Thread exit")
def kill(self):
"""
Terminate the running thread
"""
self.logger.debug("Port monitor kill")
self.running = False
try:
self.socket.close()
except:
self.logger.info("Ignoring dataplane soc shutdown error")
def timestamp_head(self):
"""
Return the timestamp of the head of queue or None if empty
"""
rv = None
try:
rv = self.packets[0][1]
except:
rv = None
return rv
def flush(self):
"""
Clear the packet queue
"""
with self.parent.pkt_sync:
self.packets_discarded += len(self.packets)
self.packets = []
def send(self, packet):
"""
Send a packet to the dataplane port
@param packet The packet data to send to the port
@retval The number of bytes sent
"""
self.txq_lock.acquire()
if len(self.txq) < self.max_pkts:
self.txq.append(struct.pack('>h', len(packet)) + packet)
retval = len(packet)
else:
retval = 0
self.txq_lock.release()
return retval
def register(self, handler):
"""
Register a callback function to receive packets from this
port. The callback will be passed the packet, the
interface name and the port number (if set) on which the
packet was received.
To be implemented
"""
pass
def show(self, prefix=''):
print prefix + "Name: " + self.interface_name
print prefix + "Pkts pending: " + str(len(self.packets))
print prefix + "Pkts total: " + str(self.packets_total)
print prefix + "socket: " + str(self.socket)
# Update this dictionary to suit your environment.
dummy_port_map = {
1 : "p1",
2 : "p2",
3 : "p3",
4 : "p4"
}
def platform_config_update(config):
"""
Update configuration for the dummy platform
@param config The configuration dictionary to use/update
"""
global dummy_port_map
config["port_map"] = dummy_port_map.copy()
config["caps_table_idx"] = 0
config["dataplane"] = {"portclass": DataPlanePortUnix}
config["allow_user"] = True
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev