Flow decomposer support for Tech Profile Reference in metadata instead of using Flow Table ID as reference in Table 1.
Also in this patch:
- Update flow count field of meter stats
- ONU root field was True and because of this flow decomposer was not working properly - it is fixed (now onu root field is false) - related to VOL-1354
- Meter & write metadata support is added to vcli
- No-action (drop) flow support is added.
- Removed broken wildcard inport support and in-band control support
- Meter functions (meter stats reply, meter modify etc.) are fixed
- Metadata information passed on to the OLT and ONU Adapters.
- Meter Reference in all Flow Tables passed on to the OLT and ONU Adapters.
- Fixed unit tests and added more unit tests
- Fixed ponsim (partially) to deal with changes to flow decomposer
Change-Id: Id4b16fc05a6740a3f521b2cc4f6fdbff88da4fa5
diff --git a/ofagent/converter.py b/ofagent/converter.py
index fb7aae5..7156d60 100644
--- a/ofagent/converter.py
+++ b/ofagent/converter.py
@@ -31,6 +31,7 @@
FieldDescriptor.TYPE_STRING: str
})
+
def pb2dict(pb):
"""
Convert protobuf to a dict of values good for instantiating
@@ -41,33 +42,53 @@
"""
return protobuf_to_dict(pb, type_callable_map)
+
def to_loxi(grpc_object):
cls = grpc_object.__class__
converter = to_loxi_converters[cls.__name__]
return converter(grpc_object)
+
def to_grpc(loxi_object):
cls = loxi_object.__class__
converter = to_grpc_converters[cls]
return converter(loxi_object)
+
def ofp_port_to_loxi_port_desc(pb):
kw = pb2dict(pb)
return of13.common.port_desc(**kw)
+
def ofp_port_status_to_loxi_port_status(pb):
return of13.message.port_status(
reason=pb.reason,
desc=ofp_port_to_loxi_port_desc(pb.desc)
)
+
def ofp_port_stats_to_loxi_port_stats(pb):
kw = pb2dict(pb)
return of13.port_stats_entry(**kw)
+
def ofp_meter_stats_to_loxi_meter_stats(pb):
- kw = pb2dict(pb)
- return of13.meter_stats(**kw)
+ return of13.meter_stats(
+ meter_id=pb.meter_id,
+ flow_count=pb.flow_count,
+ packet_in_count=pb.packet_in_count,
+ byte_in_count=pb.byte_in_count,
+ duration_sec=pb.duration_sec,
+ duration_nsec=pb.duration_nsec,
+ band_stats=[to_loxi(band_stat) for band_stat in pb.band_stats])
+
+
+def ofp_meter_band_stats_to_loxi_meter_stats(pb):
+ return of13.meter_band_stats(
+ packet_band_count=pb.packet_band_count,
+ byte_band_count=pb.byte_band_count
+ )
+
def make_loxi_field(oxm_field):
assert oxm_field['oxm_class'] == pb2.OFPXMC_OPENFLOW_BASIC
@@ -87,6 +108,9 @@
of13.oxm.ip_proto(value=ofb_field['ip_proto']))
elif field_type == pb2.OFPXMT_OFB_VLAN_VID:
+ if ofb_field.get('has_mask', 0):
+ return of13.oxm.vlan_vid_masked(value=ofb_field['vlan_vid'],
+ value_mask=ofb_field['vlan_vid_mask'])
return (
of13.oxm.vlan_vid(value=ofb_field['vlan_vid']))
@@ -118,6 +142,7 @@
raise NotImplementedError(
'OXM match field for type %s' % field_type)
+
def make_loxi_match(match):
assert match.get('type', pb2.OFPMT_STANDARD) == pb2.OFPMT_OXM
loxi_match_fields = []
@@ -174,12 +199,20 @@
return of13.instruction.write_actions(
actions=[make_loxi_action(a)
for a in inst['actions']['actions']])
+ elif type == pb2.OFPIT_WRITE_METADATA:
+ return of13.instruction.write_metadata(
+ metadata=inst['write_metadata']['metadata'])
+ elif type == pb2.OFPIT_METER:
+ return of13.instruction.meter(
+ meter_id=inst['meter']['meter_id'])
else:
raise NotImplementedError('Instruction type %d' % type)
kw['match'] = make_loxi_match(kw['match'])
- kw['instructions'] = [make_loxi_instruction(i) for i in kw['instructions']]
+ # if the flow action is drop, then the instruction is not found in the dict
+ if 'instructions' in kw:
+ kw['instructions'] = [make_loxi_instruction(i) for i in kw['instructions']]
del kw['id']
return of13.flow_stats_entry(**kw)
@@ -195,6 +228,7 @@
)
return packet_in
+
def ofp_group_desc_to_loxi_group_desc(pb):
return of13.group_desc_stats_entry(
group_type=pb.type,
@@ -239,7 +273,8 @@
'ofp_bucket': ofp_bucket_to_loxi_bucket,
'ofp_action': make_loxi_action,
'ofp_port_stats': ofp_port_stats_to_loxi_port_stats,
- 'ofp_meter_stats': ofp_meter_stats_to_loxi_meter_stats
+ 'ofp_meter_stats': ofp_meter_stats_to_loxi_meter_stats,
+ 'ofp_meter_band_stats': ofp_meter_band_stats_to_loxi_meter_stats
}
@@ -259,6 +294,7 @@
match=to_grpc(lo.match),
instructions=[to_grpc(i) for i in lo.instructions])
+
def loxi_meter_mod_to_ofp_meter_mod(lo):
return pb2.ofp_meter_mod(
command=lo.command,
@@ -368,6 +404,16 @@
vlan_vid=lo.value))
+def loxi_oxm_vlan_vid_masked_to_ofp_oxm(lo):
+ return pb2.ofp_oxm_field(
+ oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
+ ofb_field=pb2.ofp_oxm_ofb_field(
+ type=pb2.OFPXMT_OFB_VLAN_VID,
+ has_mask=True,
+ vlan_vid=lo.value,
+ vlan_vid_mask=lo.value_mask))
+
+
def loxi_oxm_vlan_pcp_to_ofp_oxm(lo):
return pb2.ofp_oxm_field(
oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
@@ -425,6 +471,20 @@
goto_table=pb2.ofp_instruction_goto_table(table_id=lo.table_id))
+def loxi_write_metadata_to_ofp_instruction(lo):
+ return pb2.ofp_instruction(
+ type=pb2.OFPIT_WRITE_METADATA,
+ write_metadata=pb2.ofp_instruction_write_metadata(
+ metadata=lo.metadata,
+ metadata_mask=lo.metadata_mask))
+
+
+def loxi_meter_to_ofp_instruction(lo):
+ return pb2.ofp_instruction(
+ type=pb2.OFPIT_METER,
+ meter=pb2.ofp_instruction_meter(meter_id=lo.meter_id))
+
+
def loxi_output_action_to_ofp_action(lo):
return pb2.ofp_action(
type=pb2.OFPAT_OUTPUT,
@@ -486,6 +546,7 @@
of13.oxm.in_port: loxi_oxm_in_port_to_ofp_oxm,
of13.oxm.ip_proto: loxi_oxm_ip_proto_to_ofp_oxm,
of13.oxm.vlan_vid: loxi_oxm_vlan_vid_to_ofp_oxm,
+ of13.oxm.vlan_vid_masked: loxi_oxm_vlan_vid_masked_to_ofp_oxm,
of13.oxm.vlan_pcp: loxi_oxm_vlan_pcp_to_ofp_oxm,
of13.oxm.ipv4_dst: loxi_oxm_ipv4_dst_to_ofp_oxm,
of13.oxm.udp_src: loxi_oxm_udp_src_to_ofp_oxm,
@@ -496,6 +557,8 @@
of13.instruction.clear_actions: loxi_clear_actions_to_ofp_instruction,
of13.instruction.write_actions: loxi_write_actions_to_ofp_instruction,
of13.instruction.goto_table: loxi_goto_table_to_ofp_instruction,
+ of13.instruction.write_metadata: loxi_write_metadata_to_ofp_instruction,
+ of13.instruction.meter: loxi_meter_to_ofp_instruction,
of13.action.output: loxi_output_action_to_ofp_action,
of13.action.group: loxi_group_action_to_ofp_action,
diff --git a/ofagent/grpc_client.py b/ofagent/grpc_client.py
index 16be6f0..155f18d 100644
--- a/ofagent/grpc_client.py
+++ b/ofagent/grpc_client.py
@@ -210,7 +210,7 @@
meter_mod=meter_mod
)
res = yield threads.deferToThread(
- self.local_stub.UpdateLogicalDeviceMeterTable, req)
+ self.local_stub.UpdateLogicalDeviceMeterTable, req, timeout=self.grpc_timeout)
returnValue(res)
@inlineCallbacks
@@ -238,6 +238,13 @@
returnValue(res.items)
@inlineCallbacks
+ def list_meters(self, device_id):
+ req = ID(id=device_id)
+ res = yield threads.deferToThread(
+ self.local_stub.ListLogicalDeviceMeters, req, timeout=self.grpc_timeout)
+ returnValue(res.items)
+
+ @inlineCallbacks
def list_ports(self, device_id):
req = ID(id=device_id)
res = yield threads.deferToThread(
@@ -262,10 +269,3 @@
res = yield threads.deferToThread(
self.local_stub.Subscribe, subscriber, timeout=self.grpc_timeout)
returnValue(res)
-
- @inlineCallbacks
- def get_meter_stats(self, device_id):
- req = ID(id=device_id)
- res = yield threads.deferToThread(
- self.local_stub.GetMeterStatsOfLogicalDevice, req)
- returnValue(res.items)
diff --git a/ofagent/of_protocol_handler.py b/ofagent/of_protocol_handler.py
index 01f896b..813c8a8 100644
--- a/ofagent/of_protocol_handler.py
+++ b/ofagent/of_protocol_handler.py
@@ -132,7 +132,6 @@
elif self.role == ofp.OFPCR_ROLE_SLAVE:
self.cxn.send(ofp.message.bad_request_error_msg(code=ofp.OFPBRC_IS_SLAVE))
-
def handle_meter_mod_request(self, req):
if self.role == ofp.OFPCR_ROLE_MASTER or self.role == ofp.OFPCR_ROLE_EQUAL:
try:
@@ -148,10 +147,9 @@
@inlineCallbacks
def handle_meter_stats_request(self, req):
try:
- meter_stats = yield self.rpc.get_meter_stats(self.device_id)
- meter_stats = [to_loxi(m) for m in meter_stats]
- of_message = ofp.message.meter_stats_reply(xid=req.xid, entries=meter_stats)
- self.cxn.send(of_message)
+ meters = yield self.rpc.list_meters(self.device_id)
+ self.cxn.send(ofp.message.meter_stats_reply(
+ xid=req.xid, entries=[to_loxi(m.stats) for m in meters]))
except Exception, e:
log.exception("failed-meter-stats-request", req=req, e=e)