[VOL-3837] Checking that OnuId, AllocId and GemPorts are unique per PON
Validate that received flow carry valid GemPortId and AllocIds
Change-Id: I1b8928c7a9e580c9711f61320595a449df7c30f5
diff --git a/Makefile b/Makefile
index a993f7f..efeea2d 100644
--- a/Makefile
+++ b/Makefile
@@ -80,7 +80,7 @@
test-unit: clean local-omci-lib-go # @HELP Execute unit tests
@echo "Running unit tests..."
@mkdir -p ./tests/results
- @${GO} test -mod=vendor -v -coverprofile ./tests/results/go-test-coverage.out -covermode count ./... 2>&1 | tee ./tests/results/go-test-results.out ;\
+ @${GO} test -mod=vendor -bench=. -v -coverprofile ./tests/results/go-test-coverage.out -covermode count ./... 2>&1 | tee ./tests/results/go-test-results.out ;\
RETURN=$$? ;\
${GO_JUNIT_REPORT} < ./tests/results/go-test-results.out > ./tests/results/go-test-results.xml ;\
${GOCOVER_COBERTURA} < ./tests/results/go-test-coverage.out > ./tests/results/go-test-coverage.xml ;\
diff --git a/api/bbsim/bbsim.pb.go b/api/bbsim/bbsim.pb.go
index fa00279..b5df9e9 100644
--- a/api/bbsim/bbsim.pb.go
+++ b/api/bbsim/bbsim.pb.go
@@ -54,6 +54,34 @@
return fileDescriptor_ef7750073d18011b, []int{0}
}
+type OltAllocatedResourceType_Type int32
+
+const (
+ OltAllocatedResourceType_UNKNOWN OltAllocatedResourceType_Type = 0
+ OltAllocatedResourceType_ALLOC_ID OltAllocatedResourceType_Type = 1
+ OltAllocatedResourceType_GEM_PORT OltAllocatedResourceType_Type = 2
+)
+
+var OltAllocatedResourceType_Type_name = map[int32]string{
+ 0: "UNKNOWN",
+ 1: "ALLOC_ID",
+ 2: "GEM_PORT",
+}
+
+var OltAllocatedResourceType_Type_value = map[string]int32{
+ "UNKNOWN": 0,
+ "ALLOC_ID": 1,
+ "GEM_PORT": 2,
+}
+
+func (x OltAllocatedResourceType_Type) String() string {
+ return proto.EnumName(OltAllocatedResourceType_Type_name, int32(x))
+}
+
+func (OltAllocatedResourceType_Type) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor_ef7750073d18011b, []int{4, 0}
+}
+
// These types correspond to the messages permitted in the oneof
// in AlarmIndication in the openolt protos
type AlarmType_Types int32
@@ -131,15 +159,22 @@
}
func (AlarmType_Types) EnumDescriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{10, 0}
+ return fileDescriptor_ef7750073d18011b, []int{14, 0}
}
type PONPort struct {
- ID int32 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
- OperState string `protobuf:"bytes,2,opt,name=OperState,proto3" json:"OperState,omitempty"`
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
- XXX_unrecognized []byte `json:"-"`
- XXX_sizecache int32 `json:"-"`
+ ID int32 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
+ OperState string `protobuf:"bytes,2,opt,name=OperState,proto3" json:"OperState,omitempty"`
+ InternalState string `protobuf:"bytes,3,opt,name=InternalState,proto3" json:"InternalState,omitempty"`
+ PacketCount uint64 `protobuf:"varint,4,opt,name=PacketCount,proto3" json:"PacketCount,omitempty"`
+ // ONU ID are reported by VOLTHA in the ActivateOnu call
+ AllocatedOnuIds []*PonAllocatedResources `protobuf:"bytes,5,rep,name=AllocatedOnuIds,proto3" json:"AllocatedOnuIds,omitempty"`
+ // these are the stored resource IDs as reported via OMCI
+ AllocatedGemPorts []*PonAllocatedResources `protobuf:"bytes,6,rep,name=AllocatedGemPorts,proto3" json:"AllocatedGemPorts,omitempty"`
+ AllocatedAllocIds []*PonAllocatedResources `protobuf:"bytes,7,rep,name=AllocatedAllocIds,proto3" json:"AllocatedAllocIds,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
func (m *PONPort) Reset() { *m = PONPort{} }
@@ -181,6 +216,88 @@
return ""
}
+func (m *PONPort) GetInternalState() string {
+ if m != nil {
+ return m.InternalState
+ }
+ return ""
+}
+
+func (m *PONPort) GetPacketCount() uint64 {
+ if m != nil {
+ return m.PacketCount
+ }
+ return 0
+}
+
+func (m *PONPort) GetAllocatedOnuIds() []*PonAllocatedResources {
+ if m != nil {
+ return m.AllocatedOnuIds
+ }
+ return nil
+}
+
+func (m *PONPort) GetAllocatedGemPorts() []*PonAllocatedResources {
+ if m != nil {
+ return m.AllocatedGemPorts
+ }
+ return nil
+}
+
+func (m *PONPort) GetAllocatedAllocIds() []*PonAllocatedResources {
+ if m != nil {
+ return m.AllocatedAllocIds
+ }
+ return nil
+}
+
+type PonAllocatedResources struct {
+ SerialNumber string `protobuf:"bytes,1,opt,name=SerialNumber,proto3" json:"SerialNumber,omitempty"`
+ Id int32 `protobuf:"varint,2,opt,name=Id,proto3" json:"Id,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *PonAllocatedResources) Reset() { *m = PonAllocatedResources{} }
+func (m *PonAllocatedResources) String() string { return proto.CompactTextString(m) }
+func (*PonAllocatedResources) ProtoMessage() {}
+func (*PonAllocatedResources) Descriptor() ([]byte, []int) {
+ return fileDescriptor_ef7750073d18011b, []int{1}
+}
+
+func (m *PonAllocatedResources) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_PonAllocatedResources.Unmarshal(m, b)
+}
+func (m *PonAllocatedResources) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_PonAllocatedResources.Marshal(b, m, deterministic)
+}
+func (m *PonAllocatedResources) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_PonAllocatedResources.Merge(m, src)
+}
+func (m *PonAllocatedResources) XXX_Size() int {
+ return xxx_messageInfo_PonAllocatedResources.Size(m)
+}
+func (m *PonAllocatedResources) XXX_DiscardUnknown() {
+ xxx_messageInfo_PonAllocatedResources.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PonAllocatedResources proto.InternalMessageInfo
+
+func (m *PonAllocatedResources) GetSerialNumber() string {
+ if m != nil {
+ return m.SerialNumber
+ }
+ return ""
+}
+
+func (m *PonAllocatedResources) GetId() int32 {
+ if m != nil {
+ return m.Id
+ }
+ return 0
+}
+
type NNIPort struct {
ID int32 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
OperState string `protobuf:"bytes,2,opt,name=OperState,proto3" json:"OperState,omitempty"`
@@ -193,7 +310,7 @@
func (m *NNIPort) String() string { return proto.CompactTextString(m) }
func (*NNIPort) ProtoMessage() {}
func (*NNIPort) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{1}
+ return fileDescriptor_ef7750073d18011b, []int{2}
}
func (m *NNIPort) XXX_Unmarshal(b []byte) error {
@@ -245,7 +362,7 @@
func (m *Olt) String() string { return proto.CompactTextString(m) }
func (*Olt) ProtoMessage() {}
func (*Olt) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{2}
+ return fileDescriptor_ef7750073d18011b, []int{3}
}
func (m *Olt) XXX_Unmarshal(b []byte) error {
@@ -315,6 +432,163 @@
return nil
}
+type OltAllocatedResourceType struct {
+ Type OltAllocatedResourceType_Type `protobuf:"varint,1,opt,name=type,proto3,enum=bbsim.OltAllocatedResourceType_Type" json:"type,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *OltAllocatedResourceType) Reset() { *m = OltAllocatedResourceType{} }
+func (m *OltAllocatedResourceType) String() string { return proto.CompactTextString(m) }
+func (*OltAllocatedResourceType) ProtoMessage() {}
+func (*OltAllocatedResourceType) Descriptor() ([]byte, []int) {
+ return fileDescriptor_ef7750073d18011b, []int{4}
+}
+
+func (m *OltAllocatedResourceType) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_OltAllocatedResourceType.Unmarshal(m, b)
+}
+func (m *OltAllocatedResourceType) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_OltAllocatedResourceType.Marshal(b, m, deterministic)
+}
+func (m *OltAllocatedResourceType) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_OltAllocatedResourceType.Merge(m, src)
+}
+func (m *OltAllocatedResourceType) XXX_Size() int {
+ return xxx_messageInfo_OltAllocatedResourceType.Size(m)
+}
+func (m *OltAllocatedResourceType) XXX_DiscardUnknown() {
+ xxx_messageInfo_OltAllocatedResourceType.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OltAllocatedResourceType proto.InternalMessageInfo
+
+func (m *OltAllocatedResourceType) GetType() OltAllocatedResourceType_Type {
+ if m != nil {
+ return m.Type
+ }
+ return OltAllocatedResourceType_UNKNOWN
+}
+
+type OltAllocatedResource struct {
+ Type string `protobuf:"bytes,1,opt,name=Type,proto3" json:"Type,omitempty"`
+ PonPortId uint32 `protobuf:"varint,2,opt,name=PonPortId,proto3" json:"PonPortId,omitempty"`
+ OnuId uint32 `protobuf:"varint,3,opt,name=OnuId,proto3" json:"OnuId,omitempty"`
+ PortNo uint32 `protobuf:"varint,4,opt,name=PortNo,proto3" json:"PortNo,omitempty"`
+ ResourceId int32 `protobuf:"varint,5,opt,name=ResourceId,proto3" json:"ResourceId,omitempty"`
+ FlowId uint64 `protobuf:"varint,6,opt,name=FlowId,proto3" json:"FlowId,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *OltAllocatedResource) Reset() { *m = OltAllocatedResource{} }
+func (m *OltAllocatedResource) String() string { return proto.CompactTextString(m) }
+func (*OltAllocatedResource) ProtoMessage() {}
+func (*OltAllocatedResource) Descriptor() ([]byte, []int) {
+ return fileDescriptor_ef7750073d18011b, []int{5}
+}
+
+func (m *OltAllocatedResource) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_OltAllocatedResource.Unmarshal(m, b)
+}
+func (m *OltAllocatedResource) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_OltAllocatedResource.Marshal(b, m, deterministic)
+}
+func (m *OltAllocatedResource) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_OltAllocatedResource.Merge(m, src)
+}
+func (m *OltAllocatedResource) XXX_Size() int {
+ return xxx_messageInfo_OltAllocatedResource.Size(m)
+}
+func (m *OltAllocatedResource) XXX_DiscardUnknown() {
+ xxx_messageInfo_OltAllocatedResource.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OltAllocatedResource proto.InternalMessageInfo
+
+func (m *OltAllocatedResource) GetType() string {
+ if m != nil {
+ return m.Type
+ }
+ return ""
+}
+
+func (m *OltAllocatedResource) GetPonPortId() uint32 {
+ if m != nil {
+ return m.PonPortId
+ }
+ return 0
+}
+
+func (m *OltAllocatedResource) GetOnuId() uint32 {
+ if m != nil {
+ return m.OnuId
+ }
+ return 0
+}
+
+func (m *OltAllocatedResource) GetPortNo() uint32 {
+ if m != nil {
+ return m.PortNo
+ }
+ return 0
+}
+
+func (m *OltAllocatedResource) GetResourceId() int32 {
+ if m != nil {
+ return m.ResourceId
+ }
+ return 0
+}
+
+func (m *OltAllocatedResource) GetFlowId() uint64 {
+ if m != nil {
+ return m.FlowId
+ }
+ return 0
+}
+
+type OltAllocatedResources struct {
+ Resources []*OltAllocatedResource `protobuf:"bytes,1,rep,name=resources,proto3" json:"resources,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *OltAllocatedResources) Reset() { *m = OltAllocatedResources{} }
+func (m *OltAllocatedResources) String() string { return proto.CompactTextString(m) }
+func (*OltAllocatedResources) ProtoMessage() {}
+func (*OltAllocatedResources) Descriptor() ([]byte, []int) {
+ return fileDescriptor_ef7750073d18011b, []int{6}
+}
+
+func (m *OltAllocatedResources) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_OltAllocatedResources.Unmarshal(m, b)
+}
+func (m *OltAllocatedResources) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_OltAllocatedResources.Marshal(b, m, deterministic)
+}
+func (m *OltAllocatedResources) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_OltAllocatedResources.Merge(m, src)
+}
+func (m *OltAllocatedResources) XXX_Size() int {
+ return xxx_messageInfo_OltAllocatedResources.Size(m)
+}
+func (m *OltAllocatedResources) XXX_DiscardUnknown() {
+ xxx_messageInfo_OltAllocatedResources.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OltAllocatedResources proto.InternalMessageInfo
+
+func (m *OltAllocatedResources) GetResources() []*OltAllocatedResource {
+ if m != nil {
+ return m.Resources
+ }
+ return nil
+}
+
type ONU struct {
ID int32 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
SerialNumber string `protobuf:"bytes,2,opt,name=SerialNumber,proto3" json:"SerialNumber,omitempty"`
@@ -337,7 +611,7 @@
func (m *ONU) String() string { return proto.CompactTextString(m) }
func (*ONU) ProtoMessage() {}
func (*ONU) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{3}
+ return fileDescriptor_ef7750073d18011b, []int{7}
}
func (m *ONU) XXX_Unmarshal(b []byte) error {
@@ -465,7 +739,7 @@
func (m *Service) String() string { return proto.CompactTextString(m) }
func (*Service) ProtoMessage() {}
func (*Service) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{4}
+ return fileDescriptor_ef7750073d18011b, []int{8}
}
func (m *Service) XXX_Unmarshal(b []byte) error {
@@ -588,7 +862,7 @@
func (m *ONUTrafficSchedulers) String() string { return proto.CompactTextString(m) }
func (*ONUTrafficSchedulers) ProtoMessage() {}
func (*ONUTrafficSchedulers) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{5}
+ return fileDescriptor_ef7750073d18011b, []int{9}
}
func (m *ONUTrafficSchedulers) XXX_Unmarshal(b []byte) error {
@@ -627,7 +901,7 @@
func (m *ONUs) String() string { return proto.CompactTextString(m) }
func (*ONUs) ProtoMessage() {}
func (*ONUs) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{6}
+ return fileDescriptor_ef7750073d18011b, []int{10}
}
func (m *ONUs) XXX_Unmarshal(b []byte) error {
@@ -666,7 +940,7 @@
func (m *Services) String() string { return proto.CompactTextString(m) }
func (*Services) ProtoMessage() {}
func (*Services) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{7}
+ return fileDescriptor_ef7750073d18011b, []int{11}
}
func (m *Services) XXX_Unmarshal(b []byte) error {
@@ -705,7 +979,7 @@
func (m *ONURequest) String() string { return proto.CompactTextString(m) }
func (*ONURequest) ProtoMessage() {}
func (*ONURequest) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{8}
+ return fileDescriptor_ef7750073d18011b, []int{12}
}
func (m *ONURequest) XXX_Unmarshal(b []byte) error {
@@ -744,7 +1018,7 @@
func (m *PONRequest) String() string { return proto.CompactTextString(m) }
func (*PONRequest) ProtoMessage() {}
func (*PONRequest) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{9}
+ return fileDescriptor_ef7750073d18011b, []int{13}
}
func (m *PONRequest) XXX_Unmarshal(b []byte) error {
@@ -782,7 +1056,7 @@
func (m *AlarmType) String() string { return proto.CompactTextString(m) }
func (*AlarmType) ProtoMessage() {}
func (*AlarmType) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{10}
+ return fileDescriptor_ef7750073d18011b, []int{14}
}
func (m *AlarmType) XXX_Unmarshal(b []byte) error {
@@ -815,7 +1089,7 @@
func (m *AlarmParameter) String() string { return proto.CompactTextString(m) }
func (*AlarmParameter) ProtoMessage() {}
func (*AlarmParameter) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{11}
+ return fileDescriptor_ef7750073d18011b, []int{15}
}
func (m *AlarmParameter) XXX_Unmarshal(b []byte) error {
@@ -867,7 +1141,7 @@
func (m *ONUAlarmRequest) String() string { return proto.CompactTextString(m) }
func (*ONUAlarmRequest) ProtoMessage() {}
func (*ONUAlarmRequest) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{12}
+ return fileDescriptor_ef7750073d18011b, []int{16}
}
func (m *ONUAlarmRequest) XXX_Unmarshal(b []byte) error {
@@ -930,7 +1204,7 @@
func (m *OLTAlarmRequest) String() string { return proto.CompactTextString(m) }
func (*OLTAlarmRequest) ProtoMessage() {}
func (*OLTAlarmRequest) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{13}
+ return fileDescriptor_ef7750073d18011b, []int{17}
}
func (m *OLTAlarmRequest) XXX_Unmarshal(b []byte) error {
@@ -986,7 +1260,7 @@
func (m *VersionNumber) String() string { return proto.CompactTextString(m) }
func (*VersionNumber) ProtoMessage() {}
func (*VersionNumber) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{14}
+ return fileDescriptor_ef7750073d18011b, []int{18}
}
func (m *VersionNumber) XXX_Unmarshal(b []byte) error {
@@ -1047,7 +1321,7 @@
func (m *LogLevel) String() string { return proto.CompactTextString(m) }
func (*LogLevel) ProtoMessage() {}
func (*LogLevel) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{15}
+ return fileDescriptor_ef7750073d18011b, []int{19}
}
func (m *LogLevel) XXX_Unmarshal(b []byte) error {
@@ -1094,7 +1368,7 @@
func (m *Response) String() string { return proto.CompactTextString(m) }
func (*Response) ProtoMessage() {}
func (*Response) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{16}
+ return fileDescriptor_ef7750073d18011b, []int{20}
}
func (m *Response) XXX_Unmarshal(b []byte) error {
@@ -1142,7 +1416,7 @@
func (m *IgmpRequest) String() string { return proto.CompactTextString(m) }
func (*IgmpRequest) ProtoMessage() {}
func (*IgmpRequest) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{17}
+ return fileDescriptor_ef7750073d18011b, []int{21}
}
func (m *IgmpRequest) XXX_Unmarshal(b []byte) error {
@@ -1196,7 +1470,7 @@
func (m *Flows) String() string { return proto.CompactTextString(m) }
func (*Flows) ProtoMessage() {}
func (*Flows) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{18}
+ return fileDescriptor_ef7750073d18011b, []int{22}
}
func (m *Flows) XXX_Unmarshal(b []byte) error {
@@ -1242,7 +1516,7 @@
func (m *Timeout) String() string { return proto.CompactTextString(m) }
func (*Timeout) ProtoMessage() {}
func (*Timeout) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{19}
+ return fileDescriptor_ef7750073d18011b, []int{23}
}
func (m *Timeout) XXX_Unmarshal(b []byte) error {
@@ -1280,7 +1554,7 @@
func (m *Empty) String() string { return proto.CompactTextString(m) }
func (*Empty) ProtoMessage() {}
func (*Empty) Descriptor() ([]byte, []int) {
- return fileDescriptor_ef7750073d18011b, []int{20}
+ return fileDescriptor_ef7750073d18011b, []int{24}
}
func (m *Empty) XXX_Unmarshal(b []byte) error {
@@ -1303,10 +1577,15 @@
func init() {
proto.RegisterEnum("bbsim.SubActionTypes", SubActionTypes_name, SubActionTypes_value)
+ proto.RegisterEnum("bbsim.OltAllocatedResourceType_Type", OltAllocatedResourceType_Type_name, OltAllocatedResourceType_Type_value)
proto.RegisterEnum("bbsim.AlarmType_Types", AlarmType_Types_name, AlarmType_Types_value)
proto.RegisterType((*PONPort)(nil), "bbsim.PONPort")
+ proto.RegisterType((*PonAllocatedResources)(nil), "bbsim.PonAllocatedResources")
proto.RegisterType((*NNIPort)(nil), "bbsim.NNIPort")
proto.RegisterType((*Olt)(nil), "bbsim.Olt")
+ proto.RegisterType((*OltAllocatedResourceType)(nil), "bbsim.OltAllocatedResourceType")
+ proto.RegisterType((*OltAllocatedResource)(nil), "bbsim.OltAllocatedResource")
+ proto.RegisterType((*OltAllocatedResources)(nil), "bbsim.OltAllocatedResources")
proto.RegisterType((*ONU)(nil), "bbsim.ONU")
proto.RegisterType((*Service)(nil), "bbsim.Service")
proto.RegisterType((*ONUTrafficSchedulers)(nil), "bbsim.ONUTrafficSchedulers")
@@ -1330,112 +1609,128 @@
func init() { proto.RegisterFile("api/bbsim/bbsim.proto", fileDescriptor_ef7750073d18011b) }
var fileDescriptor_ef7750073d18011b = []byte{
- // 1668 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0xcd, 0x72, 0xdb, 0xc8,
- 0x11, 0xe6, 0x8f, 0xf8, 0xd7, 0x14, 0x29, 0x68, 0x6c, 0x6b, 0x51, 0x5a, 0x6f, 0xcc, 0x42, 0x9c,
- 0x94, 0xec, 0xca, 0xca, 0x6b, 0x3b, 0xd9, 0x78, 0x8f, 0x30, 0x09, 0xd1, 0x88, 0x29, 0x00, 0x35,
- 0x20, 0xe5, 0xf2, 0x09, 0x05, 0x91, 0x23, 0x0a, 0x55, 0x20, 0x40, 0x03, 0x43, 0x29, 0x7a, 0x80,
- 0x3c, 0x43, 0xee, 0x79, 0xa2, 0x3c, 0x41, 0x6e, 0xc9, 0x3d, 0x95, 0x17, 0x48, 0xcd, 0x60, 0x00,
- 0x02, 0x24, 0xb5, 0x91, 0x73, 0xd9, 0x0b, 0x0b, 0xf3, 0x75, 0x7f, 0xdd, 0x3d, 0x3d, 0x3d, 0xdd,
- 0x53, 0x84, 0x27, 0xee, 0xd2, 0x7b, 0x75, 0x79, 0x19, 0x7b, 0x8b, 0xe4, 0xf7, 0x74, 0x19, 0x85,
- 0x34, 0x44, 0x35, 0xbe, 0x38, 0xfe, 0xf6, 0x26, 0xf4, 0xe9, 0xb5, 0xeb, 0x70, 0x30, 0x7e, 0x15,
- 0x2e, 0x49, 0x10, 0xfa, 0x34, 0xd1, 0x39, 0xee, 0x15, 0x85, 0x94, 0x4c, 0xaf, 0xd9, 0xf7, 0x95,
- 0xe7, 0x93, 0x44, 0x43, 0xf9, 0x23, 0x34, 0x2c, 0xd3, 0xb0, 0xc2, 0x88, 0xa2, 0x2e, 0x54, 0xf4,
- 0x81, 0x5c, 0xee, 0x95, 0x4f, 0x6a, 0xb8, 0xa2, 0x0f, 0xd0, 0x53, 0x68, 0x99, 0x4b, 0x12, 0xd9,
- 0xd4, 0xa5, 0x44, 0xae, 0xf4, 0xca, 0x27, 0x2d, 0xbc, 0x06, 0x18, 0xd1, 0x30, 0xf4, 0xff, 0x83,
- 0xf8, 0xcf, 0x32, 0x54, 0x4d, 0x7f, 0x9b, 0xa5, 0xc0, 0xbe, 0x4d, 0x22, 0xcf, 0xf5, 0x8d, 0xd5,
- 0xe2, 0x92, 0x44, 0x82, 0x58, 0xc0, 0x8a, 0x96, 0xab, 0x1b, 0x96, 0xd1, 0x73, 0xe8, 0xe8, 0x01,
- 0x25, 0x51, 0xe0, 0xfa, 0x89, 0xc6, 0x1e, 0xd7, 0x28, 0x82, 0xdc, 0xaf, 0x25, 0x37, 0xb8, 0xa8,
- 0xa2, 0x5b, 0xe8, 0x25, 0x34, 0xc5, 0x46, 0x62, 0xb9, 0xd6, 0xab, 0x9e, 0xb4, 0xdf, 0x74, 0x4f,
- 0x93, 0x3c, 0x0b, 0x18, 0x67, 0x72, 0xa6, 0x2b, 0xb2, 0x15, 0xcb, 0xf5, 0x82, 0xae, 0x80, 0x71,
- 0x26, 0x57, 0xfe, 0x53, 0x85, 0xaa, 0x69, 0x4c, 0x7e, 0xb1, 0x7d, 0x3e, 0x85, 0x96, 0x15, 0x06,
- 0x2c, 0x16, 0x7d, 0x20, 0xd7, 0xb8, 0xfb, 0x35, 0xc0, 0xa4, 0x1f, 0x6e, 0xd5, 0xd9, 0x2c, 0x22,
- 0x71, 0x2c, 0x37, 0x13, 0x0f, 0x19, 0x80, 0x8e, 0xa0, 0xce, 0xf4, 0x8c, 0x50, 0x6e, 0x71, 0xa2,
- 0x58, 0xb1, 0xfd, 0xc7, 0x24, 0xba, 0xf1, 0xa6, 0x24, 0x96, 0xa1, 0xb0, 0x7f, 0x3b, 0x81, 0x71,
- 0x26, 0x47, 0x03, 0xf8, 0x4e, 0x5f, 0xb8, 0x73, 0x62, 0x87, 0x57, 0xf4, 0xd6, 0x8d, 0x88, 0xf6,
- 0xe7, 0x25, 0x99, 0x52, 0x32, 0xb3, 0xc9, 0x94, 0x7a, 0x61, 0x10, 0xcb, 0x6d, 0x6e, 0xfa, 0xe7,
- 0x95, 0xb6, 0xac, 0x60, 0x32, 0x25, 0xde, 0x4d, 0xce, 0xca, 0xfe, 0x0e, 0x2b, 0x9b, 0x4a, 0xe8,
- 0x07, 0x78, 0xa4, 0x4e, 0xa9, 0x77, 0x43, 0xb8, 0x9a, 0x16, 0x50, 0x8f, 0xde, 0xe9, 0x33, 0xb9,
- 0xc3, 0xb9, 0xbb, 0x44, 0xe8, 0x47, 0x38, 0xea, 0x87, 0x8b, 0x85, 0x47, 0x29, 0x99, 0x15, 0x49,
- 0x5d, 0x4e, 0xba, 0x47, 0xaa, 0xfc, 0xbb, 0x02, 0x0d, 0x91, 0x0b, 0x84, 0x60, 0xcf, 0x70, 0x17,
- 0x84, 0x9f, 0x7d, 0x0b, 0xf3, 0xef, 0x62, 0xde, 0x2b, 0x9b, 0x79, 0x7f, 0x0c, 0x35, 0x33, 0x58,
- 0xd9, 0x81, 0x38, 0xf3, 0x64, 0xc1, 0xec, 0xd8, 0x63, 0x77, 0xce, 0x8f, 0xb9, 0x86, 0xf9, 0x37,
- 0xc3, 0xfa, 0x0c, 0x4b, 0x0e, 0x96, 0x7f, 0xa3, 0x5f, 0x01, 0x18, 0x84, 0xcc, 0x62, 0xcd, 0x5d,
- 0x86, 0xbe, 0x5c, 0xef, 0x95, 0x4f, 0x9a, 0x38, 0x87, 0x30, 0xdf, 0x7c, 0x35, 0xb8, 0x9e, 0x2e,
- 0xf9, 0x05, 0x68, 0xe2, 0x35, 0x90, 0x49, 0xf5, 0xf9, 0x62, 0xc9, 0x2b, 0x22, 0x95, 0x32, 0x00,
- 0xc9, 0xd0, 0x18, 0x92, 0x05, 0x2b, 0x03, 0x51, 0x12, 0xe9, 0x92, 0x79, 0xe5, 0xe6, 0x93, 0x52,
- 0x04, 0x1e, 0x78, 0x0e, 0x61, 0x76, 0x99, 0xfd, 0x44, 0xdc, 0x4e, 0x76, 0x9c, 0x01, 0xdb, 0xb5,
- 0xbc, 0x7f, 0x4f, 0x2d, 0xeb, 0xc3, 0x73, 0x2b, 0xd1, 0xe8, 0x24, 0x36, 0x32, 0x40, 0x71, 0xe1,
- 0xb1, 0x69, 0x4c, 0xc6, 0x91, 0x7b, 0x75, 0xe5, 0x4d, 0xed, 0xe9, 0x35, 0x99, 0xad, 0x7c, 0x12,
- 0xc5, 0x48, 0x87, 0x03, 0xca, 0xc0, 0x35, 0xc4, 0x8f, 0xa2, 0xfd, 0xe6, 0xd9, 0x69, 0xa1, 0x13,
- 0x6e, 0x31, 0xf1, 0x26, 0x4f, 0x39, 0x81, 0x3d, 0xd3, 0x98, 0xc4, 0xa8, 0x07, 0x35, 0x8f, 0x92,
- 0x05, 0x33, 0xc4, 0xaa, 0x1f, 0x44, 0xf5, 0x9b, 0xc6, 0x04, 0x27, 0x02, 0xe5, 0x07, 0x68, 0xda,
- 0xe9, 0x15, 0x78, 0x5e, 0xd4, 0xde, 0xbc, 0x2b, 0x19, 0x03, 0x18, 0x9f, 0x7c, 0x59, 0x91, 0x98,
- 0x6e, 0xb5, 0x87, 0xf2, 0x76, 0x7b, 0x50, 0x5e, 0x02, 0x58, 0xa6, 0x91, 0x32, 0x72, 0x17, 0x7d,
- 0xc6, 0xd5, 0x3b, 0xeb, 0x8b, 0x3e, 0x53, 0xfe, 0x51, 0x85, 0x96, 0xea, 0xbb, 0xd1, 0x62, 0x7c,
- 0xb7, 0x24, 0xca, 0xdf, 0xab, 0x50, 0x63, 0x1f, 0x31, 0x6a, 0x40, 0x75, 0x64, 0xda, 0x52, 0x09,
- 0x75, 0x01, 0x06, 0x9f, 0x75, 0x63, 0xe8, 0x0c, 0x55, 0xdb, 0x92, 0xca, 0xa8, 0x03, 0x2d, 0xd3,
- 0x98, 0x38, 0xea, 0x48, 0xc5, 0xe7, 0x52, 0x05, 0x7d, 0x03, 0x8f, 0xd8, 0xd2, 0x1e, 0xab, 0x78,
- 0x3c, 0xb1, 0x9c, 0x33, 0x55, 0x1f, 0x4d, 0xb0, 0x26, 0x55, 0xd1, 0x11, 0x20, 0x2e, 0xd0, 0x87,
- 0x86, 0x3a, 0x72, 0x06, 0xda, 0x10, 0xab, 0x03, 0x4d, 0xda, 0x4b, 0x09, 0x03, 0xac, 0x9f, 0x8d,
- 0x1d, 0xf3, 0xcc, 0xf9, 0xa4, 0x1b, 0x03, 0xf3, 0x93, 0x54, 0x43, 0x4f, 0x41, 0x66, 0x82, 0x91,
- 0x69, 0xdb, 0x0c, 0x37, 0xcf, 0xfb, 0xba, 0xd3, 0xff, 0xa0, 0x1a, 0x86, 0x36, 0x92, 0xea, 0x99,
- 0x1f, 0x6e, 0xce, 0xce, 0xfc, 0x34, 0xd0, 0x0b, 0xf8, 0x0d, 0x13, 0x8c, 0xb1, 0x6a, 0xd8, 0xe7,
- 0xba, 0x6d, 0xeb, 0xa6, 0xe1, 0xe8, 0xc6, 0x58, 0xc3, 0x67, 0x1a, 0xd6, 0x8c, 0xbe, 0xe6, 0x7c,
- 0x52, 0xb1, 0xa1, 0x1b, 0x43, 0xa9, 0x89, 0x8e, 0xe1, 0x88, 0x87, 0xde, 0x1f, 0xeb, 0x17, 0xea,
- 0x98, 0x29, 0xa6, 0x66, 0x5a, 0x48, 0xe6, 0x45, 0xe2, 0x58, 0xd8, 0xec, 0x6b, 0xb6, 0xcd, 0xf6,
- 0xab, 0x61, 0x6c, 0x62, 0x09, 0x50, 0x0f, 0x9e, 0xe6, 0xe3, 0xfa, 0xa8, 0x7d, 0x76, 0xec, 0xcf,
- 0x46, 0x3f, 0xe3, 0xb6, 0xd1, 0x13, 0x38, 0x64, 0x1a, 0xfa, 0x78, 0xe2, 0x58, 0xa6, 0xc1, 0x72,
- 0x31, 0xb6, 0xa5, 0x7d, 0x74, 0x08, 0x9d, 0x2c, 0x53, 0x8c, 0x2e, 0x75, 0x36, 0xa1, 0xf7, 0x52,
- 0x37, 0xdd, 0x58, 0x0a, 0x59, 0x7d, 0x87, 0xed, 0x42, 0x3a, 0x48, 0xf3, 0x51, 0x10, 0xf4, 0x45,
- 0x54, 0x12, 0x42, 0xd0, 0xcd, 0x4b, 0xcf, 0x74, 0xe9, 0x10, 0x3d, 0x82, 0x83, 0x3c, 0xa6, 0x9e,
- 0xeb, 0x12, 0x52, 0xde, 0x41, 0x97, 0x9f, 0xaf, 0xe5, 0x46, 0xee, 0x82, 0x50, 0x12, 0x21, 0x09,
- 0xaa, 0x1f, 0xc9, 0x9d, 0xa8, 0x1c, 0xf6, 0xc9, 0xfa, 0xca, 0x85, 0xeb, 0xaf, 0xd2, 0x69, 0x9c,
- 0x2c, 0x94, 0xbf, 0x95, 0xb9, 0x3d, 0xce, 0xce, 0x15, 0x53, 0x56, 0x2d, 0xc2, 0xc2, 0x1a, 0x78,
- 0xd0, 0xec, 0x3a, 0x82, 0x3a, 0xbb, 0x96, 0xab, 0x58, 0x34, 0x31, 0xb1, 0x42, 0x7f, 0x00, 0xc8,
- 0x42, 0x8c, 0xe5, 0x3d, 0x7e, 0x23, 0x9e, 0x88, 0x1b, 0x51, 0xdc, 0x00, 0xce, 0x29, 0x2a, 0x5f,
- 0xe0, 0xc0, 0x1c, 0x8d, 0x0b, 0x31, 0xf6, 0xa0, 0xcd, 0xdb, 0xc3, 0x95, 0x3b, 0x25, 0x62, 0xb4,
- 0x76, 0x70, 0x1e, 0xca, 0xba, 0x0a, 0x5b, 0xf2, 0x9d, 0x54, 0x72, 0x5d, 0x25, 0x05, 0xef, 0x8b,
- 0x54, 0xf9, 0x4b, 0x19, 0x3a, 0x17, 0x24, 0x8a, 0xbd, 0x30, 0x10, 0x7b, 0x92, 0xa1, 0x71, 0x93,
- 0x00, 0x22, 0x27, 0xe9, 0x92, 0xe5, 0xeb, 0x72, 0xe5, 0xf9, 0xb3, 0xb1, 0xb7, 0xc8, 0xde, 0x3a,
- 0x19, 0xc0, 0x7a, 0xe3, 0x94, 0xcf, 0x89, 0x0f, 0x6e, 0x7c, 0x2d, 0xbc, 0xe4, 0x10, 0xc6, 0x9e,
- 0x7b, 0x54, 0x04, 0x91, 0x4c, 0xf1, 0x35, 0xa0, 0xbc, 0x83, 0xe6, 0x28, 0x9c, 0x8f, 0xc8, 0x0d,
- 0xf1, 0xd9, 0x09, 0xfa, 0xec, 0x43, 0xf8, 0x4f, 0x16, 0x6c, 0x07, 0x53, 0xd7, 0xf7, 0xc5, 0x49,
- 0x34, 0xb1, 0x58, 0x29, 0x1a, 0x34, 0x31, 0x89, 0x97, 0x61, 0x10, 0x13, 0xf4, 0x0c, 0xda, 0x31,
- 0xb7, 0xe7, 0x4c, 0xc3, 0x19, 0x11, 0x0f, 0x11, 0x48, 0xa0, 0x7e, 0x38, 0x23, 0x6c, 0x73, 0x0b,
- 0x12, 0xc7, 0xee, 0x3c, 0xdd, 0x40, 0xba, 0x54, 0xfe, 0x5a, 0x86, 0x36, 0xeb, 0xfe, 0x69, 0xe2,
- 0x5f, 0x40, 0xdd, 0x0c, 0x56, 0x98, 0x7c, 0x11, 0x7d, 0xf4, 0x30, 0xd7, 0xfe, 0x12, 0x15, 0x2c,
- 0x14, 0xd0, 0x4f, 0xb0, 0x6f, 0xaf, 0x2e, 0x55, 0x3e, 0x7f, 0x2f, 0x5c, 0x9f, 0x5b, 0xee, 0x66,
- 0xe7, 0x9d, 0x89, 0x78, 0x2f, 0xc2, 0x05, 0x55, 0x56, 0x64, 0xc3, 0x28, 0x5c, 0x2d, 0xd3, 0x29,
- 0x99, 0xa4, 0xad, 0x80, 0x29, 0x1f, 0xa1, 0x76, 0xe6, 0x87, 0xb7, 0x31, 0xfa, 0x0e, 0xe0, 0xca,
- 0x0f, 0x6f, 0x9d, 0x69, 0xb8, 0x0a, 0x68, 0xda, 0xfd, 0x18, 0xd2, 0x67, 0x00, 0xfa, 0x35, 0xd4,
- 0xd8, 0x82, 0x8d, 0x5a, 0x56, 0x6f, 0x9d, 0xd3, 0xf4, 0x7d, 0xcc, 0xd8, 0x38, 0x91, 0x29, 0xcf,
- 0xa0, 0xc1, 0x4e, 0x2b, 0x5c, 0x51, 0x96, 0xe6, 0x19, 0xf1, 0xdd, 0x3b, 0x61, 0x29, 0x59, 0x28,
- 0x0d, 0xa8, 0x69, 0x8b, 0x25, 0xbd, 0x7b, 0xf9, 0x1a, 0xba, 0xc5, 0xd0, 0x51, 0x13, 0xf6, 0xfe,
- 0x64, 0xea, 0x86, 0x54, 0x42, 0x2d, 0xa8, 0x8d, 0x34, 0xf5, 0x42, 0x93, 0xca, 0x08, 0xa0, 0xce,
- 0xc0, 0x8b, 0xb7, 0x52, 0xe5, 0xcd, 0xbf, 0x00, 0x6a, 0xef, 0xdf, 0xdb, 0xde, 0x02, 0xbd, 0x82,
- 0x86, 0xa8, 0x2a, 0xb4, 0x2f, 0xf2, 0xc0, 0xad, 0x1e, 0x3f, 0x16, 0xab, 0x42, 0xcd, 0x29, 0x25,
- 0xf4, 0x1a, 0xda, 0x36, 0xa1, 0x59, 0x09, 0x1c, 0x08, 0xb5, 0x14, 0x38, 0xde, 0x04, 0x94, 0x12,
- 0x7a, 0x0e, 0xf5, 0x21, 0xa1, 0xec, 0x79, 0x5d, 0x74, 0x91, 0x0d, 0x2a, 0x9f, 0x2a, 0x25, 0xf4,
- 0x3d, 0x80, 0x15, 0xde, 0x92, 0x28, 0x0c, 0xb6, 0x35, 0x53, 0xa3, 0x69, 0xfd, 0x28, 0x25, 0x74,
- 0x0a, 0x6d, 0xfb, 0x7a, 0x45, 0x67, 0xe1, 0xed, 0xc3, 0xf4, 0x7f, 0x07, 0x2d, 0x4c, 0x2e, 0xc3,
- 0x90, 0x3e, 0x48, 0x9b, 0xe5, 0x94, 0x86, 0xcb, 0x39, 0xb6, 0xfa, 0x6c, 0x30, 0x92, 0xe8, 0x7f,
- 0x53, 0xde, 0xc0, 0x81, 0x4d, 0xdd, 0x88, 0x7e, 0x0d, 0xe7, 0x47, 0x38, 0xc4, 0x24, 0xde, 0x60,
- 0xa5, 0x13, 0x59, 0x1c, 0xff, 0x2e, 0xde, 0x8b, 0x24, 0xa3, 0xc6, 0x04, 0x6d, 0x57, 0xfb, 0x71,
- 0x6e, 0xfe, 0x2b, 0x25, 0xf4, 0x5b, 0xf6, 0x46, 0xa2, 0xfc, 0x9d, 0x50, 0x0c, 0xa7, 0xbd, 0x56,
- 0x8b, 0x93, 0x7c, 0x0e, 0x09, 0xcd, 0x5e, 0x09, 0xbb, 0x43, 0x4f, 0xc5, 0x3c, 0xf4, 0x2e, 0xb3,
- 0x1b, 0xac, 0x32, 0xca, 0x8e, 0x50, 0x76, 0xf0, 0xde, 0xe6, 0xce, 0x6d, 0x77, 0xfc, 0xf7, 0xe4,
- 0x56, 0x90, 0x54, 0xdf, 0xdf, 0xb1, 0x99, 0x1d, 0x9c, 0x9f, 0xe0, 0x30, 0xe7, 0x28, 0x36, 0x03,
- 0xcb, 0x34, 0x32, 0x77, 0xeb, 0x97, 0xca, 0x6e, 0x77, 0x59, 0x29, 0x3e, 0x38, 0xc4, 0xd7, 0xd0,
- 0x15, 0x9c, 0x07, 0x47, 0xf8, 0x0e, 0xa4, 0xb5, 0x9b, 0xaf, 0x0a, 0xf0, 0xf7, 0xb0, 0x2f, 0xea,
- 0x26, 0x79, 0x44, 0x3f, 0x2c, 0xc4, 0xb7, 0xd0, 0x16, 0x2c, 0xfe, 0xb6, 0x7e, 0x18, 0xe9, 0x3d,
- 0x3c, 0xb1, 0xf9, 0x39, 0xf3, 0x69, 0xa7, 0x07, 0x33, 0x6f, 0xea, 0xb2, 0x4e, 0x83, 0x8e, 0xd6,
- 0xf4, 0xfc, 0x20, 0xfc, 0x19, 0x1b, 0x3e, 0xbd, 0xd7, 0x46, 0x71, 0x98, 0xee, 0xb2, 0xf1, 0x3d,
- 0x34, 0x87, 0x84, 0x26, 0xfd, 0x75, 0x47, 0xe4, 0x69, 0xb2, 0xb9, 0x02, 0xcf, 0xed, 0x41, 0xff,
- 0xda, 0x0d, 0xe6, 0x84, 0x8d, 0x8a, 0xe4, 0xbd, 0x8e, 0x84, 0x4a, 0x6e, 0x78, 0xec, 0x72, 0xf4,
- 0x11, 0xbe, 0x49, 0x0a, 0x7b, 0xfb, 0xed, 0xbe, 0xc3, 0xef, 0xb7, 0x6b, 0x68, 0x4b, 0x5f, 0x29,
- 0x5d, 0xd6, 0xf9, 0x1f, 0x1a, 0x6f, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x62, 0x43, 0x1a, 0x58,
- 0x2f, 0x11, 0x00, 0x00,
+ // 1930 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0x41, 0x72, 0xdb, 0xca,
+ 0x11, 0x15, 0x49, 0x51, 0x24, 0x9b, 0x22, 0x05, 0x8d, 0x2d, 0x7d, 0x94, 0xac, 0x1f, 0xab, 0x10,
+ 0x27, 0x65, 0xbb, 0xf2, 0xe5, 0x6f, 0x39, 0xf9, 0xb1, 0x97, 0x30, 0x09, 0xd1, 0xf8, 0xa2, 0x00,
+ 0xd4, 0x80, 0x94, 0xcb, 0x95, 0x05, 0x0b, 0x22, 0x46, 0x12, 0x2b, 0x20, 0x40, 0x03, 0x43, 0x29,
+ 0x3a, 0x40, 0xce, 0x90, 0x7d, 0x0e, 0x90, 0x4b, 0xe4, 0x02, 0x39, 0x41, 0xb2, 0xca, 0x01, 0x52,
+ 0xb9, 0x40, 0x6a, 0x06, 0x03, 0x10, 0x20, 0x21, 0x9b, 0x5e, 0x65, 0xc3, 0x42, 0xbf, 0xee, 0xd7,
+ 0xd3, 0xd3, 0xdd, 0xe8, 0x19, 0x10, 0xf6, 0x9c, 0xd9, 0xe4, 0xd5, 0xe5, 0x65, 0x34, 0x99, 0xc6,
+ 0xbf, 0xc7, 0xb3, 0x30, 0xa0, 0x01, 0xaa, 0x72, 0xe1, 0xe0, 0xc9, 0x6d, 0xe0, 0xd1, 0x1b, 0x67,
+ 0xc4, 0xc1, 0xe8, 0x55, 0x30, 0x23, 0x7e, 0xe0, 0xd1, 0xd8, 0xe6, 0xe0, 0x28, 0xaf, 0xa4, 0x64,
+ 0x7c, 0xc3, 0x9e, 0xaf, 0x26, 0x1e, 0x89, 0x2d, 0x94, 0x7f, 0x95, 0xa1, 0x66, 0x99, 0x86, 0x15,
+ 0x84, 0x14, 0xb5, 0xa1, 0xac, 0x77, 0xe5, 0xd2, 0x51, 0xe9, 0x79, 0x15, 0x97, 0xf5, 0x2e, 0x3a,
+ 0x84, 0x86, 0x39, 0x23, 0xa1, 0x4d, 0x1d, 0x4a, 0xe4, 0xf2, 0x51, 0xe9, 0x79, 0x03, 0x2f, 0x00,
+ 0xf4, 0x0c, 0x5a, 0xba, 0x4f, 0x49, 0xe8, 0x3b, 0x5e, 0x6c, 0x51, 0xe1, 0x16, 0x79, 0x10, 0x1d,
+ 0x41, 0xd3, 0x72, 0xc6, 0x7f, 0x24, 0xb4, 0x13, 0xcc, 0x7d, 0x2a, 0x6f, 0x1e, 0x95, 0x9e, 0x6f,
+ 0xe2, 0x2c, 0x84, 0x4e, 0x61, 0x47, 0xf5, 0xbc, 0x60, 0xec, 0x50, 0xe2, 0x9a, 0xfe, 0x5c, 0x77,
+ 0x23, 0xb9, 0x7a, 0x54, 0x79, 0xde, 0x3c, 0x39, 0x3c, 0x8e, 0xb7, 0x6b, 0x05, 0x7e, 0x6a, 0x80,
+ 0x49, 0x14, 0xcc, 0xc3, 0x31, 0x89, 0xf0, 0x32, 0x09, 0xfd, 0x0c, 0xbb, 0x29, 0xd4, 0x23, 0x53,
+ 0xb6, 0xa3, 0x48, 0xde, 0x5a, 0xc3, 0xd3, 0x2a, 0x2d, 0xe7, 0x8b, 0x3f, 0xb0, 0xa8, 0x6a, 0xdf,
+ 0xe4, 0x2b, 0xa1, 0x29, 0x67, 0xb0, 0x57, 0x68, 0x8b, 0x14, 0xd8, 0xb6, 0x49, 0x38, 0x71, 0x3c,
+ 0x63, 0x3e, 0xbd, 0x24, 0x21, 0x4f, 0x7c, 0x03, 0xe7, 0x30, 0x5e, 0x12, 0x97, 0xe7, 0x9e, 0x95,
+ 0xc4, 0x55, 0x7e, 0x0f, 0x35, 0xc3, 0xd0, 0xbf, 0xbd, 0x5a, 0xca, 0xbf, 0x4b, 0x50, 0x31, 0xbd,
+ 0x55, 0xd6, 0x72, 0x10, 0xe5, 0x82, 0x20, 0x72, 0x9e, 0x2b, 0x5f, 0xed, 0x83, 0xcd, 0xa2, 0x3e,
+ 0x60, 0xeb, 0x5a, 0x72, 0x8d, 0xab, 0xca, 0xba, 0x85, 0x5e, 0x42, 0x5d, 0x6c, 0x24, 0x29, 0x77,
+ 0x5b, 0x24, 0x56, 0xc0, 0x38, 0xd5, 0x33, 0x5b, 0xd1, 0xa2, 0x49, 0x41, 0x13, 0x5b, 0x01, 0xe3,
+ 0x54, 0xaf, 0xfc, 0xb9, 0x04, 0xb2, 0xe9, 0xd1, 0x95, 0x74, 0x0f, 0xee, 0x67, 0x04, 0xbd, 0x85,
+ 0x4d, 0x7a, 0x3f, 0x23, 0x7c, 0xfb, 0xed, 0x93, 0x67, 0xc2, 0xc9, 0x43, 0xe6, 0xc7, 0xec, 0x07,
+ 0x73, 0x86, 0xf2, 0x0a, 0x36, 0xb9, 0x87, 0x26, 0xd4, 0x86, 0xc6, 0x99, 0x61, 0x7e, 0x34, 0xa4,
+ 0x0d, 0xb4, 0x0d, 0x75, 0xb5, 0xdf, 0x37, 0x3b, 0x23, 0xbd, 0x2b, 0x95, 0x98, 0xd4, 0xd3, 0xce,
+ 0x47, 0x96, 0x89, 0x07, 0x52, 0x59, 0xf9, 0x5b, 0x09, 0x1e, 0x17, 0x39, 0x46, 0x28, 0xf6, 0x24,
+ 0xaa, 0x1d, 0x7b, 0x3d, 0x84, 0x86, 0x15, 0xf8, 0x6c, 0x03, 0xa2, 0xd8, 0x2d, 0xbc, 0x00, 0xd0,
+ 0x63, 0xa8, 0xf2, 0x16, 0xe7, 0xa9, 0x6f, 0xe1, 0x58, 0x40, 0xfb, 0xb0, 0xc5, 0xf4, 0x46, 0xc0,
+ 0xf3, 0xdd, 0xc2, 0x42, 0x42, 0xbf, 0x00, 0x48, 0xd6, 0xd2, 0x5d, 0xb9, 0xca, 0x0b, 0x9d, 0x41,
+ 0x18, 0xef, 0xd4, 0x0b, 0xee, 0x74, 0x57, 0xde, 0xe2, 0xef, 0xa2, 0x90, 0x14, 0x0c, 0x7b, 0x45,
+ 0xf1, 0x46, 0xe8, 0x1d, 0x34, 0xc2, 0x44, 0x90, 0x4b, 0x3c, 0xfd, 0x4f, 0xbe, 0x90, 0x39, 0xbc,
+ 0xb0, 0x56, 0xfe, 0x5b, 0x81, 0x8a, 0x69, 0x0c, 0xff, 0x6f, 0x4d, 0x97, 0xc9, 0x6b, 0x57, 0xa4,
+ 0x62, 0x01, 0x30, 0xed, 0x87, 0x3b, 0xd5, 0x75, 0x43, 0x12, 0x45, 0x72, 0x3d, 0x5e, 0x21, 0x05,
+ 0x32, 0xf9, 0x6d, 0x70, 0x62, 0x92, 0xdf, 0x97, 0x50, 0x8f, 0x48, 0x78, 0x3b, 0x61, 0xd9, 0x80,
+ 0x5c, 0x33, 0xda, 0x31, 0x8c, 0x53, 0x3d, 0xea, 0xc2, 0xf7, 0xfa, 0xd4, 0xb9, 0x26, 0x76, 0x70,
+ 0x45, 0xef, 0x9c, 0x90, 0x68, 0x7f, 0x9a, 0x91, 0x31, 0x25, 0xae, 0x4d, 0xc6, 0x74, 0x12, 0xf8,
+ 0x91, 0xdc, 0xe4, 0xae, 0xbf, 0x6c, 0xb4, 0xe2, 0x05, 0x93, 0x31, 0x99, 0xdc, 0x66, 0xbc, 0x6c,
+ 0x17, 0x78, 0x59, 0x36, 0x42, 0x3f, 0xc2, 0x23, 0x75, 0x4c, 0x27, 0xb7, 0x84, 0x9b, 0x69, 0x3e,
+ 0x9d, 0xd0, 0x7b, 0xdd, 0x95, 0x5b, 0x9c, 0x5b, 0xa4, 0x42, 0x3f, 0xc1, 0x7e, 0x27, 0x98, 0x4e,
+ 0x27, 0x94, 0x12, 0x37, 0x4f, 0x6a, 0x73, 0xd2, 0x03, 0x5a, 0xe5, 0x3f, 0x65, 0xa8, 0x89, 0x5c,
+ 0xb0, 0x6e, 0x37, 0x9c, 0x69, 0xda, 0xed, 0xec, 0x39, 0x9f, 0xf7, 0xf2, 0x72, 0xde, 0xe3, 0x6e,
+ 0xb7, 0x7d, 0x51, 0xf3, 0x58, 0x60, 0x7e, 0xec, 0x81, 0x73, 0xcd, 0xcb, 0x5c, 0xc5, 0xfc, 0x99,
+ 0x61, 0x1d, 0x86, 0xc5, 0x85, 0xe5, 0xcf, 0xac, 0xfb, 0x0d, 0x42, 0xdc, 0x48, 0x73, 0x66, 0x81,
+ 0xc7, 0x3b, 0xbc, 0x8e, 0x33, 0x08, 0x5b, 0x9b, 0x4b, 0xdd, 0x9b, 0xf1, 0x8c, 0x4f, 0xa3, 0x3a,
+ 0x5e, 0x00, 0xa9, 0x56, 0xbf, 0x9e, 0xce, 0x78, 0x47, 0x24, 0x5a, 0x06, 0x20, 0x19, 0x6a, 0xe2,
+ 0x80, 0x10, 0x2d, 0x91, 0x88, 0x6c, 0x55, 0xee, 0x3e, 0x6e, 0x45, 0xe0, 0x81, 0x67, 0x10, 0xe6,
+ 0x97, 0xf9, 0x8f, 0xd5, 0xcd, 0x78, 0xc7, 0x29, 0xb0, 0xda, 0xcb, 0xdb, 0x0f, 0xf4, 0xb2, 0xde,
+ 0x3b, 0xb7, 0x62, 0x8b, 0x56, 0xec, 0x23, 0x05, 0x14, 0x07, 0x1e, 0x9b, 0xc6, 0x70, 0x10, 0x3a,
+ 0x57, 0x57, 0x93, 0xb1, 0x3d, 0xbe, 0x21, 0xee, 0xdc, 0x23, 0x61, 0x84, 0x74, 0xd8, 0xa1, 0x0c,
+ 0x5c, 0x40, 0xbc, 0x14, 0xcd, 0x93, 0xa7, 0xc7, 0xb9, 0xcb, 0xc0, 0x0a, 0x13, 0x2f, 0xf3, 0x94,
+ 0xe7, 0xb0, 0x69, 0x1a, 0xc3, 0x08, 0x1d, 0x41, 0x75, 0x42, 0xc9, 0x34, 0x99, 0x05, 0x90, 0xcc,
+ 0x02, 0x63, 0x88, 0x63, 0x85, 0xf2, 0x23, 0xd4, 0xed, 0xe4, 0x15, 0x78, 0x96, 0xb7, 0x5e, 0x7e,
+ 0x57, 0x52, 0x06, 0x30, 0x3e, 0xf9, 0x3c, 0x27, 0x11, 0x5d, 0xe7, 0x60, 0x54, 0x5e, 0x02, 0x58,
+ 0xa6, 0x91, 0x30, 0x72, 0x03, 0xb4, 0xb4, 0x34, 0x40, 0x95, 0x7f, 0x56, 0xa0, 0xa1, 0x7a, 0x4e,
+ 0x38, 0x65, 0xc3, 0x56, 0xf9, 0x47, 0x05, 0xaa, 0xec, 0x21, 0x42, 0x35, 0xa8, 0xf4, 0x4d, 0x5b,
+ 0xda, 0x40, 0x6d, 0x80, 0xee, 0x27, 0xdd, 0xe8, 0x8d, 0x7a, 0xaa, 0x6d, 0x49, 0x25, 0xd4, 0x82,
+ 0x86, 0x69, 0x0c, 0x47, 0x6a, 0x5f, 0xc5, 0xe7, 0x52, 0x19, 0x7d, 0x07, 0x8f, 0x98, 0x68, 0x0f,
+ 0x54, 0x3c, 0x18, 0x5a, 0xa3, 0x53, 0x55, 0xef, 0x0f, 0xb1, 0x26, 0x55, 0xd0, 0x3e, 0x20, 0xae,
+ 0xd0, 0x7b, 0x86, 0xda, 0x1f, 0x75, 0xb5, 0x1e, 0x56, 0xbb, 0x9a, 0xb4, 0x99, 0x10, 0xba, 0x58,
+ 0x3f, 0x1d, 0x8c, 0xcc, 0xd3, 0xd1, 0x47, 0xdd, 0xe8, 0x9a, 0x1f, 0xa5, 0x2a, 0x3a, 0x04, 0x99,
+ 0x29, 0xfa, 0xa6, 0x6d, 0x33, 0xdc, 0x3c, 0xef, 0xe8, 0xa3, 0xce, 0x07, 0xd5, 0x30, 0xb4, 0xbe,
+ 0xb4, 0x95, 0xae, 0xc3, 0xdd, 0xd9, 0xe9, 0x3a, 0x35, 0xf4, 0x02, 0x7e, 0xc5, 0x14, 0x03, 0xac,
+ 0x1a, 0xf6, 0xb9, 0x6e, 0xdb, 0xba, 0x69, 0x8c, 0x74, 0x63, 0xa0, 0xe1, 0x53, 0x0d, 0x6b, 0x46,
+ 0x47, 0x1b, 0x7d, 0x54, 0xb1, 0xa1, 0x1b, 0x3d, 0xa9, 0x8e, 0x0e, 0x60, 0x9f, 0x87, 0xde, 0x19,
+ 0xe8, 0x17, 0xea, 0x80, 0x19, 0x26, 0x6e, 0x1a, 0x48, 0xe6, 0x4d, 0x32, 0xb2, 0xb0, 0xd9, 0xd1,
+ 0x6c, 0x9b, 0xed, 0x57, 0xc3, 0xd8, 0xc4, 0x12, 0xa0, 0x23, 0x38, 0xcc, 0xc6, 0x75, 0xa6, 0x7d,
+ 0x1a, 0xd9, 0x9f, 0x8c, 0x4e, 0xca, 0x6d, 0xa2, 0x3d, 0xd8, 0x65, 0x16, 0xfa, 0x60, 0x38, 0xb2,
+ 0x4c, 0x83, 0xe5, 0x62, 0x60, 0x4b, 0xdb, 0x68, 0x17, 0x5a, 0x69, 0xa6, 0x18, 0x5d, 0x6a, 0x2d,
+ 0x43, 0xef, 0xa5, 0x76, 0xb2, 0xb1, 0x04, 0xb2, 0x3a, 0x23, 0xb6, 0x0b, 0x69, 0x27, 0xc9, 0x47,
+ 0x4e, 0xd1, 0x11, 0x51, 0x49, 0x08, 0x41, 0x3b, 0xab, 0x3d, 0xd5, 0xa5, 0x5d, 0xf4, 0x08, 0x76,
+ 0xb2, 0x98, 0x7a, 0xae, 0x4b, 0x48, 0x79, 0x0b, 0x6d, 0x5e, 0x5f, 0xcb, 0x09, 0x9d, 0x29, 0xa1,
+ 0x24, 0x44, 0x12, 0x54, 0xce, 0xc8, 0xbd, 0xe8, 0x1c, 0xf6, 0xc8, 0xe6, 0xca, 0x85, 0xe3, 0xcd,
+ 0x93, 0xab, 0x51, 0x2c, 0x28, 0x7f, 0x2d, 0x71, 0x7f, 0x9c, 0x9d, 0x69, 0xa6, 0xb4, 0x5b, 0x84,
+ 0x87, 0x05, 0xb0, 0xd6, 0xd9, 0xb5, 0x0f, 0x5b, 0xec, 0xb5, 0x9c, 0x47, 0x62, 0x88, 0x09, 0x09,
+ 0xfd, 0x0e, 0x20, 0x0d, 0x31, 0x92, 0x37, 0xf9, 0x1b, 0xb1, 0x27, 0xde, 0x88, 0xfc, 0x06, 0x70,
+ 0xc6, 0x50, 0xf9, 0x0c, 0x3b, 0x66, 0x7f, 0x90, 0x8b, 0xf1, 0x08, 0x9a, 0x7c, 0x3c, 0x5c, 0x39,
+ 0x63, 0x22, 0x8e, 0xd6, 0x16, 0xce, 0x42, 0xe9, 0x54, 0x61, 0x22, 0xdf, 0x49, 0x39, 0x33, 0x55,
+ 0x12, 0xf0, 0xa1, 0x48, 0xd9, 0x35, 0xaa, 0x75, 0x41, 0xc2, 0x68, 0x12, 0xf8, 0x62, 0x4f, 0x32,
+ 0xd4, 0x6e, 0x63, 0x40, 0xe4, 0x24, 0x11, 0x59, 0xbe, 0x2e, 0xe7, 0x13, 0xcf, 0x1d, 0x4c, 0xa6,
+ 0xe9, 0xc5, 0x33, 0x05, 0xd8, 0x6c, 0x1c, 0xf3, 0x73, 0xe2, 0x83, 0x13, 0xdd, 0x88, 0x55, 0x32,
+ 0x08, 0x63, 0x5f, 0x4f, 0xa8, 0x08, 0x22, 0x3e, 0xc5, 0x17, 0x80, 0xf2, 0x16, 0xea, 0xfd, 0xe0,
+ 0xba, 0x4f, 0x6e, 0x89, 0xc7, 0x2a, 0xe8, 0xb1, 0x07, 0xb1, 0x7e, 0x2c, 0xb0, 0x1d, 0x8c, 0x1d,
+ 0xcf, 0x13, 0x95, 0xa8, 0x63, 0x21, 0x29, 0x1a, 0xd4, 0x31, 0x89, 0x66, 0x81, 0x1f, 0x11, 0xf4,
+ 0x14, 0x9a, 0x11, 0xf7, 0x37, 0x1a, 0x07, 0x2e, 0x11, 0x17, 0x11, 0x88, 0xa1, 0x4e, 0xe0, 0x12,
+ 0xb6, 0xb9, 0x29, 0x89, 0x22, 0xe7, 0x3a, 0xd9, 0x40, 0x22, 0x2a, 0x7f, 0x29, 0x41, 0x93, 0x4d,
+ 0xff, 0x24, 0xf1, 0x2f, 0x60, 0xcb, 0xf4, 0xe7, 0x98, 0x7c, 0x16, 0x73, 0x74, 0x37, 0x33, 0xfe,
+ 0x62, 0x13, 0x2c, 0x0c, 0xd0, 0x3b, 0xd8, 0xb6, 0xe7, 0x97, 0x2a, 0x3f, 0x7f, 0x2f, 0x1c, 0x8f,
+ 0x7b, 0x6e, 0xa7, 0xf5, 0x4e, 0x55, 0x7c, 0x16, 0xe1, 0x9c, 0x29, 0x6b, 0xb2, 0x5e, 0x18, 0xcc,
+ 0x67, 0xc9, 0x29, 0x19, 0xa7, 0x2d, 0x87, 0x29, 0x67, 0x50, 0x65, 0x57, 0xb7, 0x08, 0x7d, 0x0f,
+ 0x70, 0xe5, 0x05, 0x77, 0xa3, 0x31, 0xff, 0xc2, 0x12, 0xd3, 0x8f, 0x21, 0xf1, 0xf7, 0xd5, 0x2f,
+ 0xa1, 0xca, 0x04, 0x76, 0xd4, 0xb2, 0x7e, 0x6b, 0x1d, 0x27, 0x9f, 0x88, 0x8c, 0x8d, 0x63, 0x9d,
+ 0xf2, 0x14, 0x6a, 0xac, 0x5a, 0xc1, 0x9c, 0xb2, 0x34, 0xbb, 0xc4, 0x73, 0xee, 0x85, 0xa7, 0x58,
+ 0x50, 0x6a, 0x50, 0xd5, 0xa6, 0x33, 0x7a, 0xff, 0xf2, 0x35, 0xb4, 0xf3, 0xa1, 0xa3, 0x3a, 0x6c,
+ 0xfe, 0x6c, 0xea, 0xec, 0x42, 0xdc, 0x80, 0x6a, 0x5f, 0x53, 0x2f, 0x34, 0xa9, 0x84, 0x00, 0xb6,
+ 0x18, 0x78, 0xf1, 0x46, 0x2a, 0x9f, 0xfc, 0xbd, 0x09, 0xd5, 0xf7, 0xef, 0xed, 0xc9, 0x14, 0xbd,
+ 0x82, 0x9a, 0xe8, 0x2a, 0xb4, 0x2d, 0xf2, 0xc0, 0xbd, 0x1e, 0x3c, 0x16, 0x52, 0xae, 0xe7, 0x94,
+ 0x0d, 0xf4, 0x1a, 0x9a, 0x36, 0xa1, 0x69, 0x0b, 0xec, 0x08, 0xb3, 0x04, 0x38, 0x58, 0x06, 0x94,
+ 0x0d, 0xf4, 0x0c, 0xb6, 0x7a, 0x84, 0xb2, 0x6f, 0x9d, 0xfc, 0x12, 0xb0, 0xb8, 0xb4, 0x2a, 0x1b,
+ 0xe8, 0x0f, 0x20, 0xc7, 0x56, 0x05, 0x37, 0xde, 0xa7, 0x5f, 0xf9, 0x30, 0x38, 0x38, 0xfc, 0x82,
+ 0x41, 0xa4, 0x6c, 0xa0, 0x1f, 0x00, 0xac, 0xe0, 0x8e, 0x84, 0x81, 0xbf, 0x1a, 0x46, 0x12, 0x71,
+ 0xd2, 0x9c, 0xca, 0x06, 0x3a, 0x86, 0xa6, 0x7d, 0x33, 0xa7, 0x6e, 0x70, 0xb7, 0x9e, 0xfd, 0x6f,
+ 0xa0, 0x81, 0xc9, 0x65, 0x10, 0xd0, 0xb5, 0xac, 0x59, 0xc1, 0x68, 0x30, 0xbb, 0xc6, 0x56, 0x87,
+ 0x9d, 0xba, 0x24, 0xfc, 0x3a, 0xe5, 0x04, 0x76, 0x6c, 0xea, 0x84, 0xf4, 0x5b, 0x38, 0x3f, 0xc1,
+ 0x2e, 0x26, 0xd1, 0x12, 0x2b, 0x39, 0xee, 0x45, 0x6f, 0x15, 0xf1, 0x5e, 0xc4, 0xe5, 0x32, 0x86,
+ 0x68, 0xf5, 0x55, 0x3a, 0xc8, 0x5c, 0x2e, 0x94, 0x0d, 0xf4, 0x6b, 0x76, 0x01, 0xa3, 0xfc, 0x12,
+ 0x92, 0x0f, 0xa7, 0xb9, 0x30, 0x8b, 0xe2, 0x7c, 0xf6, 0x08, 0x4d, 0xaf, 0x20, 0xc5, 0xa1, 0x27,
+ 0x6a, 0x1e, 0x7a, 0x9b, 0xf9, 0xf5, 0xe7, 0x29, 0xa5, 0x20, 0x94, 0x02, 0xde, 0x9b, 0x4c, 0xdd,
+ 0x8a, 0xe3, 0x7f, 0x20, 0xb7, 0x82, 0xa4, 0x7a, 0x5e, 0xc1, 0x66, 0x0a, 0x38, 0xef, 0x60, 0x37,
+ 0xb3, 0x50, 0x64, 0xfa, 0x96, 0x69, 0xa4, 0xcb, 0x2d, 0xae, 0x41, 0xc5, 0xcb, 0xa5, 0xad, 0xb8,
+ 0x76, 0x88, 0xaf, 0xa1, 0x2d, 0x38, 0x6b, 0x47, 0xf8, 0x16, 0xa4, 0xc5, 0x32, 0xdf, 0x14, 0xe0,
+ 0x6f, 0x61, 0x5b, 0xf4, 0x4d, 0x7c, 0x43, 0x5f, 0x2f, 0xc4, 0x37, 0xd0, 0x14, 0x2c, 0x7e, 0x71,
+ 0x5f, 0x8f, 0xf4, 0x1e, 0xf6, 0x6c, 0x5e, 0x67, 0x7e, 0x94, 0xea, 0xbe, 0x3b, 0x19, 0x3b, 0x6c,
+ 0x8c, 0xa1, 0xfd, 0x05, 0x3d, 0x7b, 0xca, 0x7e, 0xc1, 0x07, 0x7b, 0xf1, 0x1f, 0xf0, 0x91, 0x3f,
+ 0xa9, 0x8b, 0x7c, 0xfc, 0x00, 0xf5, 0x1e, 0xa1, 0xf1, 0xf0, 0x2e, 0x88, 0x3c, 0x49, 0x36, 0x37,
+ 0xe0, 0xb9, 0xdd, 0xe9, 0xdc, 0x38, 0xfe, 0x35, 0x61, 0xe7, 0x50, 0xfc, 0x31, 0x80, 0x84, 0x49,
+ 0xe6, 0x64, 0x2a, 0x5a, 0xe8, 0x0c, 0xbe, 0x8b, 0x1b, 0x7b, 0xf5, 0xc3, 0xa0, 0x60, 0xdd, 0x27,
+ 0x0b, 0x68, 0xc5, 0x5e, 0xd9, 0xb8, 0xdc, 0xe2, 0x7f, 0x18, 0xbe, 0xf9, 0x5f, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x86, 0x40, 0xa9, 0x75, 0x8f, 0x14, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -1456,6 +1751,7 @@
SetLogLevel(ctx context.Context, in *LogLevel, opts ...grpc.CallOption) (*LogLevel, error)
// Get current status of OLT
GetOlt(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Olt, error)
+ GetOltAllocatedResources(ctx context.Context, in *OltAllocatedResourceType, opts ...grpc.CallOption) (*OltAllocatedResources, error)
// Poweron OLT
PoweronOlt(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Response, error)
// Shutdown OLT
@@ -1539,6 +1835,15 @@
return out, nil
}
+func (c *bBSimClient) GetOltAllocatedResources(ctx context.Context, in *OltAllocatedResourceType, opts ...grpc.CallOption) (*OltAllocatedResources, error) {
+ out := new(OltAllocatedResources)
+ err := c.cc.Invoke(ctx, "/bbsim.BBSim/GetOltAllocatedResources", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
func (c *bBSimClient) PoweronOlt(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Response, error) {
out := new(Response)
err := c.cc.Invoke(ctx, "/bbsim.BBSim/PoweronOlt", in, out, opts...)
@@ -1754,6 +2059,7 @@
SetLogLevel(context.Context, *LogLevel) (*LogLevel, error)
// Get current status of OLT
GetOlt(context.Context, *Empty) (*Olt, error)
+ GetOltAllocatedResources(context.Context, *OltAllocatedResourceType) (*OltAllocatedResources, error)
// Poweron OLT
PoweronOlt(context.Context, *Empty) (*Response, error)
// Shutdown OLT
@@ -1815,6 +2121,9 @@
func (*UnimplementedBBSimServer) GetOlt(ctx context.Context, req *Empty) (*Olt, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetOlt not implemented")
}
+func (*UnimplementedBBSimServer) GetOltAllocatedResources(ctx context.Context, req *OltAllocatedResourceType) (*OltAllocatedResources, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method GetOltAllocatedResources not implemented")
+}
func (*UnimplementedBBSimServer) PoweronOlt(ctx context.Context, req *Empty) (*Response, error) {
return nil, status.Errorf(codes.Unimplemented, "method PoweronOlt not implemented")
}
@@ -1943,6 +2252,24 @@
return interceptor(ctx, in, info, handler)
}
+func _BBSim_GetOltAllocatedResources_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(OltAllocatedResourceType)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BBSimServer).GetOltAllocatedResources(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/bbsim.BBSim/GetOltAllocatedResources",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BBSimServer).GetOltAllocatedResources(ctx, req.(*OltAllocatedResourceType))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
func _BBSim_PoweronOlt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
@@ -2374,6 +2701,10 @@
Handler: _BBSim_GetOlt_Handler,
},
{
+ MethodName: "GetOltAllocatedResources",
+ Handler: _BBSim_GetOltAllocatedResources_Handler,
+ },
+ {
MethodName: "PoweronOlt",
Handler: _BBSim_PoweronOlt_Handler,
},
diff --git a/api/bbsim/bbsim.proto b/api/bbsim/bbsim.proto
index cf511b3..e6a253d 100644
--- a/api/bbsim/bbsim.proto
+++ b/api/bbsim/bbsim.proto
@@ -22,6 +22,18 @@
message PONPort {
int32 ID = 1;
string OperState = 2;
+ string InternalState = 3;
+ uint64 PacketCount = 4;
+ // ONU ID are reported by VOLTHA in the ActivateOnu call
+ repeated PonAllocatedResources AllocatedOnuIds = 5;
+ // these are the stored resource IDs as reported via OMCI
+ repeated PonAllocatedResources AllocatedGemPorts = 6;
+ repeated PonAllocatedResources AllocatedAllocIds = 7;
+}
+
+message PonAllocatedResources {
+ string SerialNumber = 1;
+ int32 Id = 2;
}
message NNIPort {
@@ -39,6 +51,28 @@
repeated PONPort PONPorts = 6;
}
+message OltAllocatedResourceType {
+ enum Type {
+ UNKNOWN = 0;
+ ALLOC_ID = 1;
+ GEM_PORT = 2;
+ }
+ Type type = 1;
+}
+
+message OltAllocatedResource {
+ string Type = 1;
+ uint32 PonPortId = 2;
+ uint32 OnuId = 3;
+ uint32 PortNo = 4;
+ int32 ResourceId = 5;
+ uint64 FlowId = 6;
+}
+
+message OltAllocatedResources {
+ repeated OltAllocatedResource resources = 1;
+}
+
message ONU {
int32 ID = 1;
string SerialNumber = 2;
@@ -199,6 +233,10 @@
// Get current status of OLT
rpc GetOlt (Empty) returns (Olt) {
}
+
+ rpc GetOltAllocatedResources (OltAllocatedResourceType) returns (OltAllocatedResources) {
+ }
+
// Poweron OLT
rpc PoweronOlt (Empty) returns (Response) {
}
diff --git a/go.mod b/go.mod
index 3b018ed..c6b5401 100644
--- a/go.mod
+++ b/go.mod
@@ -16,7 +16,7 @@
github.com/olekukonko/tablewriter v0.0.4
github.com/opencord/cordctl v0.0.0-20190909161711-01e9c1f04bf4
github.com/opencord/device-management-interface v0.11.0
- github.com/opencord/omci-lib-go v0.16.1
+ github.com/opencord/omci-lib-go v0.16.2
github.com/opencord/voltha-protos/v4 v4.0.15
github.com/pkg/errors v0.8.1 // indirect
github.com/sirupsen/logrus v1.4.2
diff --git a/go.sum b/go.sum
index 5718e49..79d8368 100644
--- a/go.sum
+++ b/go.sum
@@ -87,8 +87,8 @@
github.com/opencord/cordctl v0.0.0-20190909161711-01e9c1f04bf4/go.mod h1:/+3S0pwQUy7HeKnH0KfKp5W6hmh/LdZzuZTNT/m7vA4=
github.com/opencord/device-management-interface v0.11.0 h1:hoKjrkQWPr0IFXWn6HbGdV1Bk5v0gijM7P4VjUJvNh8=
github.com/opencord/device-management-interface v0.11.0/go.mod h1:G1owSqGBGaqllrwtjxfLTsy9EDsGhdhmqkJM3XOnPD0=
-github.com/opencord/omci-lib-go v0.16.1 h1:vYCqT3kN1bs2IfQXS3X/I106qY40zJfYimLLTcZ2QWY=
-github.com/opencord/omci-lib-go v0.16.1/go.mod h1:6OIHB14Ch5qGgHzwSWlMACtk5KFoLzQ4LAhdcy4jwvo=
+github.com/opencord/omci-lib-go v0.16.2 h1:ywbaZLrLV+6VgyXV3I1LysdErt5HQutcin1CaaGRkA4=
+github.com/opencord/omci-lib-go v0.16.2/go.mod h1:6OIHB14Ch5qGgHzwSWlMACtk5KFoLzQ4LAhdcy4jwvo=
github.com/opencord/voltha-protos/v4 v4.0.15 h1:TOKYlt/75w5pxT44HeYfo2kqKvqmHzVpUkiCHOMJTN8=
github.com/opencord/voltha-protos/v4 v4.0.15/go.mod h1:W/OIFIyvFh/C0vchRUuarIsMylEhzCRM9pNxLvkPtKc=
github.com/pierrec/lz4 v2.4.1+incompatible h1:mFe7ttWaflA46Mhqh+jUfjp2qTbPYxLB2/OyBppH9dg=
diff --git a/internal/bbsim/api/grpc_api_server.go b/internal/bbsim/api/grpc_api_server.go
index 01c7f4f..ec25a10 100644
--- a/internal/bbsim/api/grpc_api_server.go
+++ b/internal/bbsim/api/grpc_api_server.go
@@ -19,6 +19,7 @@
import (
"context"
"fmt"
+ "google.golang.org/grpc/status"
"strings"
"time"
@@ -67,9 +68,43 @@
}
for _, pon := range olt.Pons {
+
+ allocatedOnuIds := []*bbsim.PonAllocatedResources{}
+ allocatedAllocIds := []*bbsim.PonAllocatedResources{}
+ allocatedGemPorts := []*bbsim.PonAllocatedResources{}
+
+ for k, v := range pon.AllocatedOnuIds {
+ resource := &bbsim.PonAllocatedResources{
+ SerialNumber: common.OnuSnToString(v),
+ Id: int32(k),
+ }
+ allocatedOnuIds = append(allocatedOnuIds, resource)
+ }
+
+ for k, v := range pon.AllocatedGemPorts {
+ resource := &bbsim.PonAllocatedResources{
+ SerialNumber: common.OnuSnToString(v),
+ Id: int32(k),
+ }
+ allocatedGemPorts = append(allocatedGemPorts, resource)
+ }
+
+ for k, v := range pon.AllocatedAllocIds {
+ resource := &bbsim.PonAllocatedResources{
+ SerialNumber: common.OnuSnToString(v),
+ Id: int32(k),
+ }
+ allocatedAllocIds = append(allocatedAllocIds, resource)
+ }
+
p := bbsim.PONPort{
- ID: int32(pon.ID),
- OperState: pon.OperState.Current(),
+ ID: int32(pon.ID),
+ OperState: pon.OperState.Current(),
+ InternalState: pon.InternalState.Current(),
+ PacketCount: pon.PacketCount,
+ AllocatedOnuIds: allocatedOnuIds,
+ AllocatedAllocIds: allocatedAllocIds,
+ AllocatedGemPorts: allocatedGemPorts,
}
pons = append(pons, &p)
}
@@ -91,6 +126,48 @@
return &res, nil
}
+// takes a nested map and return a proto
+func resourcesMapToresourcesProto(resourceType bbsim.OltAllocatedResourceType_Type, resources map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool) *bbsim.OltAllocatedResources {
+ proto := &bbsim.OltAllocatedResources{
+ Resources: []*bbsim.OltAllocatedResource{},
+ }
+ for ponId, ponValues := range resources {
+ for onuId, onuValues := range ponValues {
+ for uniId, uniValues := range onuValues {
+ for allocId, flows := range uniValues {
+ for flow := range flows {
+ resource := &bbsim.OltAllocatedResource{
+ Type: resourceType.String(),
+ PonPortId: ponId,
+ OnuId: onuId,
+ PortNo: uniId,
+ ResourceId: allocId,
+ FlowId: flow,
+ }
+ proto.Resources = append(proto.Resources, resource)
+ }
+ }
+ }
+ }
+ }
+ return proto
+}
+
+func (s BBSimServer) GetOltAllocatedResources(ctx context.Context, req *bbsim.OltAllocatedResourceType) (*bbsim.OltAllocatedResources, error) {
+ o := devices.GetOLT()
+
+ switch req.Type {
+ case bbsim.OltAllocatedResourceType_UNKNOWN:
+ return nil, status.Errorf(codes.InvalidArgument, "resource-type-%s-is-invalid", req.Type)
+ case bbsim.OltAllocatedResourceType_ALLOC_ID:
+ return resourcesMapToresourcesProto(bbsim.OltAllocatedResourceType_ALLOC_ID, o.AllocIDs), nil
+ case bbsim.OltAllocatedResourceType_GEM_PORT:
+ return resourcesMapToresourcesProto(bbsim.OltAllocatedResourceType_GEM_PORT, o.GemPortIDs), nil
+ default:
+ return nil, status.Errorf(codes.InvalidArgument, "unkown-resource-type-%s", req.Type)
+ }
+}
+
func (s BBSimServer) PoweronOlt(ctx context.Context, req *bbsim.Empty) (*bbsim.Response, error) {
res := &bbsim.Response{}
o := devices.GetOLT()
diff --git a/internal/bbsim/devices/olt.go b/internal/bbsim/devices/olt.go
index f9ef936..87b9da4 100644
--- a/internal/bbsim/devices/olt.go
+++ b/internal/bbsim/devices/olt.go
@@ -90,6 +90,13 @@
OpenoltStream openolt.Openolt_EnableIndicationServer
enablePerf bool
+
+ // Allocated Resources
+ // this data are to verify that the openolt adapter does not duplicate resources
+ AllocIDsLock sync.RWMutex
+ AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
+ GemPortIDsLock sync.RWMutex
+ GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
}
var olt OltDevice
@@ -123,6 +130,8 @@
PortStatsInterval: options.Olt.PortStatsInterval,
dhcpServer: dhcp.NewDHCPServer(),
PreviouslyConnected: false,
+ AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
+ GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
}
if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
@@ -149,6 +158,10 @@
oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
},
"enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
+ "enter_deleted": func(e *fsm.Event) {
+ // remove all the resource allocations
+ olt.clearAllResources()
+ },
},
)
@@ -169,6 +182,11 @@
// create PON ports
for i := 0; i < olt.NumPon; i++ {
+
+ // initialize the resource maps for every PON Ports
+ olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
+ olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
+
p := CreatePonPort(&olt, uint32(i))
// create ONU devices
@@ -253,6 +271,12 @@
// in-band management
o.Nnis[0].OperState.SetState("down")
}
+
+ for ponId := range o.Pons {
+ // initialize the resource maps for every PON Ports
+ olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
+ olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
+ }
}
func (o *OltDevice) RestartOLT() error {
@@ -822,16 +846,14 @@
publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
pon, _ := o.GetPonById(onu.IntfId)
+
+ // Initialize the resource maps for this ONU
+ olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
+ olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
+
_onu, _ := pon.GetOnuBySn(onu.SerialNumber)
_onu.SetID(onu.OnuId)
- if err := _onu.OperState.Event("enable"); err != nil {
- oltLogger.WithFields(log.Fields{
- "IntfId": _onu.PonPortID,
- "OnuSn": _onu.Sn(),
- "OnuId": _onu.ID,
- }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
- }
if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
oltLogger.WithFields(log.Fields{
"IntfId": _onu.PonPortID,
@@ -845,7 +867,7 @@
return new(openolt.Empty), nil
}
-func (o *OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
+func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
oltLogger.Error("DeactivateOnu not implemented")
return new(openolt.Empty), nil
}
@@ -1056,6 +1078,21 @@
}
}
+ // validate that the flow reference correct IDs (Alloc, Gem)
+ if err := o.validateFlow(flow); err != nil {
+ oltLogger.WithFields(log.Fields{
+ "OnuId": flow.OnuId,
+ "IntfId": flow.AccessIntfId,
+ "Flow": flow,
+ "SerialNumber": onu.Sn(),
+ "err": err,
+ }).Error("invalid-flow-for-onu")
+ return nil, err
+ }
+
+ o.storeGemPortId(flow)
+ o.storeAllocId(flow)
+
msg := types.Message{
Type: types.FlowAdd,
Data: types.OnuFlowUpdateMessage{
@@ -1074,10 +1111,22 @@
func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
oltLogger.WithFields(log.Fields{
- "FlowId": flow.FlowId,
- "FlowType": flow.FlowType,
+ "AllocId": flow.AllocId,
+ "Cookie": flow.Cookie,
+ "FlowId": flow.FlowId,
+ "FlowType": flow.FlowType,
+ "GemportId": flow.GemportId,
+ "IntfId": flow.AccessIntfId,
+ "OnuId": flow.OnuId,
+ "PortNo": flow.PortNo,
+ "UniID": flow.UniId,
+ "ReplicateFlow": flow.ReplicateFlow,
+ "PbitToGemport": flow.PbitToGemport,
}).Debug("OLT receives FlowRemove")
+ olt.freeGemPortId(flow)
+ olt.freeAllocId(flow)
+
if !o.enablePerf { // remove only if flow were stored
flowKey := FlowKey{
ID: flow.FlowId,
@@ -1177,11 +1226,6 @@
func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
- oltLogger.WithFields(log.Fields{
- "oltId": o.ID,
- "PonPorts": o.NumPon,
- }).Info("OLT receives GetDeviceInfo call from VOLTHA")
-
intfIDs := []uint32{}
for i := 0; i < o.NumPon; i++ {
intfIDs = append(intfIDs, uint32(i))
@@ -1538,3 +1582,179 @@
func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
return &openolt.OnuStatistics{}, nil
}
+
+func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
+ o.AllocIDsLock.Lock()
+ defer o.AllocIDsLock.Unlock()
+
+ oltLogger.WithFields(log.Fields{
+ "IntfId": flow.AccessIntfId,
+ "OnuId": flow.OnuId,
+ "PortNo": flow.PortNo,
+ "AllocId": flow.AllocId,
+ }).Trace("storing-alloc-id-via-flow")
+
+ if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
+ o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
+ }
+ if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
+ o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
+ }
+ o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
+}
+
+func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
+ // if this is the last flow referencing the AllocId then remove it
+ o.AllocIDsLock.Lock()
+ defer o.AllocIDsLock.Unlock()
+
+ oltLogger.WithFields(log.Fields{
+ "IntfId": flow.AccessIntfId,
+ "OnuId": flow.OnuId,
+ "PortNo": flow.PortNo,
+ "GemportId": flow.GemportId,
+ }).Trace("freeing-alloc-id-via-flow")
+
+ // NOTE look at the freeGemPortId implementation for comments and context
+ for ponId, ponValues := range o.AllocIDs {
+ for onuId, onuValues := range ponValues {
+ for uniId, uniValues := range onuValues {
+ for allocId, flows := range uniValues {
+ for flowId := range flows {
+ // if the flow matches, remove it from the map.
+ if flow.FlowId == flowId {
+ delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
+ }
+ // if that was the last flow for a particular allocId, remove the entire allocId
+ if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
+ delete(o.AllocIDs[ponId][onuId][uniId], allocId)
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+func (o *OltDevice) storeGemPortId(flow *openolt.Flow) {
+ o.GemPortIDsLock.Lock()
+ defer o.GemPortIDsLock.Unlock()
+
+ oltLogger.WithFields(log.Fields{
+ "IntfId": flow.AccessIntfId,
+ "OnuId": flow.OnuId,
+ "PortNo": flow.PortNo,
+ "GemportId": flow.GemportId,
+ }).Trace("storing-gem-port-id-via-flow")
+
+ if _, ok := o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
+ o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
+ }
+ if _, ok := o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]; !ok {
+ o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId] = make(map[uint64]bool)
+ }
+ o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId][flow.FlowId] = true
+}
+
+func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
+ // if this is the last flow referencing the GemPort then remove it
+ o.GemPortIDsLock.Lock()
+ defer o.GemPortIDsLock.Unlock()
+
+ oltLogger.WithFields(log.Fields{
+ "IntfId": flow.AccessIntfId,
+ "OnuId": flow.OnuId,
+ "PortNo": flow.PortNo,
+ "GemportId": flow.GemportId,
+ }).Trace("freeing-gem-port-id-via-flow")
+
+ // NOTE that this loop is not very performant, it would be better if the flow carries
+ // the same information that it carries during a FlowAdd. If so we can directly remove
+ // items from the map
+
+ //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
+ //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
+ // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
+ //}
+
+ // NOTE this loop assumes that flow IDs are unique per device
+ for ponId, ponValues := range o.GemPortIDs {
+ for onuId, onuValues := range ponValues {
+ for uniId, uniValues := range onuValues {
+ for gemId, flows := range uniValues {
+ for flowId := range flows {
+ // if the flow matches, remove it from the map.
+ if flow.FlowId == flowId {
+ delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
+ }
+ // if that was the last flow for a particular gem, remove the entire gem
+ if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
+ delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// validateFlow checks that:
+// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
+// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
+func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
+
+ // validate gemPort
+ o.GemPortIDsLock.RLock()
+ allocatedGems := o.GemPortIDs[uint32(flow.AccessIntfId)]
+ o.GemPortIDsLock.RUnlock()
+ for onuId, onu := range allocatedGems {
+ if onuId == uint32(flow.OnuId) {
+ continue
+ }
+ for uniId, uni := range onu {
+ for gem := range uni {
+ if gem == flow.GemportId {
+ return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d", gem, uniId, onuId)
+ }
+ }
+ }
+ }
+
+ o.AllocIDsLock.RLock()
+ allocatedAllocIds := o.AllocIDs[uint32(flow.AccessIntfId)]
+ o.AllocIDsLock.RUnlock()
+ for onuId, onu := range allocatedAllocIds {
+ if onuId == uint32(flow.OnuId) {
+ continue
+ }
+ for uniId, uni := range onu {
+ for allocId := range uni {
+ if allocId == flow.AllocId {
+ return fmt.Errorf("allocId-%d-already-in-use-on-uni-%d-onu-%d", allocId, uniId, onuId)
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
+// clearAllResources is invoked up OLT Reboot to remove all the allocated
+// GemPorts, AllocId and ONU-IDs across the PONs
+func (o *OltDevice) clearAllResources() {
+
+ // remove the resources received via flows
+ o.GemPortIDsLock.Lock()
+ o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
+ o.GemPortIDsLock.Unlock()
+ o.AllocIDsLock.Lock()
+ o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
+ o.AllocIDsLock.Unlock()
+
+ // remove the resources received via OMCI
+ for _, pon := range o.Pons {
+ pon.removeAllAllocIds()
+ pon.removeAllGemPorts()
+ pon.removeAllOnuIds()
+ }
+}
diff --git a/internal/bbsim/devices/olt_test.go b/internal/bbsim/devices/olt_test.go
index 154942b..acbe7a7 100644
--- a/internal/bbsim/devices/olt_test.go
+++ b/internal/bbsim/devices/olt_test.go
@@ -28,15 +28,27 @@
func createMockOlt(numPon int, numOnu int, services []ServiceIf) *OltDevice {
olt := &OltDevice{
- ID: 0,
+ ID: 0,
+ AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
+ GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
}
for i := 0; i < numPon; i++ {
+
+ // initialize the resource maps for every PON Ports
+ olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
+ olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
+
pon := PonPort{
ID: uint32(i),
}
for j := 0; j < numOnu; j++ {
+
+ // initialize the resource maps for every ONU and the first UNI
+ olt.AllocIDs[uint32(i)][uint32(j)] = make(map[uint32]map[int32]map[uint64]bool)
+ olt.GemPortIDs[uint32(i)][uint32(j)] = make(map[uint32]map[int32]map[uint64]bool)
+
onuId := uint32(i + j)
onu := Onu{
ID: onuId,
@@ -51,7 +63,7 @@
onu.Services = append(onu.Services, service)
}
- onu.SerialNumber = onu.NewSN(olt.ID, pon.ID, onu.ID)
+ onu.SerialNumber = NewSN(olt.ID, pon.ID, onu.ID)
pon.Onus = append(pon.Onus, &onu)
}
olt.Pons = append(olt.Pons, &pon)
@@ -227,3 +239,209 @@
assert.Equal(t, err, nil)
assert.Equal(t, found.Sn(), onu1.Sn())
}
+
+func Test_Olt_storeGemPortId(t *testing.T) {
+
+ const (
+ pon = 1
+ onu = 1
+ uni = 16
+ gem1 = 1024
+ gem2 = 1025
+ )
+
+ numPon := 2
+ numOnu := 2
+
+ olt := createMockOlt(numPon, numOnu, []ServiceIf{})
+
+ // add a first flow on the ONU
+ flow1 := &openolt.Flow{
+ AccessIntfId: pon,
+ OnuId: onu,
+ PortNo: uni,
+ FlowId: 1,
+ GemportId: gem1,
+ }
+
+ olt.storeGemPortId(flow1)
+ assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1) // we have 1 gem port
+ assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1) // and one flow referencing it
+
+ // add a second flow on the ONU (same gem)
+ flow2 := &openolt.Flow{
+ AccessIntfId: pon,
+ OnuId: onu,
+ PortNo: uni,
+ FlowId: 2,
+ GemportId: gem1,
+ }
+
+ olt.storeGemPortId(flow2)
+ assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1) // we have 1 gem port
+ assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 2) // and two flows referencing it
+
+ // add a third flow on the ONU (different gem)
+ flow3 := &openolt.Flow{
+ AccessIntfId: pon,
+ OnuId: onu,
+ PortNo: uni,
+ FlowId: 2,
+ GemportId: 1025,
+ }
+
+ olt.storeGemPortId(flow3)
+ assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2) // we have 2 gem ports
+ assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 2) // two flows referencing the first one
+ assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem2]), 1) // and one flow referencing the second one
+}
+
+func Test_Olt_freeGemPortId(t *testing.T) {
+ const (
+ pon = 1
+ onu = 1
+ uni = 16
+ gem1 = 1024
+ gem2 = 1025
+ flow1 = 1
+ flow2 = 2
+ flow3 = 3
+ )
+
+ numPon := 2
+ numOnu := 2
+
+ olt := createMockOlt(numPon, numOnu, []ServiceIf{})
+
+ olt.GemPortIDs[pon][onu][uni] = make(map[int32]map[uint64]bool)
+ olt.GemPortIDs[pon][onu][uni][gem1] = make(map[uint64]bool)
+ olt.GemPortIDs[pon][onu][uni][gem1][flow1] = true
+ olt.GemPortIDs[pon][onu][uni][gem1][flow2] = true
+ olt.GemPortIDs[pon][onu][uni][gem2] = make(map[uint64]bool)
+ olt.GemPortIDs[pon][onu][uni][gem2][flow3] = true
+
+ // remove one flow on the first gem, check that the gem is still allocated as there is still a flow referencing it
+ // NOTE that the flow remove only carries the flow ID, no other information
+ flowGem1 := &openolt.Flow{
+ FlowId: flow1,
+ }
+
+ olt.freeGemPortId(flowGem1)
+ // we still have two unis in the map
+ assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2)
+
+ // we should now have a single gem referenced on this UNI
+ assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1, "gemport-not-removed")
+
+ // the gem should still reference flow 2
+ assert.Equal(t, olt.GemPortIDs[pon][onu][uni][gem1][flow2], true)
+ // but should not reference flow1
+ _, flow1Exists := olt.GemPortIDs[pon][onu][uni][gem1][flow1]
+ assert.Equal(t, flow1Exists, false)
+
+ // this is the only flow remaining on this gem, the gem should be removed
+ flowGem2 := &openolt.Flow{
+ FlowId: flow2,
+ }
+ olt.freeGemPortId(flowGem2)
+
+ // we should now have a single gem referenced on this UNI
+ assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1, "gemport-not-removed")
+
+ // and it should be gem2
+ _, gem1exists := olt.GemPortIDs[pon][onu][uni][gem1]
+ assert.Equal(t, gem1exists, false)
+ _, gem2exists := olt.GemPortIDs[pon][onu][uni][gem2]
+ assert.Equal(t, gem2exists, true)
+}
+
+func Test_Olt_validateFlow(t *testing.T) {
+
+ const (
+ pon0 = 0
+ pon1 = 1
+ onu0 = 0
+ onu1 = 1
+ uniPort = 0
+ usedGemIdPon0 = 1024
+ usedGemIdPon1 = 1025
+ usedAllocIdPon0 = 1
+ usedAllocIdPon1 = 2
+ flowId = 1
+ )
+
+ numPon := 2
+ numOnu := 2
+
+ olt := createMockOlt(numPon, numOnu, []ServiceIf{})
+
+ olt.GemPortIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
+ olt.GemPortIDs[pon1][onu0][uniPort] = make(map[int32]map[uint64]bool)
+
+ olt.GemPortIDs[pon0][onu0][uniPort][usedGemIdPon0] = make(map[uint64]bool)
+ olt.GemPortIDs[pon0][onu0][uniPort][usedGemIdPon0][flowId] = true
+ olt.GemPortIDs[pon1][onu0][uniPort][usedGemIdPon1] = make(map[uint64]bool)
+ olt.GemPortIDs[pon1][onu0][uniPort][usedGemIdPon1][flowId] = true
+
+ olt.AllocIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
+ olt.AllocIDs[pon1][onu0][uniPort] = make(map[int32]map[uint64]bool)
+ olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0] = make(map[uint64]bool)
+ olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0][flowId] = true
+ olt.AllocIDs[pon1][onu0][uniPort][usedAllocIdPon1] = make(map[uint64]bool)
+ olt.AllocIDs[pon1][onu0][uniPort][usedAllocIdPon1][flowId] = true
+
+ // a GemPortID can be referenced across multiple flows on the same ONU
+ validGemFlow := &openolt.Flow{
+ AccessIntfId: pon0,
+ OnuId: onu0,
+ GemportId: usedGemIdPon0,
+ }
+
+ err := olt.validateFlow(validGemFlow)
+ assert.NilError(t, err)
+
+ // a GemPortID can NOT be referenced across different ONUs on the same PON
+ invalidGemFlow := &openolt.Flow{
+ AccessIntfId: pon0,
+ OnuId: onu1,
+ GemportId: usedGemIdPon0,
+ }
+ err = olt.validateFlow(invalidGemFlow)
+ assert.Error(t, err, "gem-1024-already-in-use-on-uni-0-onu-0")
+
+ // if a flow reference the same GEM on a different PON it's a valid flow
+ invalidGemDifferentPonFlow := &openolt.Flow{
+ AccessIntfId: pon1,
+ OnuId: onu1,
+ GemportId: usedGemIdPon0,
+ }
+ err = olt.validateFlow(invalidGemDifferentPonFlow)
+ assert.NilError(t, err)
+
+ // an allocId can be referenced across multiple flows on the same ONU
+ validAllocFlow := &openolt.Flow{
+ AccessIntfId: pon0,
+ OnuId: onu0,
+ AllocId: usedAllocIdPon0,
+ }
+ err = olt.validateFlow(validAllocFlow)
+ assert.NilError(t, err)
+
+ // an allocId can NOT be referenced across different ONUs on the same PON
+ invalidAllocFlow := &openolt.Flow{
+ AccessIntfId: pon0,
+ OnuId: onu1,
+ AllocId: usedAllocIdPon0,
+ }
+ err = olt.validateFlow(invalidAllocFlow)
+ assert.Error(t, err, "allocId-1-already-in-use-on-uni-0-onu-0")
+
+ // if a flow reference the same AllocId on a different PON it's a valid flow
+ invalidAllocDifferentPonFlow := &openolt.Flow{
+ AccessIntfId: pon1,
+ OnuId: onu1,
+ AllocId: usedAllocIdPon0,
+ }
+ err = olt.validateFlow(invalidAllocDifferentPonFlow)
+ assert.NilError(t, err)
+}
diff --git a/internal/bbsim/devices/onu.go b/internal/bbsim/devices/onu.go
index fd7eca0..ab7c35f 100644
--- a/internal/bbsim/devices/onu.go
+++ b/internal/bbsim/devices/onu.go
@@ -22,14 +22,13 @@
"fmt"
pb "github.com/opencord/bbsim/api/bbsim"
"github.com/opencord/bbsim/internal/bbsim/alarmsim"
- bbsim "github.com/opencord/bbsim/internal/bbsim/types"
- me "github.com/opencord/omci-lib-go/generated"
- "strconv"
-
"github.com/opencord/bbsim/internal/bbsim/packetHandlers"
"github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
"github.com/opencord/bbsim/internal/bbsim/responders/eapol"
+ bbsim "github.com/opencord/bbsim/internal/bbsim/types"
+ me "github.com/opencord/omci-lib-go/generated"
"net"
+ "strconv"
"time"
"github.com/google/gopacket/layers"
@@ -102,11 +101,9 @@
// PortNo comes with flows and it's used when sending packetIndications,
// There is one PortNo per UNI Port, for now we're only storing the first one
// FIXME add support for multiple UNIs (each UNI has a different PortNo)
- PortNo uint32
- // deprecated (gemPort is on a Service basis)
- GemPortAdded bool
- Flows []FlowKey
- FlowIds []uint64 // keep track of the flows we currently have in the ONU
+ PortNo uint32
+ Flows []FlowKey
+ FlowIds []uint64 // keep track of the flows we currently have in the ONU
OperState *fsm.FSM
SerialNumber *openolt.SerialNumber
@@ -153,7 +150,7 @@
ActiveImageEntityId: 0, // when we start the SoftwareImage with ID 0 is active and committed
CommittedImageEntityId: 0,
}
- o.SerialNumber = o.NewSN(olt.ID, pon.ID, id)
+ o.SerialNumber = NewSN(olt.ID, pon.ID, id)
// NOTE this state machine is used to track the operational
// state as requested by VOLTHA
o.OperState = getOperStateFSM(func(e *fsm.Event) {
@@ -217,6 +214,18 @@
o.Channel <- msg
},
"enter_enabled": func(event *fsm.Event) {
+
+ if used, sn := o.PonPort.isOnuIdAllocated(o.ID); used {
+ onuLogger.WithFields(log.Fields{
+ "IntfId": o.PonPortID,
+ "OnuId": o.ID,
+ "SerialNumber": o.Sn(),
+ }).Errorf("received-omci-with-sn-%s", common.OnuSnToString(sn))
+ return
+ } else {
+ o.PonPort.storeOnuId(o.ID, o.SerialNumber)
+ }
+
msg := bbsim.Message{
Type: bbsim.OnuIndication,
Data: bbsim.OnuIndicationMessage{
@@ -235,9 +244,11 @@
"enter_disabled": func(event *fsm.Event) {
// clean the ONU state
- o.GemPortAdded = false
o.PortNo = 0
o.Flows = []FlowKey{}
+ o.PonPort.removeOnuId(o.ID)
+ o.PonPort.removeAllocId(o.SerialNumber)
+ o.PonPort.removeGemPortBySn(o.SerialNumber)
// set the OperState to disabled
if err := o.OperState.Event("disable"); err != nil {
@@ -438,7 +449,7 @@
}).Debug("Stopped handling ONU Indication Channel")
}
-func (o Onu) NewSN(oltid int, intfid uint32, onuid uint32) *openolt.SerialNumber {
+func NewSN(oltid int, intfid uint32, onuid uint32) *openolt.SerialNumber {
sn := new(openolt.SerialNumber)
@@ -477,10 +488,8 @@
}
func (o *Onu) sendOnuIndication(msg bbsim.OnuIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
- // NOTE voltha returns an ID, but if we use that ID then it complains:
- // expected_onu_id: 1, received_onu_id: 1024, event: ONU-id-mismatch, can happen if both voltha and the olt rebooted
- // so we're using the internal ID that is 1
- // o.ID = msg.OnuID
+ // NOTE the ONU ID is set by VOLTHA in the ActivateOnu call (via openolt.proto)
+ // and stored in the Onu struct via onu.SetID
indData := &openolt.Indication_OnuInd{OnuInd: &openolt.OnuIndication{
IntfId: o.PonPortID,
@@ -495,11 +504,12 @@
return
}
onuLogger.WithFields(log.Fields{
- "IntfId": o.PonPortID,
- "OnuId": o.ID,
- "OperState": msg.OperState.String(),
- "AdminState": msg.OperState.String(),
- "OnuSn": o.Sn(),
+ "IntfId": o.PonPortID,
+ "OnuId": o.ID,
+ "VolthaOnuId": msg.OnuID,
+ "OperState": msg.OperState.String(),
+ "AdminState": msg.OperState.String(),
+ "OnuSn": o.Sn(),
}).Debug("Sent Indication_OnuInd")
}
@@ -707,10 +717,7 @@
case omci.GetRequestType:
responsePkt, _ = omcilib.CreateGetResponse(omciPkt, omciMsg, o.SerialNumber, o.MibDataSync, o.ActiveImageEntityId, o.CommittedImageEntityId)
case omci.SetRequestType:
- if responsePkt, errResp = omcilib.CreateSetResponse(omciPkt, omciMsg); errResp == nil {
- o.MibDataSync++
- }
-
+ success := true
msgObj, _ := omcilib.ParseSetRequest(omciPkt)
switch msgObj.EntityClass {
case me.PhysicalPathTerminationPointEthernetUniClassID:
@@ -734,12 +741,101 @@
}
o.Channel <- msg
}
+ case me.TContClassID:
+ allocId := msgObj.Attributes["AllocId"].(uint16)
+
+ // if the AllocId is 255 (0xFF) or 65535 (0xFFFF) it means we are removing it,
+ // otherwise we are adding it
+ if allocId == 255 || allocId == 65535 {
+ onuLogger.WithFields(log.Fields{
+ "IntfId": o.PonPortID,
+ "OnuId": o.ID,
+ "TContId": msgObj.EntityInstance,
+ "AllocId": allocId,
+ "SerialNumber": o.Sn(),
+ }).Trace("freeing-alloc-id-via-omci")
+ o.PonPort.removeAllocId(o.SerialNumber)
+ } else {
+ if used, sn := o.PonPort.isAllocIdAllocated(allocId); used {
+ onuLogger.WithFields(log.Fields{
+ "IntfId": o.PonPortID,
+ "OnuId": o.ID,
+ "AllocId": allocId,
+ "SerialNumber": o.Sn(),
+ }).Errorf("allocid-already-allocated-to-onu-with-sn-%s", common.OnuSnToString(sn))
+ success = false
+ } else {
+ onuLogger.WithFields(log.Fields{
+ "IntfId": o.PonPortID,
+ "OnuId": o.ID,
+ "TContId": msgObj.EntityInstance,
+ "AllocId": allocId,
+ "SerialNumber": o.Sn(),
+ }).Trace("storing-alloc-id-via-omci")
+ o.PonPort.storeAllocId(allocId, o.SerialNumber)
+ }
+ }
+
+ }
+
+ if success {
+ if responsePkt, errResp = omcilib.CreateSetResponse(omciPkt, omciMsg, me.Success); errResp == nil {
+ o.MibDataSync++
+ }
+ } else {
+ responsePkt, _ = omcilib.CreateSetResponse(omciPkt, omciMsg, me.AttributeFailure)
}
case omci.CreateRequestType:
- if responsePkt, errResp = omcilib.CreateCreateResponse(omciPkt, omciMsg); errResp == nil {
- o.MibDataSync++
+ // check for GemPortNetworkCtp and make sure there are no duplicates on the same PON
+ var used bool
+ var sn *openolt.SerialNumber
+ msgObj, err := omcilib.ParseCreateRequest(omciPkt)
+ if err == nil {
+ if msgObj.EntityClass == me.GemPortNetworkCtpClassID {
+ if used, sn = o.PonPort.isGemPortAllocated(msgObj.EntityInstance); used {
+ onuLogger.WithFields(log.Fields{
+ "IntfId": o.PonPortID,
+ "OnuId": o.ID,
+ "GemPortId": msgObj.EntityInstance,
+ "SerialNumber": o.Sn(),
+ }).Errorf("gemport-already-allocated-to-onu-with-sn-%s", common.OnuSnToString(sn))
+ } else {
+ onuLogger.WithFields(log.Fields{
+ "IntfId": o.PonPortID,
+ "OnuId": o.ID,
+ "GemPortId": msgObj.EntityInstance,
+ "SerialNumber": o.Sn(),
+ }).Trace("storing-gem-port-id-via-omci")
+ o.PonPort.storeGemPort(msgObj.EntityInstance, o.SerialNumber)
+ }
+ }
+ }
+
+ // if the gemPort is valid then increment the MDS and return a successful response
+ // otherwise fail the request
+ // for now the CreateRequeste for the gemPort is the only one that can fail, if we start supporting multiple
+ // validation this check will need to be rewritten
+ if !used {
+ if responsePkt, errResp = omcilib.CreateCreateResponse(omciPkt, omciMsg, me.Success); errResp == nil {
+ o.MibDataSync++
+ }
+ } else {
+ responsePkt, _ = omcilib.CreateCreateResponse(omciPkt, omciMsg, me.ProcessingError)
}
case omci.DeleteRequestType:
+ msgObj, err := omcilib.ParseDeleteRequest(omciPkt)
+ if err == nil {
+ if msgObj.EntityClass == me.GemPortNetworkCtpClassID {
+ onuLogger.WithFields(log.Fields{
+ "IntfId": o.PonPortID,
+ "OnuId": o.ID,
+ "GemPortId": msgObj.EntityInstance,
+ "SerialNumber": o.Sn(),
+ }).Trace("freeing-gem-port-id-via-omci")
+ o.PonPort.removeGemPort(msgObj.EntityInstance)
+ }
+ }
+
if responsePkt, errResp = omcilib.CreateDeleteResponse(omciPkt, omciMsg); errResp == nil {
o.MibDataSync++
}
@@ -1037,6 +1133,7 @@
func (o *Onu) handleFlowAdd(msg bbsim.OnuFlowUpdateMessage) {
onuLogger.WithFields(log.Fields{
+ "AllocId": msg.Flow.AllocId,
"Cookie": msg.Flow.Cookie,
"DstPort": msg.Flow.Classifier.DstPort,
"FlowId": msg.Flow.FlowId,
@@ -1123,7 +1220,6 @@
"OnuId": o.ID,
"SerialNumber": o.Sn(),
}).Info("Resetting GemPort")
- o.GemPortAdded = false
// check if ONU delete is performed and
// terminate the ONU's ProcessOnuMessages Go routine
@@ -1245,25 +1341,7 @@
if o.seqNumber > 290 {
// NOTE we are done with the MIB Upload (290 is the number of messages the omci-sim library will respond to)
- galEnet, _ := omcilib.CreateGalEnetRequest(o.getNextTid(false))
- sendOmciMsg(galEnet, o.PonPortID, o.ID, o.SerialNumber, "CreateGalEnetRequest", client)
- } else {
- mibUploadNext, _ := omcilib.CreateMibUploadNextRequest(o.getNextTid(false), o.seqNumber)
- sendOmciMsg(mibUploadNext, o.PonPortID, o.ID, o.SerialNumber, "mibUploadNext", client)
- }
- case omci.CreateResponseType:
- // NOTE Creating a GemPort,
- // BBsim actually doesn't care about the values, so we can do we want with the parameters
- // In the same way we can create a GemPort even without setting up UNIs/TConts/...
- // but we need the GemPort to trigger the state change
-
- if !o.GemPortAdded {
- // NOTE this sends a CreateRequestType and BBSim replies with a CreateResponseType
- // thus we send this request only once
- gemReq, _ := omcilib.CreateGemPortRequest(o.getNextTid(false))
- sendOmciMsg(gemReq, o.PonPortID, o.ID, o.SerialNumber, "CreateGemPortRequest", client)
- o.GemPortAdded = true
- } else {
+ // start sending the flows, we don't care about the OMCI setup in BBR, just that a lot of messages can go through
if err := o.InternalState.Event(BbrOnuTxSendEapolFlow); err != nil {
onuLogger.WithFields(log.Fields{
"OnuId": o.ID,
@@ -1271,6 +1349,9 @@
"OnuSn": o.Sn(),
}).Errorf("Error while transitioning ONU State %v", err)
}
+ } else {
+ mibUploadNext, _ := omcilib.CreateMibUploadNextRequest(o.getNextTid(false), o.seqNumber)
+ sendOmciMsg(mibUploadNext, o.PonPortID, o.ID, o.SerialNumber, "mibUploadNext", client)
}
}
}
@@ -1290,14 +1371,16 @@
UniId: int32(0), // NOTE do not hardcode this, we need to support multiple UNIs
FlowId: uint64(o.ID),
FlowType: "downstream",
- AllocId: int32(0),
NetworkIntfId: int32(0),
- GemportId: int32(1), // FIXME use the same value as CreateGemPortRequest PortID, do not hardcode
Classifier: &classifierProto,
Action: &actionProto,
Priority: int32(100),
Cookie: uint64(o.ID),
- PortNo: uint32(o.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
+ PortNo: o.ID, // NOTE we are using this to map an incoming packetIndication to an ONU
+ // AllocId and GemPorts need to be unique per PON
+ // for now use the ONU-ID, will need to change once we support multiple UNIs
+ AllocId: int32(o.ID),
+ GemportId: int32(o.ID),
}
if _, err := client.FlowAdd(context.Background(), &downstreamFlow); err != nil {
@@ -1307,6 +1390,7 @@
"FlowId": downstreamFlow.FlowId,
"PortNo": downstreamFlow.PortNo,
"SerialNumber": common.OnuSnToString(o.SerialNumber),
+ "Err": err,
}).Fatalf("Failed to add EAPOL Flow")
}
log.WithFields(log.Fields{
@@ -1338,14 +1422,16 @@
UniId: int32(0), // FIXME do not hardcode this
FlowId: uint64(o.ID),
FlowType: "downstream",
- AllocId: int32(0),
NetworkIntfId: int32(0),
- GemportId: int32(1), // FIXME use the same value as CreateGemPortRequest PortID, do not hardcode
Classifier: &classifierProto,
Action: &actionProto,
Priority: int32(100),
Cookie: uint64(o.ID),
- PortNo: uint32(o.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
+ PortNo: o.ID, // NOTE we are using this to map an incoming packetIndication to an ONU
+ // AllocId and GemPorts need to be unique per PON
+ // for now use the ONU-ID, will need to change once we support multiple UNIs
+ AllocId: int32(o.ID),
+ GemportId: int32(o.ID),
}
if _, err := client.FlowAdd(context.Background(), &downstreamFlow); err != nil {
@@ -1355,6 +1441,7 @@
"FlowId": downstreamFlow.FlowId,
"PortNo": downstreamFlow.PortNo,
"SerialNumber": common.OnuSnToString(o.SerialNumber),
+ "Err": err,
}).Fatalf("Failed to send DHCP Flow")
}
log.WithFields(log.Fields{
diff --git a/internal/bbsim/devices/onu_flow_test.go b/internal/bbsim/devices/onu_flow_test.go
index e0ad9fe..b116843 100644
--- a/internal/bbsim/devices/onu_flow_test.go
+++ b/internal/bbsim/devices/onu_flow_test.go
@@ -100,8 +100,6 @@
fsm.Callbacks{},
)
- onu.GemPortAdded = true
-
onu.FlowIds = []uint64{64}
flow := openolt.Flow{
@@ -115,7 +113,6 @@
}
onu.handleFlowRemove(msg)
assert.Equal(t, len(onu.FlowIds), 0)
- assert.Equal(t, onu.GemPortAdded, false)
}
func TestOnu_HhandleEAPOLStart(t *testing.T) {
@@ -429,8 +426,6 @@
// one we received with the EAPOL flow
onu := createMockOnu(1, 1)
- onu.GemPortAdded = false
-
onu.InternalState = fsm.NewFSM(
"enabled",
fsm.Events{
diff --git a/internal/bbsim/devices/onu_omci_test.go b/internal/bbsim/devices/onu_omci_test.go
index 4b9cc26..4d706b9 100644
--- a/internal/bbsim/devices/onu_omci_test.go
+++ b/internal/bbsim/devices/onu_omci_test.go
@@ -17,6 +17,7 @@
package devices
import (
+ "github.com/google/gopacket"
bbsim "github.com/opencord/bbsim/internal/bbsim/types"
omcilib "github.com/opencord/bbsim/internal/common/omci"
"github.com/opencord/omci-lib-go"
@@ -27,7 +28,6 @@
)
var mockAttr = me.AttributeValueMap{
- "ManagedEntityId": 12,
"PortId": 0,
"TContPointer": 0,
"Direction": 0,
@@ -46,6 +46,7 @@
},
Attributes: mockAttr,
}
+
omciPkt, err := omcilib.Serialize(omci.CreateRequestType, omciReq, 66)
if err != nil {
t.Fatal(err.Error())
@@ -119,6 +120,34 @@
}
}
+func omciBytesToMsg(t *testing.T, data []byte) (*omci.OMCI, *gopacket.Packet) {
+ packet := gopacket.NewPacket(data, omci.LayerTypeOMCI, gopacket.NoCopy)
+ if packet == nil {
+ t.Fatal("could not decode rxMsg as OMCI")
+ }
+ omciLayer := packet.Layer(omci.LayerTypeOMCI)
+ if omciLayer == nil {
+ t.Fatal("could not decode omci layer")
+ }
+ omciMsg, ok := omciLayer.(*omci.OMCI)
+ if !ok {
+ t.Fatal("could not assign omci layer")
+ }
+ return omciMsg, &packet
+}
+
+func omciToCreateResponse(t *testing.T, omciPkt *gopacket.Packet) *omci.CreateResponse {
+ msgLayer := (*omciPkt).Layer(omci.LayerTypeCreateResponse)
+ if msgLayer == nil {
+ t.Fatal("omci Msg layer could not be detected for CreateResponse - handling of MibSyncChan stopped")
+ }
+ msgObj, msgOk := msgLayer.(*omci.CreateResponse)
+ if !msgOk {
+ t.Fatal("omci Msg layer could not be assigned for CreateResponse - handling of MibSyncChan stopped")
+ }
+ return msgObj
+}
+
func Test_MibDataSyncIncrease(t *testing.T) {
onu := createMockOnu(1, 1)
@@ -174,3 +203,39 @@
onu.handleOmciRequest(makeOmciMessage(t, onu, makeOmciDeleteRequest(t)), stream)
assert.Equal(t, onu.MibDataSync, uint8(0))
}
+
+func Test_GemPortValidation(t *testing.T) {
+
+ // setup
+ onu := createMockOnu(1, 1)
+
+ stream := &mockStream{
+ Calls: make(map[int]*openolt.Indication),
+ }
+
+ // create a gem port via OMCI (gemPortId 12)
+ onu.handleOmciRequest(makeOmciMessage(t, onu, makeOmciCreateRequest(t)), stream)
+
+ // the first time we created the gemPort
+ // the MDS should be incremented
+ assert.Equal(t, stream.CallCount, 1)
+ assert.Equal(t, onu.MibDataSync, uint8(1))
+
+ // and the OMCI response status should be me.Success
+ indication := stream.Calls[1].GetOmciInd()
+ _, omciPkt := omciBytesToMsg(t, indication.Pkt)
+ responseLayer := omciToCreateResponse(t, omciPkt)
+ assert.Equal(t, responseLayer.Result, me.Success)
+
+ // send a request to create the same gem port via OMCI (gemPortId 12)
+ onu.handleOmciRequest(makeOmciMessage(t, onu, makeOmciCreateRequest(t)), stream)
+
+ // this time the MDS should not be incremented
+ assert.Equal(t, stream.CallCount, 2)
+ assert.Equal(t, onu.MibDataSync, uint8(1))
+
+ // and the OMCI response status should be me.ProcessingError
+ _, omciPkt = omciBytesToMsg(t, stream.Calls[2].GetOmciInd().Pkt)
+ responseLayer = omciToCreateResponse(t, omciPkt)
+ assert.Equal(t, responseLayer.Result, me.ProcessingError)
+}
diff --git a/internal/bbsim/devices/onu_state_machine_test.go b/internal/bbsim/devices/onu_state_machine_test.go
index 6f62540..f0fd232 100644
--- a/internal/bbsim/devices/onu_state_machine_test.go
+++ b/internal/bbsim/devices/onu_state_machine_test.go
@@ -37,7 +37,6 @@
assert.Equal(t, onu.InternalState.Current(), OnuStateEnabled)
onu.PortNo = 16
- onu.GemPortAdded = true
onu.Flows = []FlowKey{
{ID: 1, Direction: "upstream"},
{ID: 2, Direction: "downstream"},
@@ -46,7 +45,6 @@
_ = onu.InternalState.Event(OnuTxDisable)
assert.Equal(t, onu.InternalState.Current(), OnuStateDisabled)
- assert.Equal(t, onu.GemPortAdded, false)
assert.Equal(t, onu.PortNo, uint32(0))
assert.Equal(t, len(onu.Flows), 0)
}
@@ -95,7 +93,6 @@
assert.Equal(t, onu.InternalState.Current(), OnuStateEnabled)
// succeed
- onu.GemPortAdded = true
_ = onu.InternalState.Event("start_auth")
assert.Equal(t, onu.InternalState.Current(), "auth_started")
}
@@ -104,8 +101,6 @@
t.Skip("Needs to be moved in the Service struct")
onu := createTestOnu()
- onu.GemPortAdded = true
-
onu.InternalState.SetState("auth_started")
assert.Equal(t, onu.InternalState.Current(), "auth_started")
@@ -168,8 +163,6 @@
onu.InternalState.SetState("eap_response_success_received")
assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
- onu.GemPortAdded = false
-
err := onu.InternalState.Event("start_dhcp")
if err == nil {
t.Fail()
@@ -181,7 +174,6 @@
func Test_Onu_StateMachine_dhcp_start(t *testing.T) {
t.Skip("Needs to be moved in the Service struct")
onu := createTestOnu()
- onu.GemPortAdded = true
onu.InternalState.SetState("eap_response_success_received")
assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
@@ -195,8 +187,6 @@
t.Skip("Needs to be moved in the Service struct")
onu := createTestOnu()
- onu.GemPortAdded = true
-
onu.InternalState.SetState("dhcp_started")
assert.Equal(t, onu.InternalState.Current(), "dhcp_started")
diff --git a/internal/bbsim/devices/onu_test_helpers.go b/internal/bbsim/devices/onu_test_helpers.go
index f0d5dab..2f18199 100644
--- a/internal/bbsim/devices/onu_test_helpers.go
+++ b/internal/bbsim/devices/onu_test_helpers.go
@@ -137,15 +137,16 @@
// this method creates a fake ONU used in the tests
func createMockOnu(id uint32, ponPortId uint32) *Onu {
o := Onu{
- ID: id,
- PonPortID: ponPortId,
- PortNo: 0,
- GemPortAdded: true,
+ ID: id,
+ PonPortID: ponPortId,
+ PortNo: 0,
PonPort: &PonPort{
- Olt: &OltDevice{},
+ AllocatedGemPorts: make(map[uint16]*openolt.SerialNumber),
+ AllocatedAllocIds: make(map[uint16]*openolt.SerialNumber),
+ Olt: &OltDevice{},
},
}
- o.SerialNumber = o.NewSN(0, ponPortId, o.ID)
+ o.SerialNumber = NewSN(0, ponPortId, o.ID)
o.Channel = make(chan types.Message, 10)
return &o
}
@@ -155,11 +156,10 @@
olt := OltDevice{
ID: 0,
}
- pon := PonPort{
- ID: 1,
- Olt: &olt,
- }
- onu := CreateONU(&olt, &pon, 1, time.Duration(1*time.Millisecond), true)
+
+ pon := CreatePonPort(&olt, 1)
+
+ onu := CreateONU(&olt, pon, 1, time.Duration(1*time.Millisecond), true)
// NOTE we need this in order to create the OnuChannel
_ = onu.InternalState.Event(OnuTxInitialize)
onu.DiscoveryRetryDelay = 100 * time.Millisecond
diff --git a/internal/bbsim/devices/pon.go b/internal/bbsim/devices/pon.go
index 1e0483d..3d74eb1 100644
--- a/internal/bbsim/devices/pon.go
+++ b/internal/bbsim/devices/pon.go
@@ -19,6 +19,7 @@
import (
"bytes"
"fmt"
+ "sync"
"github.com/looplab/fsm"
"github.com/opencord/voltha-protos/v4/go/openolt"
@@ -37,17 +38,30 @@
// PON Attributes
OperState *fsm.FSM
Type string
+
+ // Allocated resources
+ // Some resources (eg: OnuId, AllocId and GemPorts) have to be unique per PON port
+ // we are keeping a list so that we can throw an error in cases we receive duplicates
+ AllocatedGemPorts map[uint16]*openolt.SerialNumber
+ allocatedGemPortsLock sync.RWMutex
+ AllocatedOnuIds map[uint32]*openolt.SerialNumber
+ allocatedOnuIdsLock sync.RWMutex
+ AllocatedAllocIds map[uint16]*openolt.SerialNumber
+ allocatedAllocIdsLock sync.RWMutex
}
// CreatePonPort creates pon port object
func CreatePonPort(olt *OltDevice, id uint32) *PonPort {
ponPort := PonPort{
- NumOnu: olt.NumOnuPerPon,
- ID: id,
- Type: "pon",
- Olt: olt,
- Onus: []*Onu{},
+ NumOnu: olt.NumOnuPerPon,
+ ID: id,
+ Type: "pon",
+ Olt: olt,
+ Onus: []*Onu{},
+ AllocatedGemPorts: make(map[uint16]*openolt.SerialNumber),
+ AllocatedOnuIds: make(map[uint32]*openolt.SerialNumber),
+ AllocatedAllocIds: make(map[uint16]*openolt.SerialNumber),
}
ponPort.InternalState = fsm.NewFSM(
@@ -170,7 +184,7 @@
return &ponPort
}
-func (p PonPort) GetOnuBySn(sn *openolt.SerialNumber) (*Onu, error) {
+func (p *PonPort) GetOnuBySn(sn *openolt.SerialNumber) (*Onu, error) {
for _, onu := range p.Onus {
if bytes.Equal(onu.SerialNumber.VendorSpecific, sn.VendorSpecific) {
return onu, nil
@@ -179,7 +193,7 @@
return nil, fmt.Errorf("Cannot find Onu with serial number %d in PonPort %d", sn, p.ID)
}
-func (p PonPort) GetOnuById(id uint32) (*Onu, error) {
+func (p *PonPort) GetOnuById(id uint32) (*Onu, error) {
for _, onu := range p.Onus {
if onu.ID == id {
return onu, nil
@@ -189,7 +203,7 @@
}
// GetNumOfActiveOnus returns number of active ONUs for PON port
-func (p PonPort) GetNumOfActiveOnus() uint32 {
+func (p *PonPort) GetNumOfActiveOnus() uint32 {
var count uint32 = 0
for _, onu := range p.Onus {
if onu.InternalState.Current() == OnuStateInitialized || onu.InternalState.Current() == OnuStateCreated || onu.InternalState.Current() == OnuStateDisabled {
@@ -199,3 +213,111 @@
}
return count
}
+
+// storeOnuId adds the Id to the ONU Ids already allocated to this PON port
+func (p *PonPort) storeOnuId(onuId uint32, onuSn *openolt.SerialNumber) {
+ p.allocatedOnuIdsLock.Lock()
+ defer p.allocatedOnuIdsLock.Unlock()
+ p.AllocatedOnuIds[onuId] = onuSn
+}
+
+// removeOnuId removes the OnuId from the allocated resources
+func (p *PonPort) removeOnuId(onuId uint32) {
+ p.allocatedOnuIdsLock.Lock()
+ defer p.allocatedOnuIdsLock.Unlock()
+ delete(p.AllocatedOnuIds, onuId)
+}
+
+func (p *PonPort) removeAllOnuIds() {
+ p.allocatedOnuIdsLock.Lock()
+ defer p.allocatedOnuIdsLock.Unlock()
+ p.AllocatedOnuIds = make(map[uint32]*openolt.SerialNumber)
+}
+
+// isOnuIdAllocated returns whether this OnuId is already in use on this PON
+func (p *PonPort) isOnuIdAllocated(onuId uint32) (bool, *openolt.SerialNumber) {
+ p.allocatedOnuIdsLock.RLock()
+ defer p.allocatedOnuIdsLock.RUnlock()
+
+ if _, ok := p.AllocatedOnuIds[onuId]; ok {
+ return true, p.AllocatedOnuIds[onuId]
+ }
+ return false, nil
+}
+
+// storeGemPort adds the gemPortId to the gemports already allocated to this PON port
+func (p *PonPort) storeGemPort(gemPortId uint16, onuSn *openolt.SerialNumber) {
+ p.allocatedGemPortsLock.Lock()
+ defer p.allocatedGemPortsLock.Unlock()
+ p.AllocatedGemPorts[gemPortId] = onuSn
+}
+
+// removeGemPort removes the gemPortId from the allocated resources
+func (p *PonPort) removeGemPort(gemPortId uint16) {
+ p.allocatedGemPortsLock.Lock()
+ defer p.allocatedGemPortsLock.Unlock()
+ delete(p.AllocatedGemPorts, gemPortId)
+}
+
+func (p *PonPort) removeGemPortBySn(onuSn *openolt.SerialNumber) {
+ p.allocatedGemPortsLock.Lock()
+ defer p.allocatedGemPortsLock.Unlock()
+ for gemPort, sn := range p.AllocatedGemPorts {
+ if sn == onuSn {
+ delete(p.AllocatedGemPorts, gemPort)
+ }
+ }
+}
+
+func (p *PonPort) removeAllGemPorts() {
+ p.allocatedGemPortsLock.Lock()
+ defer p.allocatedGemPortsLock.Unlock()
+ p.AllocatedGemPorts = make(map[uint16]*openolt.SerialNumber)
+}
+
+// isGemPortAllocated returns whether this gemPort is already in use on this PON
+func (p *PonPort) isGemPortAllocated(gemPortId uint16) (bool, *openolt.SerialNumber) {
+ p.allocatedGemPortsLock.RLock()
+ defer p.allocatedGemPortsLock.RUnlock()
+
+ if _, ok := p.AllocatedGemPorts[gemPortId]; ok {
+ return true, p.AllocatedGemPorts[gemPortId]
+ }
+ return false, nil
+}
+
+// storeAllocId adds the Id to the ONU Ids already allocated to this PON port
+func (p *PonPort) storeAllocId(allocId uint16, onuSn *openolt.SerialNumber) {
+ p.allocatedAllocIdsLock.Lock()
+ defer p.allocatedAllocIdsLock.Unlock()
+ p.AllocatedAllocIds[allocId] = onuSn
+}
+
+// removeAllocId removes the AllocId from the allocated resources
+// this is done via SN as the AllocId is not remove but set to a default value
+func (p *PonPort) removeAllocId(onuSn *openolt.SerialNumber) {
+ p.allocatedAllocIdsLock.Lock()
+ defer p.allocatedAllocIdsLock.Unlock()
+ for allocId, sn := range p.AllocatedAllocIds {
+ if sn == onuSn {
+ delete(p.AllocatedAllocIds, allocId)
+ }
+ }
+}
+
+func (p *PonPort) removeAllAllocIds() {
+ p.allocatedAllocIdsLock.Lock()
+ defer p.allocatedAllocIdsLock.Unlock()
+ p.AllocatedAllocIds = make(map[uint16]*openolt.SerialNumber)
+}
+
+// isAllocIdAllocated returns whether this AllocId is already in use on this PON
+func (p *PonPort) isAllocIdAllocated(allocId uint16) (bool, *openolt.SerialNumber) {
+ p.allocatedAllocIdsLock.RLock()
+ defer p.allocatedAllocIdsLock.RUnlock()
+
+ if _, ok := p.AllocatedAllocIds[allocId]; ok {
+ return true, p.AllocatedAllocIds[allocId]
+ }
+ return false, nil
+}
diff --git a/internal/bbsim/devices/pon_test.go b/internal/bbsim/devices/pon_test.go
new file mode 100644
index 0000000..45e1861
--- /dev/null
+++ b/internal/bbsim/devices/pon_test.go
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package devices
+
+import (
+ "github.com/opencord/voltha-protos/v4/go/openolt"
+ "github.com/stretchr/testify/assert"
+ "sync"
+ "testing"
+)
+
+var sn1 = NewSN(0, 0, 1)
+var sn2 = NewSN(0, 0, 2)
+var sn3 = NewSN(0, 0, 3)
+
+// NOTE that we are using a benchmark test to actually test concurrency
+func Benchmark_storeGemPort(b *testing.B) {
+ pon := PonPort{
+ AllocatedGemPorts: make(map[uint16]*openolt.SerialNumber),
+ }
+
+ wg := sync.WaitGroup{}
+ wg.Add(3)
+
+ // concurrently add multiple ports
+ go func(wg *sync.WaitGroup) { pon.storeGemPort(1, sn1); wg.Done() }(&wg)
+ go func(wg *sync.WaitGroup) { pon.storeGemPort(2, sn2); wg.Done() }(&wg)
+ go func(wg *sync.WaitGroup) { pon.storeGemPort(3, sn3); wg.Done() }(&wg)
+
+ wg.Wait()
+
+ assert.Equal(b, len(pon.AllocatedGemPorts), 3)
+}
+
+func Benchmark_removeGemPort(b *testing.B) {
+ pon := PonPort{
+ AllocatedGemPorts: make(map[uint16]*openolt.SerialNumber),
+ }
+
+ pon.storeGemPort(1, sn1)
+ pon.storeGemPort(2, sn2)
+ pon.storeGemPort(3, sn3)
+
+ assert.Equal(b, len(pon.AllocatedGemPorts), 3)
+
+ wg := sync.WaitGroup{}
+ wg.Add(3)
+
+ // concurrently add multiple ports
+ go func(wg *sync.WaitGroup) { pon.removeGemPort(1); wg.Done() }(&wg)
+ go func(wg *sync.WaitGroup) { pon.removeGemPort(2); wg.Done() }(&wg)
+ go func(wg *sync.WaitGroup) { pon.removeGemPort(3); wg.Done() }(&wg)
+
+ wg.Wait()
+
+ assert.Equal(b, len(pon.AllocatedGemPorts), 0)
+}
+
+func Test_removeGemPort(t *testing.T) {
+ pon := &PonPort{
+ AllocatedGemPorts: make(map[uint16]*openolt.SerialNumber),
+ }
+
+ pon.storeGemPort(1, sn1)
+ pon.storeGemPort(2, sn2)
+ assert.Equal(t, len(pon.AllocatedGemPorts), 2)
+
+ // remove a non exiting gemPort
+ pon.removeGemPort(3)
+ assert.Equal(t, len(pon.AllocatedGemPorts), 2)
+
+ // remove an existing gemPort
+ pon.removeGemPort(1)
+ assert.Equal(t, len(pon.AllocatedGemPorts), 1)
+
+}
+
+func Test_removeGemPortBySn(t *testing.T) {
+ pon := &PonPort{
+ AllocatedGemPorts: make(map[uint16]*openolt.SerialNumber),
+ }
+
+ pon.storeGemPort(1, sn1)
+ pon.storeGemPort(2, sn2)
+ assert.Equal(t, len(pon.AllocatedGemPorts), 2)
+
+ // remove a non exiting gemPort
+ pon.removeGemPortBySn(sn1)
+ assert.Equal(t, len(pon.AllocatedGemPorts), 1)
+ assert.Nil(t, pon.AllocatedGemPorts[1])
+ assert.Equal(t, pon.AllocatedGemPorts[2], sn2)
+}
+
+func Test_isGemPortAllocated(t *testing.T) {
+ pon := &PonPort{
+ AllocatedGemPorts: make(map[uint16]*openolt.SerialNumber),
+ }
+
+ pon.storeGemPort(1, sn1)
+
+ assert.Equal(t, len(pon.AllocatedGemPorts), 1)
+
+ free, sn := pon.isGemPortAllocated(1)
+
+ assert.Equal(t, free, true)
+ assert.Equal(t, sn, sn1)
+
+ used, sn_ := pon.isGemPortAllocated(2)
+
+ assert.Equal(t, used, false)
+ assert.Nil(t, sn_)
+}
+
+// the allocId is never removed, is always set to either 255 or 65535
+func Test_removeAllocId(t *testing.T) {
+
+ const (
+ allocId1 = 1024
+ allocId2 = 1025
+ )
+
+ pon := &PonPort{
+ AllocatedAllocIds: make(map[uint16]*openolt.SerialNumber),
+ }
+
+ pon.AllocatedAllocIds[allocId1] = sn1
+ pon.AllocatedAllocIds[allocId2] = sn2
+
+ assert.Equal(t, len(pon.AllocatedAllocIds), 2)
+
+ pon.removeAllocId(sn1)
+
+ assert.Equal(t, len(pon.AllocatedAllocIds), 1)
+ assert.Nil(t, pon.AllocatedAllocIds[allocId1])
+ assert.Equal(t, pon.AllocatedAllocIds[allocId2], sn2)
+
+}
diff --git a/internal/bbsim/responders/dhcp/dhcp_test.go b/internal/bbsim/responders/dhcp/dhcp_test.go
index 7b598a0..3334e82 100644
--- a/internal/bbsim/responders/dhcp/dhcp_test.go
+++ b/internal/bbsim/responders/dhcp/dhcp_test.go
@@ -18,7 +18,6 @@
import (
"errors"
- "fmt"
"net"
"testing"
@@ -68,10 +67,6 @@
xid2 := macAddressToTxId(mac2)
xid3 := macAddressToTxId(mac3)
- fmt.Println(xid1)
- fmt.Println(xid2)
- fmt.Println(xid3)
-
assert.NotEqual(t, xid1, xid2)
assert.NotEqual(t, xid1, xid3)
assert.NotEqual(t, xid2, xid3)
diff --git a/internal/bbsim/responders/sadis/sadis_test.go b/internal/bbsim/responders/sadis/sadis_test.go
index 76facb5..a3ca6df 100644
--- a/internal/bbsim/responders/sadis/sadis_test.go
+++ b/internal/bbsim/responders/sadis/sadis_test.go
@@ -38,7 +38,7 @@
mac := net.HardwareAddr{0x2e, 0x60, 0x01, byte(1), byte(1), byte(0)}
- onu.SerialNumber = onu.NewSN(0, onu.PonPortID, onu.ID)
+ onu.SerialNumber = devices.NewSN(0, onu.PonPortID, onu.ID)
onu.Services = []devices.ServiceIf{
&devices.Service{Name: "hsia", CTag: 923, STag: 900, NeedsEapol: true, NeedsDhcp: true, NeedsIgmp: true, HwAddress: mac, TechnologyProfileID: 64},
}
diff --git a/internal/bbsimctl/commands/helpers.go b/internal/bbsimctl/commands/helpers.go
new file mode 100644
index 0000000..f2a9ee1
--- /dev/null
+++ b/internal/bbsimctl/commands/helpers.go
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package commands
+
+import (
+ pb "github.com/opencord/bbsim/api/bbsim"
+ "github.com/opencord/bbsim/internal/bbsimctl/config"
+ log "github.com/sirupsen/logrus"
+ "google.golang.org/grpc"
+)
+
+func connect() (pb.BBSimClient, *grpc.ClientConn) {
+ conn, err := grpc.Dial(config.GlobalConfig.Server, grpc.WithInsecure())
+
+ if err != nil {
+ log.Fatalf("did not connect: %v", err)
+ return nil, conn
+ }
+ return pb.NewBBSimClient(conn), conn
+}
diff --git a/internal/bbsimctl/commands/olt.go b/internal/bbsimctl/commands/olt.go
index bed3733..1789c86 100644
--- a/internal/bbsimctl/commands/olt.go
+++ b/internal/bbsimctl/commands/olt.go
@@ -22,6 +22,7 @@
"fmt"
"os"
"strconv"
+ "strings"
"github.com/jessevdk/go-flags"
"github.com/olekukonko/tablewriter"
@@ -29,12 +30,13 @@
"github.com/opencord/bbsim/internal/bbsimctl/config"
"github.com/opencord/cordctl/pkg/format"
log "github.com/sirupsen/logrus"
- "google.golang.org/grpc"
)
const (
- DEFAULT_OLT_DEVICE_HEADER_FORMAT = "table{{ .ID }}\t{{ .SerialNumber }}\t{{ .OperState }}\t{{ .InternalState }}\t{{ .IP }}"
- DEFAULT_PORT_HEADER_FORMAT = "table{{ .ID }}\t{{ .OperState }}"
+ DEFAULT_OLT_DEVICE_HEADER_FORMAT = "table{{ .ID }}\t{{ .SerialNumber }}\t{{ .OperState }}\t{{ .InternalState }}\t{{ .IP }}"
+ DEFAULT_OLT_RESOURCES_HEADER_FORMAT = "table{{ .Type }}\t{{ .PonPortId }}\t{{ .OnuId }}\t{{ .PortNo }}\t{{ .ResourceId }}\t{{ .FlowId }}"
+ DEFAULT_NNI_PORT_HEADER_FORMAT = "table{{ .ID }}\t{{ .OperState }}\t{{ .InternalState }}\t{{ .PacketCount }}"
+ DEFAULT_PON_PORT_HEADER_FORMAT = "table{{ .ID }}\t{{ .OperState }}\t{{ .InternalState }}\t{{ .PacketCount }}\t{{ .AllocatedOnuIds }}\t{{ .AllocatedGemPorts }}\t{{ .AllocatedAllocIds }}"
)
type OltGet struct{}
@@ -64,8 +66,16 @@
type OltShutdownAllOnus struct{}
+type oltResourcesType string
+type OltResources struct {
+ Args struct {
+ Type oltResourcesType
+ } `positional-args:"yes" required:"yes"`
+}
+
type oltOptions struct {
Get OltGet `command:"get"`
+ GetResources OltResources `command:"resources"`
NNI OltNNIs `command:"nnis"`
PON OltPONs `command:"pons"`
Shutdown OltShutdown `command:"shutdown"`
@@ -85,19 +95,12 @@
}
func getOLT() *pb.Olt {
- conn, err := grpc.Dial(config.GlobalConfig.Server, grpc.WithInsecure())
- if err != nil {
- log.Fatalf("did not connect: %v", err)
- return nil
- }
+ client, conn := connect()
defer conn.Close()
- c := pb.NewBBSimClient(conn)
-
- // Contact the server and print out its response.
ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
defer cancel()
- olt, err := c.GetOlt(ctx, &pb.Empty{})
+ olt, err := client.GetOlt(ctx, &pb.Empty{})
if err != nil {
log.Fatalf("could not get OLT: %v", err)
return nil
@@ -120,12 +123,34 @@
return nil
}
+func (o *OltResources) Execute(args []string) error {
+ client, conn := connect()
+ defer conn.Close()
+
+ resourceType := pb.OltAllocatedResourceType_Type_value[string(o.Args.Type)]
+
+ ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+ defer cancel()
+ resources, err := client.GetOltAllocatedResources(ctx, &pb.OltAllocatedResourceType{Type: pb.OltAllocatedResourceType_Type(resourceType)})
+
+ if err != nil {
+ log.Fatalf("could not get OLT resources: %v", err)
+ return nil
+ }
+
+ tableFormat := format.Format(DEFAULT_OLT_RESOURCES_HEADER_FORMAT)
+ if err := tableFormat.Execute(os.Stdout, true, resources.Resources); err != nil {
+ return err
+ }
+ return nil
+}
+
func (o *OltNNIs) Execute(args []string) error {
olt := getOLT()
printOltHeader("NNI Ports for", olt)
- tableFormat := format.Format(DEFAULT_PORT_HEADER_FORMAT)
+ tableFormat := format.Format(DEFAULT_NNI_PORT_HEADER_FORMAT)
_ = tableFormat.Execute(os.Stdout, true, olt.NNIPorts)
return nil
@@ -136,7 +161,7 @@
printOltHeader("PON Ports for", olt)
- tableFormat := format.Format(DEFAULT_PORT_HEADER_FORMAT)
+ tableFormat := format.Format(DEFAULT_PON_PORT_HEADER_FORMAT)
_ = tableFormat.Execute(os.Stdout, true, olt.PONPorts)
return nil
@@ -354,3 +379,13 @@
fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
return nil
}
+
+func (rt *oltResourcesType) Complete(match string) []flags.Completion {
+ list := make([]flags.Completion, 0)
+ for k := range pb.OltAllocatedResourceType_Type_value {
+ if strings.HasPrefix(k, strings.ToUpper(match)) && k != pb.OltAllocatedResourceType_UNKNOWN.String() {
+ list = append(list, flags.Completion{Item: k})
+ }
+ }
+ return list
+}
diff --git a/internal/bbsimctl/commands/onu.go b/internal/bbsimctl/commands/onu.go
index 78923e0..33bd5ef 100644
--- a/internal/bbsimctl/commands/onu.go
+++ b/internal/bbsimctl/commands/onu.go
@@ -30,7 +30,6 @@
"github.com/opencord/bbsim/internal/bbsimctl/config"
"github.com/opencord/cordctl/pkg/format"
log "github.com/sirupsen/logrus"
- "google.golang.org/grpc"
)
const (
@@ -127,16 +126,6 @@
_, _ = parser.AddCommand("onu", "ONU Commands", "Commands to query and manipulate ONU devices", &ONUOptions{})
}
-func connect() (pb.BBSimClient, *grpc.ClientConn) {
- conn, err := grpc.Dial(config.GlobalConfig.Server, grpc.WithInsecure())
-
- if err != nil {
- log.Fatalf("did not connect: %v", err)
- return nil, conn
- }
- return pb.NewBBSimClient(conn), conn
-}
-
func getONUs() *pb.ONUs {
client, conn := connect()
diff --git a/internal/common/logger.go b/internal/common/logger.go
index cc6e48d..ce17bb5 100644
--- a/internal/common/logger.go
+++ b/internal/common/logger.go
@@ -21,6 +21,11 @@
func SetLogLevel(logger *log.Logger, level string, caller bool) {
logger.SetReportCaller(caller)
+ Formatter := new(log.TextFormatter)
+ Formatter.TimestampFormat = "2006-01-02T15:04:05.999999999Z07:00"
+ Formatter.FullTimestamp = true
+ //Formatter.ForceColors = true
+ logger.SetFormatter(Formatter)
switch level {
case "trace":
diff --git a/internal/common/omci/create.go b/internal/common/omci/create.go
index c1e2b0b..d3c88b3 100644
--- a/internal/common/omci/create.go
+++ b/internal/common/omci/create.go
@@ -42,7 +42,7 @@
return msgObj, nil
}
-func CreateCreateResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI) ([]byte, error) {
+func CreateCreateResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI, result me.Results) ([]byte, error) {
msgObj, err := ParseCreateRequest(omciPkt)
@@ -60,7 +60,7 @@
EntityClass: msgObj.EntityClass,
EntityInstance: msgObj.EntityInstance,
},
- Result: me.Success,
+ Result: result,
}
pkt, err := Serialize(omci.CreateResponseType, response, omciMsg.TransactionID)
@@ -78,75 +78,3 @@
return pkt, nil
}
-
-// methods used by BBR to drive the OMCI state machine
-
-func CreateGalEnetRequest(tid uint16) ([]byte, error) {
- params := me.ParamData{
- EntityID: 1,
- Attributes: me.AttributeValueMap{"MaximumGemPayloadSize": 48},
- }
- meDef, _ := me.NewGalEthernetProfile(params)
- pkt, err := omci.GenFrame(meDef, omci.CreateRequestType, omci.TransactionID(tid))
- if err != nil {
- omciLogger.WithField("err", err).Fatalf("Can't generate GalEnetRequest")
- }
- return HexEncode(pkt)
-}
-
-func CreateEnableUniRequest(tid uint16, uniId uint16, enabled bool, isPtp bool) ([]byte, error) {
-
- var _enabled uint8
- if enabled {
- _enabled = uint8(1)
- } else {
- _enabled = uint8(0)
- }
-
- data := me.ParamData{
- EntityID: uniId,
- Attributes: me.AttributeValueMap{
- "AdministrativeState": _enabled,
- },
- }
- var medef *me.ManagedEntity
- var omciErr me.OmciErrors
-
- if isPtp {
- medef, omciErr = me.NewPhysicalPathTerminationPointEthernetUni(data)
- } else {
- medef, omciErr = me.NewVirtualEthernetInterfacePoint(data)
- }
- if omciErr != nil {
- return nil, omciErr.GetError()
- }
- pkt, err := omci.GenFrame(medef, omci.SetRequestType, omci.TransactionID(tid))
- if err != nil {
- omciLogger.WithField("err", err).Fatalf("Can't generate EnableUniRequest")
- }
- return HexEncode(pkt)
-}
-
-func CreateGemPortRequest(tid uint16) ([]byte, error) {
- params := me.ParamData{
- EntityID: 1,
- Attributes: me.AttributeValueMap{
- "PortId": 1,
- "TContPointer": 1,
- "Direction": 0,
- "TrafficManagementPointerForUpstream": 0,
- "TrafficDescriptorProfilePointerForUpstream": 0,
- "UniCounter": 0,
- "PriorityQueuePointerForDownStream": 0,
- "EncryptionState": 0,
- "TrafficDescriptorProfilePointerForDownstream": 0,
- "EncryptionKeyRing": 0,
- },
- }
- meDef, _ := me.NewGemPortNetworkCtp(params)
- pkt, err := omci.GenFrame(meDef, omci.CreateRequestType, omci.TransactionID(tid))
- if err != nil {
- omciLogger.WithField("err", err).Fatalf("Can't generate GemPortRequest")
- }
- return HexEncode(pkt)
-}
diff --git a/internal/common/omci/create_test.go b/internal/common/omci/create_test.go
new file mode 100644
index 0000000..33d3a3e
--- /dev/null
+++ b/internal/common/omci/create_test.go
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package omci
+
+import (
+ "github.com/google/gopacket"
+ "github.com/opencord/omci-lib-go"
+ me "github.com/opencord/omci-lib-go/generated"
+ "gotest.tools/assert"
+ "testing"
+)
+
+func omciToCreateResponse(t *testing.T, omciPkt *gopacket.Packet) *omci.CreateResponse {
+ msgLayer := (*omciPkt).Layer(omci.LayerTypeCreateResponse)
+ if msgLayer == nil {
+ t.Fatal("omci Msg layer could not be detected for CreateResponse - handling of MibSyncChan stopped")
+ }
+ msgObj, msgOk := msgLayer.(*omci.CreateResponse)
+ if !msgOk {
+ t.Fatal("omci Msg layer could not be assigned for CreateResponse - handling of MibSyncChan stopped")
+ }
+ return msgObj
+}
+
+type createArgs struct {
+ omciPkt []byte
+ result me.Results
+}
+
+type createWant struct {
+ result me.Results
+}
+
+func TestCreateResponse(t *testing.T) {
+
+ // generate a CreateRequest packet to create a GemPort
+ omciReq := &omci.CreateRequest{
+ MeBasePacket: omci.MeBasePacket{
+ EntityClass: me.GemPortNetworkCtpClassID,
+ EntityInstance: 12,
+ },
+ Attributes: me.AttributeValueMap{
+ "PortId": 0,
+ "TContPointer": 0,
+ "Direction": 0,
+ "TrafficManagementPointerForUpstream": 0,
+ "TrafficDescriptorProfilePointerForUpstream": 0,
+ "PriorityQueuePointerForDownStream": 0,
+ "TrafficDescriptorProfilePointerForDownstream": 0,
+ "EncryptionKeyRing": 0,
+ },
+ }
+ omciPkt, err := Serialize(omci.CreateRequestType, omciReq, 66)
+ if err != nil {
+ t.Fatal(err.Error())
+ }
+
+ omciPkt, _ = HexEncode(omciPkt)
+
+ tests := []struct {
+ name string
+ args createArgs
+ want createWant
+ }{
+ {"createSuccess",
+ createArgs{omciPkt, me.Success},
+ createWant{me.Success},
+ },
+ {"createProcessingError",
+ createArgs{omciPkt, me.ProcessingError},
+ createWant{me.ProcessingError},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ pkt, msg, _ := ParseOpenOltOmciPacket(tt.args.omciPkt)
+ requestPkt, _ := CreateCreateResponse(pkt, msg, tt.args.result)
+
+ omciMsg, omciPkt := omciBytesToMsg(t, requestPkt)
+
+ assert.Equal(t, omciMsg.MessageType, omci.CreateResponseType)
+
+ getResponseLayer := omciToCreateResponse(t, omciPkt)
+
+ assert.Equal(t, getResponseLayer.Result, tt.want.result)
+
+ })
+ }
+}
diff --git a/internal/common/omci/get_test.go b/internal/common/omci/get_test.go
index ca580ed..d995bba 100644
--- a/internal/common/omci/get_test.go
+++ b/internal/common/omci/get_test.go
@@ -55,12 +55,12 @@
return msgObj
}
-type args struct {
+type getArgs struct {
generatedPkt *omci.GetResponse
transactionId uint16
}
-type want struct {
+type getWant struct {
transactionId uint16
attributes map[string]interface{}
}
@@ -77,20 +77,20 @@
tests := []struct {
name string
- args args
- want want
+ args getArgs
+ want getWant
}{
{"getOnu2gResponse",
- args{createOnu2gResponse(57344, 10), 1},
- want{1, map[string]interface{}{"OpticalNetworkUnitManagementAndControlChannelOmccVersion": uint8(180)}},
+ getArgs{createOnu2gResponse(57344, 10), 1},
+ getWant{1, map[string]interface{}{"OpticalNetworkUnitManagementAndControlChannelOmccVersion": uint8(180)}},
},
{"getOnugResponse",
- args{createOnugResponse(40960, 10, sn), 1},
- want{1, map[string]interface{}{}},
+ getArgs{createOnugResponse(40960, 10, sn), 1},
+ getWant{1, map[string]interface{}{}},
},
{"getOnuDataResponse",
- args{createOnuDataResponse(32768, 10, 129), 2},
- want{2, map[string]interface{}{"MibDataSync": uint8(129)}},
+ getArgs{createOnuDataResponse(32768, 10, 129), 2},
+ getWant{2, map[string]interface{}{"MibDataSync": uint8(129)}},
},
}
for _, tt := range tests {
diff --git a/internal/common/omci/set.go b/internal/common/omci/set.go
index 64f048f..73e17df 100644
--- a/internal/common/omci/set.go
+++ b/internal/common/omci/set.go
@@ -40,7 +40,7 @@
return msgObj, nil
}
-func CreateSetResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI) ([]byte, error) {
+func CreateSetResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI, result me.Results) ([]byte, error) {
msgObj, err := ParseSetRequest(omciPkt)
@@ -59,7 +59,7 @@
EntityClass: msgObj.EntityClass,
EntityInstance: msgObj.EntityInstance,
},
- Result: me.Success,
+ Result: result,
}
pkt, err := Serialize(omci.SetResponseType, response, omciMsg.TransactionID)
diff --git a/vendor/github.com/opencord/omci-lib-go/VERSION b/vendor/github.com/opencord/omci-lib-go/VERSION
index 2a0970c..201a22c 100644
--- a/vendor/github.com/opencord/omci-lib-go/VERSION
+++ b/vendor/github.com/opencord/omci-lib-go/VERSION
@@ -1 +1 @@
-0.16.1
+0.16.2
diff --git a/vendor/github.com/opencord/omci-lib-go/messagetypes.go b/vendor/github.com/opencord/omci-lib-go/messagetypes.go
index 42a0d42..f0ff447 100644
--- a/vendor/github.com/opencord/omci-lib-go/messagetypes.go
+++ b/vendor/github.com/opencord/omci-lib-go/messagetypes.go
@@ -271,7 +271,7 @@
// DecodeFromBytes decodes the given bytes of a Create Response into this layer
func (omci *CreateResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 3)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+3)
if err != nil {
return err
}
@@ -397,7 +397,7 @@
// DecodeFromBytes decodes the given bytes of a Delete Response into this layer
func (omci *DeleteResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 1)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+1)
if err != nil {
return err
}
@@ -460,7 +460,7 @@
// DecodeFromBytes decodes the given bytes of a Set Request into this layer
func (omci *SetRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 2)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+2)
if err != nil {
return err
}
@@ -567,7 +567,7 @@
// DecodeFromBytes decodes the given bytes of a Set Response into this layer
func (omci *SetResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 5)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+5)
if err != nil {
return err
}
@@ -636,7 +636,7 @@
// DecodeFromBytes decodes the given bytes of a Get Request into this layer
func (omci *GetRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 2)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+2)
if err != nil {
return err
}
@@ -703,7 +703,7 @@
// DecodeFromBytes decodes the given bytes of a Get Response into this layer
func (omci *GetResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 3)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+3)
if err != nil {
return err
}
@@ -870,7 +870,7 @@
// DecodeFromBytes decodes the given bytes of a Get All Alarms Request into this layer
func (omci *GetAllAlarmsRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 1)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+1)
if err != nil {
return err
}
@@ -948,7 +948,7 @@
// DecodeFromBytes decodes the given bytes of a Get All Alarms Response into this layer
func (omci *GetAllAlarmsResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 2)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+2)
if err != nil {
return err
}
@@ -1021,7 +1021,7 @@
// DecodeFromBytes decodes the given bytes of a Get All Alarms Next Request into this layer
func (omci *GetAllAlarmsNextRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 2)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+2)
if err != nil {
return err
}
@@ -1097,7 +1097,7 @@
// DecodeFromBytes decodes the given bytes of a Get All Alarms Next Response into this layer
func (omci *GetAllAlarmsNextResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 4 + 28)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+4+28)
if err != nil {
return err
}
@@ -1240,7 +1240,7 @@
// DecodeFromBytes decodes the given bytes of a MIB Upload Response into this layer
func (omci *MibUploadResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 2)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+2)
if err != nil {
return err
}
@@ -1313,7 +1313,7 @@
// DecodeFromBytes decodes the given bytes of a MIB Upload Next Request into this layer
func (omci *MibUploadNextRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 2)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+2)
if err != nil {
return err
}
@@ -1386,7 +1386,7 @@
// DecodeFromBytes decodes the given bytes of a MIB Upload Next Response into this layer
func (omci *MibUploadNextResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 6)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+6)
if err != nil {
return err
}
@@ -1511,7 +1511,7 @@
// DecodeFromBytes decodes the given bytes of a MIB Reset Response into this layer
func (omci *MibResetResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 1)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+1)
if err != nil {
return err
}
@@ -1684,7 +1684,7 @@
// DecodeFromBytes decodes the given bytes of an Alarm Notification into this layer
func (omci *AlarmNotificationMsg) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 28)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+28)
if err != nil {
return err
}
@@ -1770,7 +1770,7 @@
// DecodeFromBytes decodes the given bytes of an Attribute Value Change notification into this layer
func (omci *AttributeValueChangeMsg) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 2)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+2)
if err != nil {
return err
}
@@ -1855,7 +1855,7 @@
// DecodeFromBytes decodes the given bytes of a Test Request into this layer
func (omci *TestRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 5)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+5)
if err != nil {
return err
}
@@ -1891,7 +1891,7 @@
// DecodeFromBytes decodes the given bytes of a Test Response into this layer
func (omci *TestResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 1)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+1)
if err != nil {
return err
}
@@ -1931,7 +1931,7 @@
// DecodeFromBytes decodes the given bytes of a Start Software Download Request into this layer
func (omci *StartSoftwareDownloadRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 4)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+4)
if err != nil {
return err
}
@@ -2033,7 +2033,7 @@
// DecodeFromBytes decodes the given bytes of a Start Software Download Response into this layer
func (omci *StartSoftwareDownloadResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 3)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+3)
if err != nil {
return err
}
@@ -2155,7 +2155,7 @@
// DecodeFromBytes decodes the given bytes of a Download Section Request into this layer
func (omci *DownloadSectionRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 1)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+1)
if err != nil {
return err
}
@@ -2228,7 +2228,7 @@
// DecodeFromBytes decodes the given bytes of a Download Section Response into this layer
func (omci *DownloadSectionResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 2)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+2)
if err != nil {
return err
}
@@ -2313,7 +2313,7 @@
// DecodeFromBytes decodes the given bytes of an End Software Download Request into this layer
func (omci *EndSoftwareDownloadRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 7)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+7)
if err != nil {
return err
}
@@ -2406,7 +2406,7 @@
// DecodeFromBytes decodes the given bytes of an End Software Download Response into this layer
func (omci *EndSoftwareDownloadResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 2)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+2)
if err != nil {
return err
}
@@ -2525,7 +2525,7 @@
// DecodeFromBytes decodes the given bytes of an Activate Software Request into this layer
func (omci *ActivateSoftwareRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 1)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+1)
if err != nil {
return err
}
@@ -2604,7 +2604,7 @@
// DecodeFromBytes decodes the given bytes of an Activate Softwre Response into this layer
func (omci *ActivateSoftwareResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 1)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+1)
if err != nil {
return err
}
@@ -2735,6 +2735,7 @@
//
type CommitSoftwareResponse struct {
MeBasePacket
+ Result me.Results
}
func (omci *CommitSoftwareResponse) String() string {
@@ -2744,7 +2745,7 @@
// DecodeFromBytes decodes the given bytes of a Commit Softwar Response into this layer
func (omci *CommitSoftwareResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 1)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+1)
if err != nil {
return err
}
@@ -2753,7 +2754,7 @@
if omciErr.StatusCode() != me.Success {
return omciErr.GetError()
}
- // ME needs to support End Software Download
+ // ME needs to support Commit Software
if !me.SupportsMsgType(meDefinition, me.CommitSoftware) {
return me.NewProcessingError("managed entity does not support Commit Software Message-Type")
}
@@ -2761,6 +2762,12 @@
if omci.EntityClass != me.SoftwareImageClassID {
return me.NewProcessingError("invalid Entity Class for Commit Software response")
}
+ omci.Result = me.Results(data[4])
+ if omci.Result > me.Results(6) {
+ msg := fmt.Sprintf("invalid results for Commit Software response: %v, must be 0..6",
+ omci.Result)
+ return errors.New(msg)
+ }
return nil
}
@@ -2782,7 +2789,7 @@
if omciErr.StatusCode() != me.Success {
return omciErr.GetError()
}
- // ME needs to support End Software Download
+ // ME needs to support Commit Software
if !me.SupportsMsgType(meDefinition, me.CommitSoftware) {
return me.NewProcessingError("managed entity does not support Commit Message-Type")
}
@@ -2790,6 +2797,16 @@
if omci.EntityClass != me.SoftwareImageClassID {
return me.NewProcessingError("invalid Entity Class for Commit Software response")
}
+ bytes, err := b.AppendBytes(1)
+ if err != nil {
+ return err
+ }
+ bytes[0] = byte(omci.Result)
+ if omci.Result > me.Results(6) {
+ msg := fmt.Sprintf("invalid results for Commit Software response: %v, must be 0..6",
+ omci.Result)
+ return errors.New(msg)
+ }
return nil
}
@@ -2813,7 +2830,7 @@
// DecodeFromBytes decodes the given bytes of a Synchronize Time Request into this layer
func (omci *SynchronizeTimeRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 7)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+7)
if err != nil {
return err
}
@@ -2893,7 +2910,7 @@
// DecodeFromBytes decodes the given bytes of a Synchronize Time Response into this layer
func (omci *SynchronizeTimeResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 2)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+2)
if err != nil {
return err
}
@@ -2981,7 +2998,7 @@
// DecodeFromBytes decodes the given bytes of a Reboot Request into this layer
func (omci *RebootRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 1)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+1)
if err != nil {
return err
}
@@ -3052,7 +3069,7 @@
// DecodeFromBytes decodes the given bytes of a Reboot Response into this layer
func (omci *RebootResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 1)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+1)
if err != nil {
return err
}
@@ -3123,7 +3140,7 @@
// DecodeFromBytes decodes the given bytes of a Get Next Request into this layer
func (omci *GetNextRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 4)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+4)
if err != nil {
return err
}
@@ -3194,7 +3211,7 @@
// DecodeFromBytes decodes the given bytes of a Get Next Response into this layer
func (omci *GetNextResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 3)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+3)
if err != nil {
return err
}
@@ -3350,7 +3367,7 @@
// DecodeFromBytes decodes the given bytes of a Get Current Data Request into this layer
func (omci *GetCurrentDataRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 2)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+2)
if err != nil {
return err
}
@@ -3416,7 +3433,7 @@
// DecodeFromBytes decodes the given bytes of a Get Current Data Respnse into this layer
func (omci *GetCurrentDataResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 4 + 3)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+3)
if err != nil {
return err
}
@@ -3503,7 +3520,7 @@
// DecodeFromBytes decodes the given bytes of a Set Table Request into this layer
func (omci *SetTableRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 6 + 2)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 6+2)
if err != nil {
return err
}
@@ -3540,7 +3557,7 @@
// DecodeFromBytes decodes the given bytes of a Set Table Response into this layer
func (omci *SetTableResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
// Common ClassID/EntityID decode in msgBase
- err := omci.MeBasePacket.DecodeFromBytes(data, p, 6 + 1)
+ err := omci.MeBasePacket.DecodeFromBytes(data, p, 6+1)
if err != nil {
return err
}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 93d6658..ddc585d 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -74,7 +74,7 @@
github.com/opencord/cordctl/pkg/format
# github.com/opencord/device-management-interface v0.11.0
github.com/opencord/device-management-interface/go/dmi
-# github.com/opencord/omci-lib-go v0.16.1
+# github.com/opencord/omci-lib-go v0.16.2
github.com/opencord/omci-lib-go
github.com/opencord/omci-lib-go/generated
# github.com/opencord/voltha-protos/v4 v4.0.15