blob: a2f17905bc4506f503bf182c441679cf2e6ac4c6 [file] [log] [blame]
Rich Lane17215b32012-10-26 18:01:12 -07001"""
2Dummy platform
3
4This platform uses Open vSwitch dummy interfaces.
5"""
6
7import logging
8import os
9import select
10import socket
11import struct
12import sys
13import time
14from threading import Thread
15from threading import Lock
16
17RCV_TIMEOUT = 10000
18RUN_DIR = os.environ.get("OVS_RUNDIR", "/var/run/openvswitch")
19
Ben Pfaff40661482013-02-01 13:37:59 -080020class DataPlanePortOVSDummy:
Rich Lane17215b32012-10-26 18:01:12 -070021 """
22 Class defining a port monitoring object that uses Unix domain
23 sockets for ports, intended for connecting to Open vSwitch "dummy"
24 netdevs.
25 """
26
Ben Pfaff40661482013-02-01 13:37:59 -080027 def __init__(self, interface_name, port_number, max_pkts=1024):
Rich Lane17215b32012-10-26 18:01:12 -070028 """
29 Set up a port monitor object
30 @param interface_name The name of the physical interface like eth1
31 @param port_number The port number associated with this port
Rich Lane17215b32012-10-26 18:01:12 -070032 @param max_pkts Maximum number of pkts to keep in queue
33 """
Rich Lane17215b32012-10-26 18:01:12 -070034 self.interface_name = interface_name
35 self.max_pkts = max_pkts
Rich Lane17215b32012-10-26 18:01:12 -070036 self.port_number = port_number
37 self.txq = []
Ben Pfaff40661482013-02-01 13:37:59 -080038 self.rxbuf = ""
Rich Lane17215b32012-10-26 18:01:12 -070039 logname = "dp-" + interface_name
40 self.logger = logging.getLogger(logname)
41 try:
42 self.socket = DataPlanePortOVSDummy.interface_open(interface_name)
43 except:
44 self.logger.info("Could not open socket")
45 raise
46 self.logger.info("Opened port monitor (class %s)", type(self).__name__)
Rich Lane17215b32012-10-26 18:01:12 -070047
48 @staticmethod
49 def interface_open(interface_name):
50 """
51 Open a Unix domain socket interface.
52 @param interface_name port name as a string such as 'eth1'
53 @retval s socket
54 """
55 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
56 s.settimeout(RCV_TIMEOUT)
57 s.setblocking(0)
58 s.connect("%s/%s" % (RUN_DIR, interface_name))
59 return s
60
Ben Pfaff40661482013-02-01 13:37:59 -080061 def __del__(self):
62 if self.socket:
Rich Lane17215b32012-10-26 18:01:12 -070063 self.socket.close()
Rich Lane17215b32012-10-26 18:01:12 -070064
Ben Pfaff40661482013-02-01 13:37:59 -080065 def fileno(self):
Rich Lane17215b32012-10-26 18:01:12 -070066 """
Ben Pfaff40661482013-02-01 13:37:59 -080067 Return an integer file descriptor that can be passed to select(2).
Rich Lane17215b32012-10-26 18:01:12 -070068 """
Ben Pfaff40661482013-02-01 13:37:59 -080069 return self.socket.fileno()
Rich Lane17215b32012-10-26 18:01:12 -070070
Ben Pfaff40661482013-02-01 13:37:59 -080071 def recv(self):
72 while True:
73 rout, wout, eout = select.select([self.socket], [], [], 0)
74 if not rout:
75 return
76
77 if len(self.rxbuf) < 2:
78 n = 2 - len(self.rxbuf)
79 else:
80 frame_len = struct.unpack('>h', self.rxbuf[:2])[0]
81 n = (2 + frame_len) - len(self.rxbuf)
82
83 data = self.socket.recv(n)
84 self.rxbuf += data
85 if len(data) == n and len(self.rxbuf) > 2:
86 rcvtime = time.time()
87 packet = self.rxbuf[2:]
88 self.logger.debug("Pkt len " + str(len(packet)) +
89 " in at " + str(rcvtime) + " on port " +
90 str(self.port_number))
91 self.rxbuf = ""
92 return (packet, rcvtime)
Rich Lane17215b32012-10-26 18:01:12 -070093
94 def send(self, packet):
Rich Lane17215b32012-10-26 18:01:12 -070095 if len(self.txq) < self.max_pkts:
96 self.txq.append(struct.pack('>h', len(packet)) + packet)
97 retval = len(packet)
98 else:
99 retval = 0
Ben Pfaff40661482013-02-01 13:37:59 -0800100 self.__run_tx()
Rich Lane17215b32012-10-26 18:01:12 -0700101 return retval
102
Ben Pfaff40661482013-02-01 13:37:59 -0800103 def __run_tx(self):
104 while self.txq:
105 rout, wout, eout = select.select([], [self.socket], [], 0)
106 if not wout:
107 return
Rich Lane17215b32012-10-26 18:01:12 -0700108
Ben Pfaff40661482013-02-01 13:37:59 -0800109 retval = self.socket.send(self.txq[0])
110 if retval > 0:
111 self.txq[0] = self.txq[0][retval:]
112 if len(self.txq[0]) == 0:
113 self.txq = self.txq[1:]
114
115 def down(self):
Rich Lane17215b32012-10-26 18:01:12 -0700116 pass
117
Ben Pfaff40661482013-02-01 13:37:59 -0800118 def up(self):
119 pass
Rich Lane17215b32012-10-26 18:01:12 -0700120
121# Update this dictionary to suit your environment.
122dummy_port_map = {
123 1 : "p1",
124 2 : "p2",
125 3 : "p3",
126 4 : "p4"
127}
128
129def platform_config_update(config):
130 """
131 Update configuration for the dummy platform
132
133 @param config The configuration dictionary to use/update
134 """
135 global dummy_port_map
136 config["port_map"] = dummy_port_map.copy()
137 config["caps_table_idx"] = 0
138 config["dataplane"] = {"portclass": DataPlanePortOVSDummy}
139 config["allow_user"] = True