Expand field/action conversion scope of ofagent
Ofagent did not parse all fields back from protobuf to lexi,
hence ONOS was not able to confirm downloaded flows. This
made her unhappy.
Also, DHCP config info is added to ONOS netcfg.json.
Change-Id: I57ac5d3b4d14c8c52feb52e08bb420c15809238e
diff --git a/docker/Dockerfile.onos b/docker/Dockerfile.onos
index eab9368..878c602 100644
--- a/docker/Dockerfile.onos
+++ b/docker/Dockerfile.onos
@@ -24,4 +24,6 @@
rm $ONOS/apps/org.opencord.igmp/active &&\
rm $ONOS/apps/org.opencord.vtn/active
+RUN touch $ONOS/apps/org.onosproject.dhcp/active
+
COPY config/netcfg.json $KARAF_ROOT/../config/network-cfg.json
diff --git a/docker/config/netcfg.json b/docker/config/netcfg.json
index 265b15e..9e399e8 100644
--- a/docker/config/netcfg.json
+++ b/docker/config/netcfg.json
@@ -1,22 +1,40 @@
{
- "apps" : {
- "org.onosproject.aaa" : {
- "AAA" : {
- "radiusIp": "172.25.0.100",
- "radiusServerPort": "1812",
- "radiusSecret": "SECRET"
- }
- }
+ "apps": {
+ "org.onosproject.aaa": {
+ "AAA": {
+ "radiusIp": "172.25.0.100",
+ "radiusServerPort": "1812",
+ "radiusSecret": "SECRET"
+ }
},
- "devices" : {
- "of:0000000000000001" : {
- "basic" : {
- "driver" : "pmc-olt"
- },
- "accessDevice": {
- "uplink": "0",
- "vlan": "1000"
- }
- }
+ "org.onosproject.dhcp": {
+ "dhcp": {
+ "ip": "10.1.11.50",
+ "mac": "ca:fe:ca:fe:ca:fe",
+ "subnet": "255.255.252.0",
+ "broadcast": "10.1.11.255",
+ "router": "10.1.8.1",
+ "domain": "8.8.8.8",
+ "ttl": "63",
+ "lease": "300",
+ "renew": "150",
+ "rebind": "200",
+ "delay": "2",
+ "timeout": "150",
+ "startip": "10.1.11.51",
+ "endip": "10.1.11.100"
+ }
}
+ },
+ "devices": {
+ "of:0000000000000001": {
+ "basic": {
+ "driver": "pmc-olt"
+ },
+ "accessDevice": {
+ "uplink": "0",
+ "vlan": "1000"
+ }
+ }
+ }
}
diff --git a/ofagent/converter.py b/ofagent/converter.py
index 2b97055..2a221b7 100644
--- a/ofagent/converter.py
+++ b/ofagent/converter.py
@@ -43,7 +43,7 @@
def to_loxi(grpc_object):
cls = grpc_object.__class__
- converter = to_loxi_converters[cls]
+ converter = to_loxi_converters[cls.__name__]
return converter(grpc_object)
def to_grpc(loxi_object):
@@ -61,22 +61,60 @@
desc=ofp_port_to_loxi_port_desc(pb.desc)
)
+def make_loxi_field(oxm_field):
+ assert oxm_field['oxm_class'] == pb2.OFPXMC_OPENFLOW_BASIC
+ ofb_field = oxm_field['ofb_field']
+ field_type = ofb_field.get('type', 0)
+
+ if field_type == pb2.OFPXMT_OFB_ETH_TYPE:
+ return (
+ of13.oxm.eth_type(value=ofb_field['eth_type']))
+
+ elif field_type == pb2.OFPXMT_OFB_IN_PORT:
+ return (
+ of13.oxm.in_port(value=ofb_field['port']))
+
+ elif field_type == pb2.OFPXMT_OFB_IP_PROTO:
+ return (
+ of13.oxm.ip_proto(value=ofb_field['ip_proto']))
+
+ elif field_type == pb2.OFPXMT_OFB_VLAN_VID:
+ return (
+ of13.oxm.vlan_vid(value=ofb_field['vlan_vid']))
+
+ elif field_type == pb2.OFPXMT_OFB_VLAN_PCP:
+ return (
+ of13.oxm.vlan_pcp(value=ofb_field['vlan_pcp']))
+
+ elif field_type == pb2.OFPXMT_OFB_IPV4_SRC:
+ return (
+ of13.oxm.ipv4_src(value=ofb_field['ipv4_src']))
+
+ elif field_type == pb2.OFPXMT_OFB_IPV4_DST:
+ return (
+ of13.oxm.ipv4_dst(value=ofb_field['ipv4_dst']))
+
+ elif field_type == pb2.OFPXMT_OFB_UDP_SRC:
+ return (
+ of13.oxm.udp_src(value=ofb_field['udp_src']))
+
+ elif field_type == pb2.OFPXMT_OFB_UDP_DST:
+ return (
+ of13.oxm.udp_dst(value=ofb_field['udp_dst']))
+
+ elif field_type == pb2.OFPXMT_OFB_METADATA:
+ return (
+ of13.oxm.metadata(value=ofb_field['table_metadata']))
+
+ else:
+ 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 = []
for oxm_field in match.get('oxm_fields', []):
- assert oxm_field['oxm_class'] == pb2.OFPXMC_OPENFLOW_BASIC
- ofb_field = oxm_field['ofb_field']
- field_type = ofb_field.get('type', 0)
- if field_type == pb2.OFPXMT_OFB_ETH_TYPE:
- loxi_match_fields.append(
- of13.oxm.eth_type(value=ofb_field['eth_type']))
- elif field_type == pb2.OFPXMT_OFB_IN_PORT:
- loxi_match_fields.append(
- of13.oxm.in_port(value=ofb_field['port']))
- else:
- raise NotImplementedError(
- 'OXM match field for type %s' % field_type)
+ loxi_match_fields.append(make_loxi_field(oxm_field))
return of13.match_v3(oxm_list=loxi_match_fields)
def ofp_flow_stats_to_loxi_flow_stats(pb):
@@ -84,9 +122,26 @@
def make_loxi_action(a):
type = a.get('type', 0)
+
if type == pb2.OFPAT_OUTPUT:
- output = a['output']
- return of13.action.output(**output)
+ output_kws = a['output']
+ return of13.action.output(**output_kws)
+
+ elif type == pb2.OFPAT_POP_VLAN:
+ return of13.action.pop_vlan()
+
+ elif type == pb2.OFPAT_PUSH_VLAN:
+ push_vlan_kws = a['push']
+ return of13.action.push_vlan(**push_vlan_kws)
+
+ elif type == pb2.OFPAT_SET_FIELD:
+ loxi_field = make_loxi_field(a['set_field']['field'])
+ return of13.action.set_field(loxi_field)
+
+ elif type == pb2.OFPAT_GROUP:
+ group_kws = a['group']
+ return of13.action.group(**group_kws)
+
else:
raise NotImplementedError(
'Action decoder for action OFPAT_* %d' % type)
@@ -97,6 +152,10 @@
return of13.instruction.apply_actions(
actions=[make_loxi_action(a)
for a in inst['actions']['actions']])
+ elif type == pb2.OFPIT_GOTO_TABLE:
+ return of13.instruction.goto_table(
+ table_id=inst['goto_table']['table_id'])
+
else:
raise NotImplementedError('Instruction type %d' % type)
@@ -136,12 +195,12 @@
to_loxi_converters = {
- pb2.ofp_port: ofp_port_to_loxi_port_desc,
- pb2.ofp_port_status: ofp_port_status_to_loxi_port_status,
- pb2.ofp_flow_stats: ofp_flow_stats_to_loxi_flow_stats,
- pb2.ofp_packet_in: ofp_packet_in_to_loxi_packet_in,
- pb2.ofp_group_entry: ofp_group_entry_to_loxi_group_entry,
- pb2.ofp_bucket_counter: ofp_bucket_counter_to_loxy_bucket_counter
+ 'ofp_port': ofp_port_to_loxi_port_desc,
+ 'ofp_port_status': ofp_port_status_to_loxi_port_status,
+ 'ofp_flow_stats': ofp_flow_stats_to_loxi_flow_stats,
+ 'ofp_packet_in': ofp_packet_in_to_loxi_packet_in,
+ 'ofp_group_entry': ofp_group_entry_to_loxi_group_entry,
+ 'ofp_bucket_counter': ofp_bucket_counter_to_loxy_bucket_counter
}
@@ -248,6 +307,14 @@
udp_dst=lo.value))
+def loxi_oxm_udp_src_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_UDP_SRC,
+ udp_src=lo.value))
+
+
def loxi_oxm_metadata_to_ofp_oxm(lo):
return pb2.ofp_oxm_field(
oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
@@ -319,6 +386,7 @@
of13.oxm.vlan_vid: loxi_oxm_vlan_vid_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,
of13.oxm.udp_dst: loxi_oxm_udp_dst_to_ofp_oxm,
of13.oxm.metadata: loxi_oxm_metadata_to_ofp_oxm,
diff --git a/ofagent/of_protocol_handler.py b/ofagent/of_protocol_handler.py
index 87feb37..d0b71e3 100644
--- a/ofagent/of_protocol_handler.py
+++ b/ofagent/of_protocol_handler.py
@@ -168,9 +168,12 @@
@inlineCallbacks
def handle_flow_stats_request(self, req):
- flow_stats = yield self.rpc.list_flows(self.device_id)
- self.cxn.send(ofp.message.flow_stats_reply(
- xid=req.xid, entries=[to_loxi(f) for f in flow_stats]))
+ try:
+ flow_stats = yield self.rpc.list_flows(self.device_id)
+ self.cxn.send(ofp.message.flow_stats_reply(
+ xid=req.xid, entries=[to_loxi(f) for f in flow_stats]))
+ except Exception, e:
+ log.exception('failed-flow-stats-request', req=req)
@inlineCallbacks
def handle_group_stats_request(self, req):
diff --git a/ponsim/ponsim.py b/ponsim/ponsim.py
index 3086ff5..f041171 100644
--- a/ponsim/ponsim.py
+++ b/ponsim/ponsim.py
@@ -101,6 +101,10 @@
if f.haslayer(IP):
return f.getlayer(IP).dst
+ def get_udp_src(f):
+ if f.haslayer(UDP):
+ return f.getlayer(UDP).sport
+
def get_udp_dst(f):
if f.haslayer(UDP):
return f.getlayer(UDP).dport
@@ -137,6 +141,10 @@
if ipv4int2str(field.ipv4_dst) != get_ipv4_dst(frame):
return False
+ elif field.type == UDP_SRC:
+ if field.udp_src != get_udp_src(frame):
+ return False
+
elif field.type == UDP_DST:
if field.udp_dst != get_udp_dst(frame):
return False
diff --git a/tests/utests/ofagent/test_converter.py b/tests/utests/ofagent/test_converter.py
new file mode 100644
index 0000000..e84108a
--- /dev/null
+++ b/tests/utests/ofagent/test_converter.py
@@ -0,0 +1,206 @@
+from unittest import TestCase, main
+
+from loxi import of13
+from voltha.protos import third_party
+from ofagent.converter import to_loxi
+from voltha.core.flow_decomposer import *
+
+_ = third_party
+
+
+class TestConverter(TestCase):
+
+ def gen_pb_flow_stats(self):
+
+ # device level flows
+
+ flow_stats = [
+ mk_flow_stat(
+ priority=2000,
+ match_fields=[in_port(2), vlan_vid(4096 + 4000), vlan_pcp(0)],
+ actions=[pop_vlan(), output(1)]
+ ),
+ mk_flow_stat(
+ priority=2000,
+ match_fields=[in_port(1), eth_type(0x888e)],
+ actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 4000)),
+ output(2)]
+ ),
+ mk_flow_stat(
+ priority=1000,
+ match_fields=[in_port(1), eth_type(0x800), ip_proto(2)],
+ actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 4000)),
+ output(2)]
+ ),
+ mk_flow_stat(
+ priority=1000,
+ match_fields=[in_port(1), eth_type(0x800), ip_proto(17),
+ udp_src(68), udp_dst(67)],
+ actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 4000)),
+ output(2)]
+ ),
+ mk_flow_stat(
+ priority=1000,
+ match_fields=[in_port(2), vlan_vid(4096 + 140)],
+ actions=[pop_vlan(), output(1)]
+ ),
+ mk_flow_stat(
+ priority=500,
+ match_fields=[in_port(2), vlan_vid(4096 + 1000), metadata(128)],
+ actions=[pop_vlan(), output(1)]
+ ),
+ mk_flow_stat(
+ priority=500,
+ match_fields=[in_port(1), vlan_vid(4096 + 128)],
+ actions=[
+ push_vlan(0x8100), set_field(vlan_vid(4096 + 1000)),
+ output(2)]
+ ),
+ mk_flow_stat(
+ priority=500,
+ match_fields=[in_port(1), vlan_vid(4096 + 129)],
+ actions=[
+ push_vlan(0x8100), set_field(vlan_vid(4096 + 1000)),
+ output(2)]
+ ),
+ ] + [
+ mk_flow_stat(
+ priority=500,
+ match_fields=[in_port(2), vlan_vid(4096 + 0)],
+ actions=[
+ set_field(vlan_vid(4096 + 128)), output(1)]
+ ),
+ mk_flow_stat(
+ priority=1000,
+ match_fields=[
+ in_port(1), eth_type(0x800), ipv4_dst(0xe4010102)],
+ actions=[output(2)]
+ ),
+ mk_flow_stat(
+ priority=1000,
+ match_fields=[
+ in_port(1), eth_type(0x800), ipv4_dst(0xe4010104)],
+ actions=[output(2)]
+ ),
+ mk_flow_stat(
+ priority=500,
+ match_fields=[in_port(1), vlan_vid(4096 + 128)],
+ actions=[set_field(vlan_vid(4096 + 0)), output(2)]
+ ),
+ mk_flow_stat(
+ priority=500,
+ match_fields=[in_port(2), vlan_vid(0)],
+ actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 128)),
+ output(1)]
+ )
+
+ ]
+
+ # logical device level flows
+
+ # Various controller-bound rules
+ for _in_port in (1, 2):
+ flow_stats.append(mk_flow_stat(
+ priority=2000,
+ match_fields=[in_port(_in_port), eth_type(0x888e)],
+ actions=[
+ push_vlan(0x8100),
+ set_field(vlan_vid(4096 + 4000)),
+ output(ofp.OFPP_CONTROLLER)
+ ]
+ ))
+ flow_stats.append(mk_flow_stat(
+ priority=1000,
+ match_fields=[eth_type(0x800), ip_proto(2)],
+ actions=[output(ofp.OFPP_CONTROLLER)]
+ ))
+ flow_stats.append(mk_flow_stat(
+ priority=1000,
+ match_fields=[eth_type(0x800), ip_proto(17),
+ udp_src(68), udp_dst(67)],
+ actions=[output(ofp.OFPP_CONTROLLER)]
+ ))
+
+ # Multicast channels
+ mcast_setup = (
+ (1, 0xe4010101, ()),
+ (2, 0xe4010102, (1,)),
+ (3, 0xe4010103, (2,)),
+ (4, 0xe4010104, (1, 2)),
+ )
+ for group_id, mcast_addr, ports in mcast_setup:
+ # self.lda.update_group_table(mk_multicast_group_mod(
+ # group_id=group_id,
+ # buckets=[
+ # ofp.ofp_bucket(actions=[
+ # pop_vlan(),
+ # output(port)
+ # ]) for port in ports
+ # ]))
+ flow_stats.append(mk_flow_stat(
+ priority=1000,
+ match_fields=[
+ in_port(0),
+ eth_type(0x800),
+ vlan_vid(4096 + 140),
+ ipv4_dst(mcast_addr)
+ ],
+ actions=[
+ group(group_id)
+ ]
+ ))
+
+ # Unicast channels for each subscriber
+ # Downstream flow 1 for both
+ flow_stats.append(mk_flow_stat(
+ priority=500,
+ match_fields=[
+ in_port(0),
+ vlan_vid(4096 + 1000),
+ metadata(128)
+ ],
+ actions=[pop_vlan()],
+ next_table_id=1
+ ))
+ # Downstream flow 2 and upsrteam flow 1 for each ONU
+ for port, c_vid in ((1, 101), (2, 102)):
+ flow_stats.append(mk_flow_stat(
+ priority=500,
+ match_fields=[in_port(0), vlan_vid(4096 + c_vid)],
+ actions=[set_field(vlan_vid(4096 + 0)), output(port)]
+ ))
+ # for the 0-tagged case
+ flow_stats.append(mk_flow_stat(
+ priority=500,
+ match_fields=[in_port(port), vlan_vid(4096 + 0)],
+ actions=[set_field(vlan_vid(4096 + c_vid))],
+ next_table_id=1
+ ))
+ # for the untagged case
+ flow_stats.append(mk_flow_stat(
+ priority=500,
+ match_fields=[in_port(port), vlan_vid(0)],
+ actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + c_vid))],
+ next_table_id=1
+ ))
+ # Upstream flow 2 for s-tag
+ flow_stats.append(mk_flow_stat(
+ priority=500,
+ match_fields=[in_port(port), vlan_vid(4096 + c_vid)],
+ actions=[
+ push_vlan(0x8100),
+ set_field(vlan_vid(4096 + 1000)),
+ output(0)
+ ]
+ ))
+
+ return flow_stats
+
+ def test_flow_spec_pb_to_loxi_conversion(self):
+ flow_stats = self.gen_pb_flow_stats()
+ for flow_stat in flow_stats:
+ loxi_flow_stats = to_loxi(flow_stat)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/utests/voltha/core/test_logical_device_agent.py b/tests/utests/voltha/core/test_logical_device_agent.py
index 7b2cbce..c9879ca 100644
--- a/tests/utests/voltha/core/test_logical_device_agent.py
+++ b/tests/utests/voltha/core/test_logical_device_agent.py
@@ -593,8 +593,8 @@
))
self.lda._flow_table_updated(self.flows)
self.assertEqual(len(self.device_flows['olt'].items), 2)
- self.assertEqual(len(self.device_flows['onu1'].items), 1)
- self.assertEqual(len(self.device_flows['onu2'].items), 1)
+ self.assertEqual(len(self.device_flows['onu1'].items), 3)
+ self.assertEqual(len(self.device_flows['onu2'].items), 3)
self.assertEqual(len(self.device_groups['olt'].items), 0)
self.assertEqual(len(self.device_groups['onu1'].items), 0)
self.assertEqual(len(self.device_groups['onu2'].items), 0)
@@ -630,7 +630,8 @@
))
self.lda.update_flow_table(mk_simple_flow_mod(
priority=1000,
- match_fields=[eth_type(0x800), ip_proto(17), udp_dst(67)],
+ match_fields=[eth_type(0x800), ip_proto(17),
+ udp_src(68), udp_dst(67)],
actions=[output(ofp.OFPP_CONTROLLER)]
))
@@ -669,7 +670,8 @@
priority=500,
match_fields=[
in_port(0),
- vlan_vid(4096 + 1000)
+ vlan_vid(4096 + 1000),
+ metadata(128)
],
actions=[pop_vlan()],
next_table_id=1
@@ -741,7 +743,7 @@
self.assertFlowsEqual(self.device_flows['olt'].items[3], mk_flow_stat(
priority=1000,
match_fields=[in_port(1), eth_type(0x800), ip_proto(17),
- udp_dst(67)],
+ udp_src(68), udp_dst(67)],
actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 4000)),
output(0)]
))
@@ -752,7 +754,7 @@
))
self.assertFlowsEqual(self.device_flows['olt'].items[5], mk_flow_stat(
priority=500,
- match_fields=[in_port(0), vlan_vid(4096 + 1000)],
+ match_fields=[in_port(0), vlan_vid(4096 + 1000), metadata(128)],
actions=[pop_vlan(), output(1)]
))
self.assertFlowsEqual(self.device_flows['olt'].items[6], mk_flow_stat(
diff --git a/voltha/adapters/simulated_olt/simulated_olt.py b/voltha/adapters/simulated_olt/simulated_olt.py
index ec52c3a..251e849 100644
--- a/voltha/adapters/simulated_olt/simulated_olt.py
+++ b/voltha/adapters/simulated_olt/simulated_olt.py
@@ -455,9 +455,13 @@
_vlan_pcp = field.vlan_pcp
pass # construct VLAN PCP based filter condition here
+ elif field.type == UDP_SRC:
+ _udp_src = field.udp_src
+ pass # construct UDP SRC based filter here
+
elif field.type == UDP_DST:
_udp_dst = field.udp_dst
- pass # construct UDP SDT based filter here
+ pass # construct UDP DST based filter here
# TODO
else:
diff --git a/voltha/adapters/simulated_onu/simulated_onu.py b/voltha/adapters/simulated_onu/simulated_onu.py
index afae516..2b0ea9f 100644
--- a/voltha/adapters/simulated_onu/simulated_onu.py
+++ b/voltha/adapters/simulated_onu/simulated_onu.py
@@ -283,9 +283,13 @@
_ipv4_dst = field.ipv4_dst
pass # construct IPv4 DST address based condition
+ elif field.type == UDP_SRC:
+ _udp_src = field.udp_src
+ pass # construct UDP SRC based filter here
+
elif field.type == UDP_DST:
_udp_dst = field.udp_dst
- pass # construct UDP SDT based filter here
+ pass # construct UDP DST based filter here
# TODO
else:
diff --git a/voltha/adapters/tibit_olt/tibit_olt.py b/voltha/adapters/tibit_olt/tibit_olt.py
index 615394b..850a0c9 100644
--- a/voltha/adapters/tibit_olt/tibit_olt.py
+++ b/voltha/adapters/tibit_olt/tibit_olt.py
@@ -450,10 +450,15 @@
log.info('#### field.type == VLAN_PCP ####')
pass # construct VLAN PCP based filter condition here
+ elif field.type == UDP_SRC:
+ _udp_src = field.udp_src
+ log.info('#### field.type == UDP_SRC ####')
+ pass # construct UDP SRC based filter here
+
elif field.type == UDP_DST:
_udp_dst = field.udp_dst
log.info('#### field.type == UDP_DST ####')
- pass # construct UDP SDT based filter here
+ pass # construct UDP DST based filter here
elif field.type == METADATA:
pass # safe to ignore
@@ -537,10 +542,15 @@
log.info('#### field.type == VLAN_PCP ####')
pass # construct VLAN PCP based filter condition here
+ elif field.type == UDP_SRC:
+ _udp_src = field.udp_src
+ log.info('#### field.type == UDP_SRC ####')
+ pass # construct UDP SRC based filter here
+
elif field.type == UDP_DST:
_udp_dst = field.udp_dst
log.info('#### field.type == UDP_DST ####')
- pass # construct UDP SDT based filter here
+ pass # construct UDP DST based filter here
else:
raise NotImplementedError('field.type={}'.format(
diff --git a/voltha/adapters/tibit_onu/tibit_onu.py b/voltha/adapters/tibit_onu/tibit_onu.py
index bb87902..7180553 100644
--- a/voltha/adapters/tibit_onu/tibit_onu.py
+++ b/voltha/adapters/tibit_onu/tibit_onu.py
@@ -296,9 +296,13 @@
_ipv4_dst = field.ipv4_dst
pass # construct IPv4 DST address based condition
+ elif field.type == UDP_SRC:
+ _udp_src = field.udp_src
+ pass # construct UDP SRC based filter here
+
elif field.type == UDP_DST:
_udp_dst = field.udp_dst
- pass # construct UDP SDT based filter here
+ pass # construct UDP DST based filter here
# TODO
else:
diff --git a/voltha/core/flow_decomposer.py b/voltha/core/flow_decomposer.py
index 6c72f07..2d6aafb 100644
--- a/voltha/core/flow_decomposer.py
+++ b/voltha/core/flow_decomposer.py
@@ -23,8 +23,10 @@
import structlog
+from voltha.protos import third_party
from voltha.protos import openflow_13_pb2 as ofp
+_ = third_party
log = structlog.get_logger()
diff --git a/voltha/protos/third_party/__init__.py b/voltha/protos/third_party/__init__.py
index faf6704..3b654af 100644
--- a/voltha/protos/third_party/__init__.py
+++ b/voltha/protos/third_party/__init__.py
@@ -46,5 +46,8 @@
sys.meta_path.append(GoogleApiImporter())
-from google.api import http_pb2, annotations_pb2
-_ = http_pb2, annotations_pb2
+try:
+ from google.api import http_pb2, annotations_pb2
+ _ = http_pb2, annotations_pb2
+except AssertionError:
+ pass