blob: ca7652f271d8b77f8ca8c1ef0c8d375ea6f9874c [file] [log] [blame]
Zsolt Harasztied091602016-12-08 13:36:38 -08001#
2# Copyright 2016 the original author or authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
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 implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17"""
18Tibit OLT device adapter
19"""
Zsolt Haraszti4ef0a9a2016-12-20 01:35:48 -080020import json
Zsolt Haraszti4ef0a9a2016-12-20 01:35:48 -080021from uuid import uuid4
22
Zsolt Haraszti80175202016-12-24 00:17:51 -080023import structlog
24from scapy.fields import StrField
Zsolt Haraszti348d1932016-12-10 01:10:07 -080025from scapy.layers.l2 import Ether, Dot1Q
Zsolt Haraszti80175202016-12-24 00:17:51 -080026from scapy.packet import Packet, bind_layers
Zsolt Haraszti89a27302016-12-08 16:53:06 -080027from twisted.internet import reactor
Zsolt Haraszti80175202016-12-24 00:17:51 -080028from twisted.internet.defer import DeferredQueue, inlineCallbacks
Zsolt Harasztied091602016-12-08 13:36:38 -080029from zope.interface import implementer
30
Zsolt Haraszti313c4be2016-12-27 11:06:53 -080031from common.frameio.frameio import BpfProgramFilter, hexify
Zsolt Harasztied091602016-12-08 13:36:38 -080032from voltha.adapters.interface import IAdapterInterface
Nathan Knuth31c36962016-12-27 10:04:49 -080033from voltha.extensions.eoam.EOAM import EOAMPayload, DPoEOpcode_SetRequest
34from voltha.extensions.eoam.EOAM_TLV import DOLTObject, \
Zsolt Haraszti80175202016-12-24 00:17:51 -080035 PortIngressRuleClauseMatchLength02, PortIngressRuleResultForward, \
36 PortIngressRuleResultSet, PortIngressRuleResultInsert, \
Zsolt Haraszti313c4be2016-12-27 11:06:53 -080037 PortIngressRuleTerminator, AddPortIngressRule, CablelabsOUI, PonPortObject
Nathan Knuth31c36962016-12-27 10:04:49 -080038from voltha.extensions.eoam.EOAM_TLV import PortIngressRuleHeader
39from voltha.extensions.eoam.EOAM_TLV import ClauseSubtypeEnum as Clause
Zsolt Haraszti80175202016-12-24 00:17:51 -080040from voltha.core.flow_decomposer import *
Zsolt Harasztiaa4626e2016-12-08 16:53:06 -080041from voltha.core.logical_device_agent import mac_str_to_tuple
Zsolt Harasztied091602016-12-08 13:36:38 -080042from voltha.protos.adapter_pb2 import Adapter, AdapterConfig
Zsolt Haraszti80175202016-12-24 00:17:51 -080043from voltha.protos.common_pb2 import LogLevel, ConnectStatus
44from voltha.protos.common_pb2 import OperStatus, AdminState
Zsolt Haraszti4ef0a9a2016-12-20 01:35:48 -080045from voltha.protos.device_pb2 import Device, Port
Zsolt Harasztied091602016-12-08 13:36:38 -080046from voltha.protos.device_pb2 import DeviceType, DeviceTypes
47from voltha.protos.health_pb2 import HealthStatus
Zsolt Harasztiaa4626e2016-12-08 16:53:06 -080048from voltha.protos.logical_device_pb2 import LogicalDevice, LogicalPort
49from voltha.protos.openflow_13_pb2 import ofp_desc, ofp_port, OFPPF_10GB_FD, \
50 OFPPF_FIBER, OFPPS_LIVE, ofp_switch_features, OFPC_PORT_STATS, \
51 OFPC_GROUP_STATS, OFPC_TABLE_STATS, OFPC_FLOW_STATS
Zsolt Haraszti80175202016-12-24 00:17:51 -080052from voltha.registry import registry
Zsolt Haraszti348d1932016-12-10 01:10:07 -080053log = structlog.get_logger()
Zsolt Harasztied091602016-12-08 13:36:38 -080054
Nathan Knuth6e57f332016-12-22 15:49:20 -080055# Match on the MGMT VLAN, Priority 7
Zsolt Haraszti313c4be2016-12-27 11:06:53 -080056TIBIT_MGMT_VLAN = 4090
57TIBIT_MGMT_PRIORITY = 7
58frame_match_case1 = 'ether[14:2] = 0x{:01x}{:03x}'.format(
59 TIBIT_MGMT_PRIORITY << 1, TIBIT_MGMT_VLAN)
60
61TIBIT_PACKET_IN_VLAN = 4000
62frame_match_case2 = '(ether[14:2] & 0xfff) = 0x{:03x}'.format(
63 TIBIT_PACKET_IN_VLAN)
64
65is_tibit_frame = BpfProgramFilter('{} or {}'.format(
66 frame_match_case1, frame_match_case2))
67
Nathan Knuth6e57f332016-12-22 15:49:20 -080068#is_tibit_frame = lambda x: True
Zsolt Haraszti89a27302016-12-08 16:53:06 -080069
Zsolt Haraszti85f12852016-12-24 08:30:58 -080070
Zsolt Haraszti348d1932016-12-10 01:10:07 -080071# To be removed in favor of OAM
Zsolt Haraszti89a27302016-12-08 16:53:06 -080072class TBJSON(Packet):
73 """ TBJSON 'packet' layer. """
74 name = "TBJSON"
75 fields_desc = [StrField("data", default="")]
76
Nathan Knuth6e57f332016-12-22 15:49:20 -080077bind_layers(Ether, TBJSON, type=0x9001)
Zsolt Haraszti4ef0a9a2016-12-20 01:35:48 -080078
Zsolt Haraszti85f12852016-12-24 08:30:58 -080079
Zsolt Harasztied091602016-12-08 13:36:38 -080080@implementer(IAdapterInterface)
81class TibitOltAdapter(object):
82
83 name = 'tibit_olt'
84
85 supported_device_types = [
86 DeviceType(
87 id='tibit_olt',
88 adapter=name,
89 accepts_bulk_flow_update=True
90 )
91 ]
92
93 def __init__(self, adapter_agent, config):
94 self.adapter_agent = adapter_agent
95 self.config = config
96 self.descriptor = Adapter(
97 id=self.name,
98 vendor='Tibit Communications Inc.',
99 version='0.1',
100 config=AdapterConfig(log_level=LogLevel.INFO)
101 )
Zsolt Harasztia17f3ec2016-12-08 14:55:49 -0800102 self.interface = registry('main').get_args().interface
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800103 self.io_port = None
Nathan Knuth6e57f332016-12-22 15:49:20 -0800104 self.incoming_queues = {} # OLT mac_address -> DeferredQueue()
105 self.device_ids = {} # OLT mac_address -> device_id
Zsolt Haraszti313c4be2016-12-27 11:06:53 -0800106 self.vlan_to_device_ids = {} # c-vid -> (device_id, logical_device_id)
Zsolt Harasztied091602016-12-08 13:36:38 -0800107
108 def start(self):
Zsolt Harasztia17f3ec2016-12-08 14:55:49 -0800109 log.debug('starting', interface=self.interface)
110 log.info('started', interface=self.interface)
Zsolt Harasztied091602016-12-08 13:36:38 -0800111
112 def stop(self):
113 log.debug('stopping')
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800114 if self.io_port is not None:
115 registry('frameio').del_interface(self.interface)
Zsolt Harasztied091602016-12-08 13:36:38 -0800116 log.info('stopped')
117
118 def adapter_descriptor(self):
119 return self.descriptor
120
121 def device_types(self):
122 return DeviceTypes(items=self.supported_device_types)
123
124 def health(self):
125 return HealthStatus(state=HealthStatus.HealthState.HEALTHY)
126
127 def change_master_state(self, master):
128 raise NotImplementedError()
129
130 def adopt_device(self, device):
131 log.info('adopt-device', device=device)
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800132 self._activate_io_port()
133 reactor.callLater(0, self._launch_device_activation, device)
Zsolt Harasztied091602016-12-08 13:36:38 -0800134
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800135 def _activate_io_port(self):
136 if self.io_port is None:
137 self.io_port = registry('frameio').add_interface(
138 self.interface, self._rcv_io, is_tibit_frame)
139
140 @inlineCallbacks
141 def _launch_device_activation(self, device):
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800142 try:
143 log.debug('launch_dev_activation')
144 # prepare receive queue
145 self.incoming_queues[device.mac_address] = DeferredQueue(size=100)
146
Nathan Knuth6e57f332016-12-22 15:49:20 -0800147 # add mac_address to device_ids table
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800148 olt_mac = device.mac_address
Nathan Knuth6e57f332016-12-22 15:49:20 -0800149 self.device_ids[olt_mac] = device.id
150
151 # send out ping to OLT device
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800152 ping_frame = self._make_ping_frame(mac_address=olt_mac)
153 self.io_port.send(ping_frame)
154
155 # wait till we receive a response
Nathan Knuth6e57f332016-12-22 15:49:20 -0800156 ## TODO add timeout mechanism so we can signal if we cannot reach
157 ##device
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800158 while True:
159 response = yield self.incoming_queues[olt_mac].get()
160 # verify response and if not the expected response
161 if 1: # TODO check if it is really what we expect, and wait if not
162 break
163
164 except Exception, e:
165 log.exception('launch device failed', e=e)
166
167 # if we got response, we can fill out the device info, mark the device
168 # reachable
Zsolt Haraszti80175202016-12-24 00:17:51 -0800169 # jdev = json.loads(response.data[5:])
170 jdev = json.loads(response.payload.payload.body.load)
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800171 device.root = True
Zsolt Haraszti4ef0a9a2016-12-20 01:35:48 -0800172 device.vendor = 'Tibit Communications, Inc.'
Nathan Knuth6e57f332016-12-22 15:49:20 -0800173 device.model = jdev.get('results', {}).get('device', 'DEVICE_UNKNOWN')
Zsolt Haraszti4ef0a9a2016-12-20 01:35:48 -0800174 device.hardware_version = jdev['results']['datecode']
175 device.firmware_version = jdev['results']['firmware']
176 device.software_version = jdev['results']['modelversion']
177 device.serial_number = jdev['results']['manufacturer']
Nathan Knuth6e57f332016-12-22 15:49:20 -0800178
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800179 device.connect_status = ConnectStatus.REACHABLE
180 self.adapter_agent.update_device(device)
181
Zsolt Harasztiaa4626e2016-12-08 16:53:06 -0800182 # then shortly after we create some ports for the device
183 log.info('create-port')
184 nni_port = Port(
185 port_no=2,
186 label='NNI facing Ethernet port',
187 type=Port.ETHERNET_NNI,
188 admin_state=AdminState.ENABLED,
189 oper_status=OperStatus.ACTIVE
190 )
191 self.adapter_agent.add_port(device.id, nni_port)
192 self.adapter_agent.add_port(device.id, Port(
193 port_no=1,
194 label='PON port',
195 type=Port.PON_OLT,
196 admin_state=AdminState.ENABLED,
197 oper_status=OperStatus.ACTIVE
198 ))
199
200 log.info('create-logical-device')
201 # then shortly after we create the logical device with one port
202 # that will correspond to the NNI port
203 logical_device_id = uuid4().hex[:12]
204 ld = LogicalDevice(
205 id=logical_device_id,
206 datapath_id=int('0x' + logical_device_id[:8], 16), # from id
207 desc=ofp_desc(
208 mfr_desc=device.vendor,
209 hw_desc=jdev['results']['device'],
210 sw_desc=jdev['results']['firmware'],
211 serial_num=uuid4().hex,
212 dp_desc='n/a'
213 ),
214 switch_features=ofp_switch_features(
215 n_buffers=256, # TODO fake for now
216 n_tables=2, # TODO ditto
217 capabilities=( # TODO and ditto
218 OFPC_FLOW_STATS
219 | OFPC_TABLE_STATS
220 | OFPC_PORT_STATS
221 | OFPC_GROUP_STATS
222 )
223 ),
224 root_device_id=device.id
225 )
226 self.adapter_agent.create_logical_device(ld)
227 cap = OFPPF_10GB_FD | OFPPF_FIBER
228 self.adapter_agent.add_logical_port(ld.id, LogicalPort(
229 id='nni',
230 ofp_port=ofp_port(
231 port_no=129,
232 hw_addr=mac_str_to_tuple(device.mac_address),
233 name='nni',
234 config=0,
235 state=OFPPS_LIVE,
236 curr=cap,
237 advertised=cap,
238 peer=cap,
239 curr_speed=OFPPF_10GB_FD,
240 max_speed=OFPPF_10GB_FD
241 ),
242 device_id=device.id,
243 device_port_no=nni_port.port_no,
244 root_port=True
245 ))
246
247 # and finally update to active
248 device = self.adapter_agent.get_device(device.id)
249 device.parent_id = ld.id
250 device.oper_status = OperStatus.ACTIVE
251 self.adapter_agent.update_device(device)
252
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800253 # Just transitioned to ACTIVE, wait a tenth of second
254 # before checking for ONUs
255 reactor.callLater(0.1, self._detect_onus, device)
256
257 @inlineCallbacks
258 def _detect_onus(self, device):
259 # send out get 'links' to the OLT device
260 olt_mac = device.mac_address
261 links_frame = self._make_links_frame(mac_address=olt_mac)
262 self.io_port.send(links_frame)
263 while True:
264 response = yield self.incoming_queues[olt_mac].get()
265 # verify response and if not the expected response
266 if 1: # TODO check if it is really what we expect, and wait if not
267 break
268
Zsolt Haraszti80175202016-12-24 00:17:51 -0800269 jdev = json.loads(response.payload.payload.body.load)
Nathan Knuth6e57f332016-12-22 15:49:20 -0800270 tibit_mac = ''
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800271 for macid in jdev['results']:
272 if macid['macid'] is None:
273 log.info('MAC ID is NONE %s' % str(macid['macid']))
274 else:
Nathan Knuth6e57f332016-12-22 15:49:20 -0800275 tibit_mac = '000c' + macid.get('macid', 'e2000000')[4:]
276 log.info('activate-olt-for-onu-%s' % tibit_mac)
277
278 # Convert from string to colon separated form
279 tibit_mac = ':'.join(s.encode('hex') for s in tibit_mac.decode('hex'))
280
Zsolt Haraszti313c4be2016-12-27 11:06:53 -0800281 vlan_id = self._olt_side_onu_activation(int(macid['macid'][-4:-2], 16))
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800282 self.adapter_agent.child_device_detected(
283 parent_device_id=device.id,
284 parent_port_no=1,
285 child_device_type='tibit_onu',
Nathan Knuth6e57f332016-12-22 15:49:20 -0800286 mac_address = tibit_mac,
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800287 proxy_address=Device.ProxyAddress(
288 device_id=device.id,
289 channel_id=vlan_id
290 ),
291 vlan=vlan_id
292 )
293
Zsolt Haraszti313c4be2016-12-27 11:06:53 -0800294 # also record the vlan_id -> (device_id, logical_device_id) for
295 # later use
296 self.vlan_to_device_ids[vlan_id] = (device.id, device.parent_id)
297
Nathan Knuth6e57f332016-12-22 15:49:20 -0800298 def _olt_side_onu_activation(self, serial):
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800299 """
300 This is where if this was a real OLT, the OLT-side activation for
301 the new ONU should be performed. By the time we return, the OLT shall
302 be able to provide tunneled (proxy) communication to the given ONU,
303 using the returned information.
304 """
Nathan Knuth6e57f332016-12-22 15:49:20 -0800305 vlan_id = serial + 200
Zsolt Haraszti313c4be2016-12-27 11:06:53 -0800306 return vlan_id
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800307
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800308 def _rcv_io(self, port, frame):
309
Zsolt Haraszti313c4be2016-12-27 11:06:53 -0800310 log.info('frame-received', frame=hexify(frame))
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800311
Zsolt Haraszti4ef0a9a2016-12-20 01:35:48 -0800312 # make into frame to extract source mac
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800313 response = Ether(frame)
314
Nathan Knuth6e57f332016-12-22 15:49:20 -0800315 if response.haslayer(Dot1Q):
Nathan Knuth6e57f332016-12-22 15:49:20 -0800316
Zsolt Haraszti313c4be2016-12-27 11:06:53 -0800317 # All OAM responses from the OLT should have a TIBIT_MGMT_VLAN.
318 # Responses from the ONUs should have a TIBIT_MGMT_VLAN followed by a ONU CTAG
319 # All packet-in frames will have the TIBIT_PACKET_IN_VLAN.
320 if response.getlayer(Dot1Q).type == 0x8100:
321
322 if response.getlayer(Dot1Q).vlan == TIBIT_PACKET_IN_VLAN:
323
324 inner_tag_and_rest = response.payload.payload
325
326 inner_tag_and_rest.show() # TODO remove this soon
327
328 if isinstance(inner_tag_and_rest, Dot1Q):
329
330 cvid = inner_tag_and_rest.vlan
331
332 frame = Ether(src=response.src,
333 dst=response.dst,
334 type=inner_tag_and_rest.type) /\
335 inner_tag_and_rest.payload
336
337 _, logical_device_id = self.vlan_to_device_ids.get(cvid)
338 if logical_device_id is None:
339 log.error('invalid-cvid', cvid=cvid)
340 else:
341 self.adapter_agent.send_packet_in(
342 logical_device_id=logical_device_id,
343 logical_port_no=cvid, # C-VID encodes port no
344 packet=str(frame))
345
346 else:
347 log.error('packet-in-single-tagged',
348 frame=hexify(response))
349
350 else:
351 ## Responses from the ONU
352 ## Since the type of the first layer is 0x8100,
353 ## then the frame must have an inner tag layer
354 olt_mac = response.src
355 device_id = self.device_ids[olt_mac]
356 channel_id = response[Dot1Q:2].vlan
357 log.info('received_channel_id', channel_id=channel_id,
358 device_id=device_id)
359
360 proxy_address=Device.ProxyAddress(
361 device_id=device_id,
362 channel_id=channel_id
363 )
364 # pop dot1q header(s)
365 msg = response.payload.payload
366 self.adapter_agent.receive_proxied_message(proxy_address, msg)
367
Nathan Knuth6e57f332016-12-22 15:49:20 -0800368 else:
369 ## Respones from the OLT
370 ## enqueue incoming parsed frame to right device
Zsolt Haraszti313c4be2016-12-27 11:06:53 -0800371 log.info('received-dot1q-not-8100')
Nathan Knuth6e57f332016-12-22 15:49:20 -0800372 self.incoming_queues[response.src].put(response)
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800373
374 def _make_ping_frame(self, mac_address):
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800375 # Create a json packet
376 json_operation_str = '{\"operation\":\"version\"}'
Nathan Knuth6e57f332016-12-22 15:49:20 -0800377 frame = Ether(dst=mac_address)/Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY)/TBJSON(data='json %s' % json_operation_str)
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800378 return str(frame)
379
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800380 def _make_links_frame(self, mac_address):
381 # Create a json packet
382 json_operation_str = '{\"operation\":\"links\"}'
Nathan Knuth6e57f332016-12-22 15:49:20 -0800383 frame = Ether(dst=mac_address)/Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY)/TBJSON(data='json %s' % json_operation_str)
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800384 return str(frame)
385
Zsolt Harasztied091602016-12-08 13:36:38 -0800386 def abandon_device(self, device):
387 raise NotImplementedError(0
388 )
389 def deactivate_device(self, device):
390 raise NotImplementedError()
391
392 def update_flows_bulk(self, device, flows, groups):
Zsolt Haraszti80175202016-12-24 00:17:51 -0800393 log.info('bulk-flow-update', device_id=device.id,
394 flows=flows, groups=groups)
395
396 assert len(groups.items) == 0, "Cannot yet deal with groups"
397
398 for flow in flows.items:
399 in_port = get_in_port(flow)
400 assert in_port is not None
401
402 precedence = 255 - min(flow.priority / 256, 255)
403
404 if in_port == 2:
405 # Downstream rule
406 pass # TODO still ignores
407
408 elif in_port == 1:
409 # Upstream rule
Zsolt Haraszti313c4be2016-12-27 11:06:53 -0800410 req = PonPortObject()
Zsolt Haraszti80175202016-12-24 00:17:51 -0800411 req /= PortIngressRuleHeader(precedence=precedence)
412
413 for field in get_ofb_fields(flow):
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800414
Zsolt Haraszti80175202016-12-24 00:17:51 -0800415 if field.type == ETH_TYPE:
416 _type = field.eth_type
417 req /= PortIngressRuleClauseMatchLength02(
418 fieldcode=3,
419 operator=1,
420 match0=(_type >> 8) & 0xff,
421 match1=_type & 0xff)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800422
Zsolt Haraszti80175202016-12-24 00:17:51 -0800423 elif field.type == IP_PROTO:
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800424 _proto = field.ip_proto
425 pass # construct ip_proto based condition here
426
427 elif field.type == IN_PORT:
428 _port = field.port
429 pass # construct in_port based condition here
430
431 elif field.type == VLAN_VID:
432 _vlan_vid = field.vlan_vid
433 pass # construct VLAN ID based filter condition here
434
435 elif field.type == VLAN_PCP:
436 _vlan_pcp = field.vlan_pcp
437 pass # construct VLAN PCP based filter condition here
438
439 elif field.type == UDP_DST:
440 _udp_dst = field.udp_dst
441 pass # construct UDP SDT based filter here
442
443 else:
444 raise NotImplementedError('field.type={}'.format(
445 field.type))
Zsolt Haraszti80175202016-12-24 00:17:51 -0800446
447 for action in get_actions(flow):
448
449 if action.type == OUTPUT:
450 req /= PortIngressRuleResultForward()
451
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800452 elif action.type == POP_VLAN:
453 pass # construct vlan pop command here
454
Zsolt Haraszti80175202016-12-24 00:17:51 -0800455 elif action.type == PUSH_VLAN:
456 if action.push.ethertype != 0x8100:
457 log.error('unhandled-ether-type',
458 ethertype=action.push.ethertype)
459 req /= PortIngressRuleResultInsert(fieldcode=7)
460
461 elif action.type == SET_FIELD:
462 assert (action.set_field.field.oxm_class ==
463 ofp.OFPXMC_OPENFLOW_BASIC)
464 field = action.set_field.field.ofb_field
465 if field.type == VLAN_VID:
466 req /= PortIngressRuleResultSet(
467 fieldcode=7, value=field.vlan_vid & 0xfff)
468 else:
469 log.error('unsupported-action-set-field-type',
470 field_type=field.type)
471
472 else:
473 log.error('unsupported-action-type',
474 action_type=action.type)
475
476 req /= PortIngressRuleTerminator()
477 req /= AddPortIngressRule()
478
479 msg = (
480 Ether(dst=device.mac_address) /
481 Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) /
482 EOAMPayload(
483 body=CablelabsOUI() / DPoEOpcode_SetRequest() / req)
484 )
485
486 self.io_port.send(str(msg))
487
488 else:
489 raise Exception('Port should be 1 or 2 by our convention')
Zsolt Harasztied091602016-12-08 13:36:38 -0800490
491 def update_flows_incrementally(self, device, flow_changes, group_changes):
492 raise NotImplementedError()
493
494 def send_proxied_message(self, proxy_address, msg):
Nathan Knuth6e57f332016-12-22 15:49:20 -0800495 log.info('send-proxied-message', proxy_address=proxy_address)
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800496 # TODO build device_id -> mac_address cache
497 device = self.adapter_agent.get_device(proxy_address.device_id)
Nathan Knuth6e57f332016-12-22 15:49:20 -0800498 frame = Ether(dst='00:0c:e2:22:29:00') / \
499 Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) / \
500 Dot1Q(vlan=proxy_address.channel_id, prio=TIBIT_MGMT_PRIORITY) / \
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800501 msg
Nathan Knuth6e57f332016-12-22 15:49:20 -0800502
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800503 self.io_port.send(str(frame))
Zsolt Harasztied091602016-12-08 13:36:38 -0800504
505 def receive_proxied_message(self, proxy_address, msg):
506 raise NotImplementedError()
Zsolt Haraszti656ecc62016-12-28 15:08:23 -0800507
508 def receive_packet_out(self, logical_device_id, egress_port_no, msg):
509 log.info('packet-out', logical_device_id=logical_device_id,
510 egress_port_no=egress_port_no, msg_len=len(msg))