Update OMCI support for Mcast Operation Profile and Subscriber Config Info MEs
Add support for adding rows to Multicst Operations Profile access
control list tables and Multicast Subscriber Config Info service
package and preview tables.
Create and set attributes of Multicst Operations Profilie and
Multicast Subscriber Config Info MEs from BRCM ONU adapter.
Change-Id: I33a2527bcb85d526bde8ae363e4d851f271a81a7
diff --git a/voltha/adapters/broadcom_onu/broadcom_onu.py b/voltha/adapters/broadcom_onu/broadcom_onu.py
index f81859c..933e3c7 100644
--- a/voltha/adapters/broadcom_onu/broadcom_onu.py
+++ b/voltha/adapters/broadcom_onu/broadcom_onu.py
@@ -168,7 +168,7 @@
# populate device info
device.root = True
device.vendor = 'Broadcom'
- device.model ='n/a'
+ device.model = 'n/a'
device.hardware_version = 'to be filled'
device.firmware_version = 'to be filled'
device.software_version = 'to be filled'
@@ -355,7 +355,6 @@
except Exception as e:
log.exception('failed-to-install-flow', e=e, flow=flow)
-
def get_tx_id(self):
self.tx_id += 1
return self.tx_id
@@ -392,7 +391,9 @@
)
self.send_omci_message(frame)
- def send_create_gal_ethernet_profile(self, entity_id, max_gem_payload_size):
+ def send_create_gal_ethernet_profile(self,
+ entity_id,
+ max_gem_payload_size):
frame = OmciFrame(
transaction_id=self.get_tx_id(),
message_type=OmciCreate.message_id,
@@ -406,7 +407,9 @@
)
self.send_omci_message(frame)
- def send_set_tcont(self, entity_id, alloc_id):
+ def send_set_tcont(self,
+ entity_id,
+ alloc_id):
data = dict(
alloc_id=alloc_id
)
@@ -415,16 +418,17 @@
message_type=OmciSet.message_id,
omci_message=OmciSet(
entity_class=Tcont.class_id,
- entity_id = entity_id,
+ entity_id=entity_id,
attributes_mask=Tcont.mask_for(*data.keys()),
data=data
)
)
self.send_omci_message(frame)
- def send_create_8021p_mapper_service_profile(self, entity_id):
+ def send_create_8021p_mapper_service_profile(self,
+ entity_id):
frame = OmciFrame(
- transaction_id = self.get_tx_id(),
+ transaction_id=self.get_tx_id(),
message_type=OmciCreate.message_id,
omci_message=OmciCreate(
entity_class=Ieee8021pMapperServiceProfile.class_id,
@@ -437,9 +441,10 @@
)
self.send_omci_message(frame)
- def send_create_mac_bridge_service_profile(self, entity_id):
+ def send_create_mac_bridge_service_profile(self,
+ entity_id):
frame = OmciFrame(
- transaction_id = self.get_tx_id(),
+ transaction_id=self.get_tx_id(),
message_type=OmciCreate.message_id,
omci_message=OmciCreate(
entity_class=MacBridgeServiceProfile.class_id,
@@ -457,9 +462,21 @@
)
self.send_omci_message(frame)
- def send_create_gem_port_network_ctp(self, entity_id, port_id, tcont_id):
+ def send_create_gem_port_network_ctp(self,
+ entity_id,
+ port_id,
+ tcont_id,
+ direction,
+ tm):
+ _directions = {"upstream": 1, "downstream": 2, "bi-directional": 3}
+ if _directions.has_key(direction):
+ _direction = _directions[direction]
+ else:
+ self.log.error('invalid-gem-port-direction', direction=direction)
+ raise ValueError('Invalid GEM port direction: {_dir}'.format(_dir=direction))
+
frame = OmciFrame(
- transaction_id = self.get_tx_id(),
+ transaction_id=self.get_tx_id(),
message_type=OmciCreate.message_id,
omci_message=OmciCreate(
entity_class=GemPortNetworkCtp.class_id,
@@ -467,16 +484,18 @@
data=dict(
port_id=port_id,
tcont_pointer=tcont_id,
- direction=3,
- traffic_management_pointer_upstream=0x100
+ direction=_direction,
+ traffic_management_pointer_upstream=tm
)
)
)
self.send_omci_message(frame)
- def send_create_multicast_gem_interworking_tp(self, entity_id, gem_port_net_ctp_id):
+ def send_create_multicast_gem_interworking_tp(self,
+ entity_id,
+ gem_port_net_ctp_id):
frame = OmciFrame(
- transaction_id = self.get_tx_id(),
+ transaction_id=self.get_tx_id(),
message_type=OmciCreate.message_id,
omci_message=OmciCreate(
entity_class=MulticastGemInterworkingTp.class_id,
@@ -484,15 +503,18 @@
data=dict(
gem_port_network_ctp_pointer=gem_port_net_ctp_id,
interworking_option=0,
- service_profile_pointer=0x1,
+ service_profile_pointer=0x1
)
)
)
self.send_omci_message(frame)
- def send_create_gem_inteworking_tp(self, entity_id, gem_port_net_ctp_id, service_profile_id):
+ def send_create_gem_inteworking_tp(self,
+ entity_id,
+ gem_port_net_ctp_id,
+ service_profile_id):
frame = OmciFrame(
- transaction_id = self.get_tx_id(),
+ transaction_id=self.get_tx_id(),
message_type=OmciCreate.message_id,
omci_message=OmciCreate(
entity_class=GemInterworkingTp.class_id,
@@ -508,12 +530,14 @@
)
self.send_omci_message(frame)
- def send_set_8021p_mapper_service_profile(self, entity_id, interwork_tp_id):
+ def send_set_8021p_mapper_service_profile(self,
+ entity_id,
+ interwork_tp_id):
data = dict(
interwork_tp_pointer_for_p_bit_priority_0 = interwork_tp_id
)
frame = OmciFrame(
- transaction_id = self.get_tx_id(),
+ transaction_id=self.get_tx_id(),
message_type=OmciSet.message_id,
omci_message=OmciSet(
entity_class=Ieee8021pMapperServiceProfile.class_id,
@@ -541,15 +565,17 @@
bridge_id_pointer = bridge_id,
port_num=port_id,
tp_type=tp_type,
- tp_pointer = tp_id
+ tp_pointer=tp_id
)
)
)
self.send_omci_message(frame)
- def send_create_vlan_tagging_filter_data(self, entity_id, vlan_id):
+ def send_create_vlan_tagging_filter_data(self,
+ entity_id,
+ vlan_id):
frame = OmciFrame(
- transaction_id = self.get_tx_id(),
+ transaction_id=self.get_tx_id(),
message_type=OmciCreate.message_id,
omci_message=OmciCreate(
entity_class=VlanTaggingFilterData.class_id,
@@ -568,7 +594,7 @@
assoc_type,
assoc_me):
frame = OmciFrame(
- transaction_id = self.get_tx_id(),
+ transaction_id=self.get_tx_id(),
message_type=OmciCreate.message_id,
omci_message=OmciCreate(
entity_class=
@@ -582,20 +608,23 @@
)
self.send_omci_message(frame)
- def send_set_extended_vlan_tagging_operation_tpid_configuration_data(self, entity_id, input_tpid, output_tpid):
+ def send_set_extended_vlan_tagging_operation_tpid_configuration_data(self,
+ entity_id,
+ input_tpid,
+ output_tpid):
data = dict(
- input_tpid = input_tpid,
- output_tpid = output_tpid,
+ input_tpid=input_tpid,
+ output_tpid=output_tpid,
downstream_mode=0, # inverse of upstream
)
frame = OmciFrame(
- transaction_id = self.get_tx_id(),
+ transaction_id=self.get_tx_id(),
message_type=OmciSet.message_id,
omci_message=OmciSet(
- entity_class=\
+ entity_class=
ExtendedVlanTaggingOperationConfigurationData.class_id,
entity_id=entity_id,
- attributes_mask= \
+ attributes_mask=
ExtendedVlanTaggingOperationConfigurationData.mask_for(
*data.keys()),
data=data
@@ -608,7 +637,7 @@
filter_inner_vid,
treatment_inner_vid):
data = dict(
- received_frame_vlan_tagging_operation_table=\
+ received_frame_vlan_tagging_operation_table=
VlanTaggingOperation(
filter_outer_priority=15,
filter_outer_vid=4096,
@@ -630,13 +659,13 @@
)
)
frame = OmciFrame(
- transaction_id = self.get_tx_id(),
+ transaction_id=self.get_tx_id(),
message_type=OmciSet.message_id,
omci_message=OmciSet(
- entity_class=\
+ entity_class=
ExtendedVlanTaggingOperationConfigurationData.class_id,
- entity_id = entity_id,
- attributes_mask= \
+ entity_id=entity_id,
+ attributes_mask=
ExtendedVlanTaggingOperationConfigurationData.mask_for(
*data.keys()),
data=data
@@ -644,13 +673,237 @@
)
self.send_omci_message(frame)
+ def send_create_multicast_operations_profile(self,
+ entity_id,
+ igmp_ver):
+ frame = OmciFrame(
+ transaction_id=self.get_tx_id(),
+ message_type=OmciCreate.message_id,
+ omci_message=OmciCreate(
+ entity_class=
+ MulticastOperationsProfile.class_id,
+ entity_id=entity_id,
+ data=dict(
+ igmp_version=igmp_ver,
+ igmp_function=0,
+ immediate_leave=0
+ )
+ )
+ )
+ self.send_omci_message(frame)
+
+ def send_set_multicast_operations_profile_acl_row0(self,
+ entity_id,
+ acl_table,
+ row_key,
+ gem_port,
+ vlan,
+ src_ip,
+ dst_ip_start,
+ dst_ip_end):
+ row0 = AccessControlRow0(
+ set_ctrl=1,
+ row_part_id=0,
+ test=0,
+ row_key=row_key,
+ gem_port_id=gem_port,
+ vlan_id=vlan,
+ src_ip=src_ip,
+ dst_ip_start=dst_ip_start,
+ dst_ip_end=dst_ip_end,
+ ipm_group_bw=0
+ )
+
+ if acl_table == 'dynamic':
+ data = dict(
+ dynamic_access_control_list_table=row0
+ )
+ else:
+ data = dict(
+ static_access_control_list_table=row0
+ )
+
+ frame = OmciFrame(
+ transaction_id=self.get_tx_id(),
+ message_type=OmciSet.message_id,
+ omci_message=OmciSet(
+ entity_class=MulticastOperationsProfile.class_id,
+ entity_id=entity_id,
+ attributes_mask=MulticastOperationsProfile.mask_for(
+ *data.keys()),
+ data=data
+ )
+ )
+ self.send_omci_message(frame)
+
+ def send_set_multicast_operations_profile_ds_igmp_mcast_tci(self,
+ entity_id,
+ ctrl_type,
+ tci):
+ data = dict(
+ ds_igmp_mcast_tci=
+ DownstreamIgmpMulticastTci(
+ ctrl_type=ctrl_type,
+ tci=tci
+ )
+ )
+ frame = OmciFrame(
+ transaction_id=self.get_tx_id(),
+ message_type=OmciSet.message_id,
+ omci_message=OmciSet(
+ entity_class=MulticastOperationsProfile.class_id,
+ entity_id=entity_id,
+ attributes_mask=MulticastOperationsProfile.mask_for(
+ *data.keys()),
+ data=data
+ )
+ )
+ self.send_omci_message(frame)
+
+ def send_create_multicast_subscriber_config_info(self,
+ entity_id,
+ me_type,
+ mcast_oper_profile):
+ frame = OmciFrame(
+ transaction_id=self.get_tx_id(),
+ message_type=OmciCreate.message_id,
+ omci_message=OmciCreate(
+ entity_class=
+ MulticastSubscriberConfigInfo.class_id,
+ entity_id=entity_id,
+ data=dict(
+ me_type=me_type,
+ mcast_operations_profile_pointer=mcast_oper_profile
+ )
+ )
+ )
+ self.send_omci_message(frame)
+
+ def send_set_multicast_subscriber_config_info(self,
+ entity_id,
+ max_groups=0,
+ max_mcast_bw=0,
+ bw_enforcement=0):
+ data = dict(
+ max_simultaneous_groups=max_groups,
+ max_multicast_bandwidth=max_mcast_bw,
+ bandwidth_enforcement=bw_enforcement
+ )
+ frame = OmciFrame(
+ transaction_id=self.get_tx_id(),
+ message_type=OmciSet.message_id,
+ omci_message=OmciSet(
+ entity_class=MulticastSubscriberConfigInfo.class_id,
+ entity_id=entity_id,
+ attributes_mask=MulticastSubscriberConfigInfo.mask_for(
+ *data.keys()),
+ data=data
+ )
+ )
+ self.send_omci_message(frame)
+
+ def send_set_multicast_service_package(self,
+ entity_id,
+ row_key,
+ vid_uni,
+ max_groups,
+ max_mcast_bw,
+ mcast_oper_profile):
+ data = dict(
+ multicast_service_package_table=
+ MulticastServicePackage(
+ set_ctrl=1,
+ row_key=row_key,
+
+ vid_uni=vid_uni,
+ max_simultaneous_groups=max_groups,
+ max_multicast_bw=max_mcast_bw,
+ mcast_operations_profile_pointer=mcast_oper_profile
+ )
+ )
+ frame = OmciFrame(
+ transaction_id=self.get_tx_id(),
+ message_type=OmciSet.message_id,
+ omci_message=OmciSet(
+ entity_class=MulticastSubscriberConfigInfo.class_id,
+ entity_id=entity_id,
+ attributes_mask=MulticastSubscriberConfigInfo.mask_for(
+ *data.keys()),
+ data=data
+ )
+ )
+ self.send_omci_message(frame)
+
+ def send_set_multicast_allowed_preview_groups_row0(self,
+ entity_id,
+ row_key,
+ src_ip,
+ vlan_id_ani,
+ vlan_id_uni):
+ data = dict(
+ allowed_preview_groups_table=
+ AllowedPreviewGroupsRow0(
+ set_ctrl=1,
+ row_part_id=0,
+ row_key=row_key,
+
+ src_ip=src_ip,
+ vlan_id_ani=vlan_id_ani,
+ vlan_id_uni=vlan_id_uni
+ )
+ )
+ frame = OmciFrame(
+ transaction_id=self.get_tx_id(),
+ message_type=OmciSet.message_id,
+ omci_message=OmciSet(
+ entity_class=MulticastSubscriberConfigInfo.class_id,
+ entity_id=entity_id,
+ attributes_mask=MulticastSubscriberConfigInfo.mask_for(
+ *data.keys()),
+ data=data
+ )
+ )
+ self.send_omci_message(frame)
+
+ def send_set_multicast_allowed_preview_groups_row1(self,
+ entity_id,
+ row_key,
+ dst_ip,
+ duration,
+ time_left):
+ data = dict(
+ allowed_preview_groups_table=
+ AllowedPreviewGroupsRow1(
+ set_ctrl=1,
+ row_part_id=1,
+ row_key=row_key,
+
+ dst_ip=dst_ip,
+ duration=duration,
+ time_left=time_left
+ )
+ )
+ frame = OmciFrame(
+ transaction_id=self.get_tx_id(),
+ message_type=OmciSet.message_id,
+ omci_message=OmciSet(
+ entity_class=MulticastSubscriberConfigInfo.class_id,
+ entity_id=entity_id,
+ attributes_mask=MulticastSubscriberConfigInfo.mask_for(
+ *data.keys()),
+ data=data
+ )
+ )
+ self.send_omci_message(frame)
+
@inlineCallbacks
def wait_for_response(self):
log.info('wait-for-response')
try:
response = yield self.incoming_messages.get()
- resp = OmciFrame(response)
- resp.show()
+ log.info('got-response')
+ # resp = OmciFrame(response)
+ # resp.show()
except Exception as e:
self.log.info('wait-for-response-exception', exc=str(e))
@@ -707,19 +960,23 @@
yield self.wait_for_response()
# Create AR - GemPortNetworkCtp - 256 - 1024 - 32768
- self.send_create_gem_port_network_ctp(0x100, 0x400, 0x8000)
+ self.send_create_gem_port_network_ctp(0x100, 0x400, 0x8000, "bi-directional", 0x100)
yield self.wait_for_response()
# Create AR - GemPortNetworkCtp - 257 - 1025 - 32769
- self.send_create_gem_port_network_ctp(0x101, 0x401, 0x8001)
+ self.send_create_gem_port_network_ctp(0x101, 0x401, 0x8001, "bi-directional", 0x100)
yield self.wait_for_response()
# Create AR - GemPortNetworkCtp - 258 - 1026 - 32770
- self.send_create_gem_port_network_ctp(0x102, 0x402, 0x8002)
+ self.send_create_gem_port_network_ctp(0x102, 0x402, 0x8002, "bi-directional", 0x100)
yield self.wait_for_response()
# Create AR - GemPortNetworkCtp - 259 - 1027 - 32771
- self.send_create_gem_port_network_ctp(0x103, 0x403, 0x8003)
+ self.send_create_gem_port_network_ctp(0x103, 0x403, 0x8003, "bi-directional", 0x100)
+ yield self.wait_for_response()
+
+ # Create AR - GemPortNetworkCtp - 260 - 4000 - 0
+ self.send_create_gem_port_network_ctp(0x104, 0x0FA0, 0, "downstream", 0)
yield self.wait_for_response()
# Create AR - MulticastGemInterworkingTp - 6 - 260
@@ -794,8 +1051,31 @@
self.send_create_vlan_tagging_filter_data(0x2104, 0x0403)
yield self.wait_for_response()
+ # Create AR - MulticastOperationsProfile
+ self.send_create_multicast_operations_profile(0x201, 3)
+ yield self.wait_for_response()
+
+ # Set AR - MulticastOperationsProfile - Dynamic Access Control List table
+ self.send_set_multicast_operations_profile_acl_row0(0x201,
+ 'dynamic',
+ 0,
+ 0x0fa0,
+ 0x0fa0,
+ '0.0.0.0',
+ '224.0.0.0',
+ '239.255.255.255')
+ yield self.wait_for_response()
+
+ # Create AR - MulticastSubscriberConfigInfo
+ self.send_create_multicast_subscriber_config_info(0x201, 0, 0x201)
+ yield self.wait_for_response()
+
+ # Set AR - MulticastOperationsProfile - Downstream IGMP Multicast TCI
+ self.send_set_multicast_operations_profile_ds_igmp_mcast_tci(0x201, 3, 0x401)
+ yield self.wait_for_response()
+
# Create AR - ExtendedVlanTaggingOperationConfigData - 514 - 2 - 0x105
- self.send_create_extended_vlan_tagging_operation_configuration_data(0x202, 2, 0x105)
+ self.send_create_extended_vlan_tagging_operation_configuration_data(0x202, 2, 0x102)
yield self.wait_for_response()
# Set AR - ExtendedVlanTaggingOperationConfigData - 514 - 8100 - 8100
@@ -808,5 +1088,5 @@
yield self.wait_for_response()
# Create AR - MacBridgePortConfigData - 513 - 513 - 1 - 1 - 0x105
- self.send_create_mac_bridge_port_configuration_data(0x201, 0x201, 1, 1, 0x105)
+ self.send_create_mac_bridge_port_configuration_data(0x201, 0x201, 1, 1, 0x102)
yield self.wait_for_response()
diff --git a/voltha/extensions/omci/omci_entities.py b/voltha/extensions/omci/omci_entities.py
index 79b0d6c..e3f7473 100644
--- a/voltha/extensions/omci/omci_entities.py
+++ b/voltha/extensions/omci/omci_entities.py
@@ -585,6 +585,58 @@
mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.GetNext, OP.Set}
+class AccessControlRow0(Packet):
+ name = "AccessControlRow0"
+ fields_desc = [
+ BitField("set_ctrl", 0, 2),
+ BitField("row_part_id", 0, 3),
+ BitField("test", 0, 1),
+ BitField("row_key", 0, 10),
+
+ ShortField("gem_port_id", None),
+ ShortField("vlan_id", None),
+ IPField("src_ip", None),
+ IPField("dst_ip_start", None),
+ IPField("dst_ip_end", None),
+ IntField("ipm_group_bw", None),
+ ShortField("reserved0", 0)
+ ]
+
+class AccessControlRow1(Packet):
+ name = "AccessControlRow1"
+ fields_desc = [
+ BitField("set_ctrl", 0, 2),
+ BitField("row_part_id", 0, 3),
+ BitField("test", 0, 1),
+ BitField("row_key", 0, 10),
+
+ StrFixedLenField("ipv6_src_addr_start_bytes", None, 12),
+ ShortField("preview_length", None),
+ ShortField("preview_repeat_time", None),
+ ShortField("preview_repeat_count", None),
+ ShortField("preview_reset_time", None),
+ ShortField("reserved1", 0)
+ ]
+
+class AccessControlRow2(Packet):
+ name = "AccessControlRow2"
+ fields_desc = [
+ BitField("set_ctrl", 0, 2),
+ BitField("row_part_id", 0, 3),
+ BitField("test", 0, 1),
+ BitField("row_key", 0, 10),
+
+ StrFixedLenField("ipv6_dst_addr_start_bytes", None, 12),
+ StrFixedLenField("reserved2", None, 10)
+ ]
+
+class DownstreamIgmpMulticastTci(Packet):
+ name = "DownstreamIgmpMulticastTci"
+ fields_desc = [
+ ByteField("ctrl_type", None),
+ ShortField("tci", None)
+ ]
+
class MulticastOperationsProfile(EntityClass):
class_id = 309
attributes = [
@@ -604,15 +656,56 @@
# TODO: need to make table and add column data
ECA(StrFixedLenField("lost_groups_list_table", None, 10), {AA.R}, optional=True),
ECA(ByteField("robustness", None), {AA.R, AA.W, AA.SBC}, optional=True),
- ECA(IPField("querier_ip", None), {AA.R, AA.W, AA.SBC}, optional=True),
+ ECA(IntField("querier_ip", None), {AA.R, AA.W, AA.SBC}, optional=True),
ECA(IntField("query_interval", None), {AA.R, AA.W, AA.SBC}, optional=True),
ECA(IntField("querier_max_response_time", None), {AA.R, AA.W, AA.SBC}, optional=True),
ECA(IntField("last_member_response_time", None), {AA.R, AA.W}, optional=True),
ECA(ByteField("unauthorized_join_behaviour", None), {AA.R, AA.W}, optional=True),
- ECA(ThreeBytesField("ds_igmp_mcast_tci", None), {AA.R, AA.W, AA.SBC}, optional=True),
+ ECA(StrFixedLenField("ds_igmp_mcast_tci", None, 3), {AA.R, AA.W, AA.SBC}, optional=True)
]
mandatory_operations = {OP.Create, OP.Delete, OP.Set, OP.Get, OP.GetNext}
+class MulticastServicePackage(Packet):
+ name = "MulticastServicePackage"
+ fields_desc = [
+ BitField("set_ctrl", 0, 2),
+ BitField("reserved0", 0, 4),
+ BitField("row_key", 0, 10),
+
+ ShortField("vid_uni", None),
+ ShortField("max_simultaneous_groups", None),
+ IntField("max_multicast_bw", None),
+ ShortField("mcast_operations_profile_pointer", None),
+ StrFixedLenField("reserved1", None, 8)
+ ]
+
+class AllowedPreviewGroupsRow0(Packet):
+ name = "AllowedPreviewGroupsRow0"
+ fields_desc = [
+ BitField("set_ctrl", 0, 2),
+ BitField("row_part_id", 0, 3),
+ BitField("reserved0", 0, 1),
+ BitField("row_key", 0, 10),
+
+ StrFixedLenField("ipv6_pad", 0, 12),
+ IPField("src_ip", None),
+ ShortField("vlan_id_ani", None),
+ ShortField("vlan_id_uni", None)
+ ]
+
+class AllowedPreviewGroupsRow1(Packet):
+ name = "AllowedPreviewGroupsRow1"
+ fields_desc = [
+ BitField("set_ctrl", 0, 2),
+ BitField("row_part_id", 0, 3),
+ BitField("reserved0", 0, 1),
+ BitField("row_key", 0, 10),
+
+ StrFixedLenField("ipv6_pad", 0, 12),
+ IPField("dst_ip", None),
+ ShortField("duration", None),
+ ShortField("time_left", None)
+ ]
class MulticastSubscriberConfigInfo(EntityClass):
class_id = 310
@@ -622,6 +715,7 @@
ECA(ShortField("mcast_operations_profile_pointer", None), {AA.R, AA.W, AA.SBC}),
ECA(ShortField("max_simultaneous_groups", None), {AA.R, AA.W, AA.SBC}, optional=True),
ECA(IntField("max_multicast_bandwidth", None), {AA.R, AA.W, AA.SBC}, optional=True),
+ ECA(ByteField("bandwidth_enforcement", None), {AA.R, AA.W, AA.SBC}, optional=True),
# TODO: need to make table and add column data
ECA(StrFixedLenField(
"multicast_service_package_table", None, 20), {AA.R, AA.W}, optional=True),