/*
 * Copyright (c) 2018 - present.  Boling Consulting Solutions (bcsw.net)
 * Copyright 2020-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.
 */
 /*
 * NOTE: This file was generated, manual edits will be overwritten!
 *
 * Generated by 'goCodeGenerator.py':
 *              https://github.com/cboling/OMCI-parser/README.md
 */

package generated

import "github.com/deckarep/golang-set"

// GemPortNetworkCtpClassID is the 16-bit ID for the OMCI
// Managed entity GEM port network CTP
const GemPortNetworkCtpClassID ClassID = ClassID(268)

var gemportnetworkctpBME *ManagedEntityDefinition

// GemPortNetworkCtp (class ID #268)
//	This ME represents the termination of a GEM port on an ONU. This ME aggregates connectivity
//	functionality from the network view and alarms from the network element view as well as
//	artefacts from trails.
//
//	Instances of the GEM port network CTP ME are created and deleted by the OLT. An instance of GEM
//	port network CTP can be deleted only when no GEM IW TP or GEM port network CTP PM history data
//	are associated with it. It is the responsibility of the OLT to make sure that the ONU
//	configuration meets this condition.
//
//	In ITU-T G.984 systems, when a GEM port network CTP is created, its encryption state is by
//	default not encrypted. If the OLT wishes to configure the GEM port to use encryption, it must
//	send the appropriate PLOAM message. This applies equally to new CTPs and to CTPs that are re-
//	created after an MIB reset.
//
//	In ITU-T G.987 systems, GEM ports are dynamically encrypted. If it is intended to encrypt the
//	GEM port, the OLT must configure a key ring to be used, and the key must be known to the ONU at
//	run time.
//
//	Relationships
//		An instance of the GEM port network CTP ME may be associated with an instance of the T-CONT and
//		GEM IW TP MEs.
//
//	Attributes
//		Managed Entity Id
//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
//			(mandatory) (2-bytes)
//
//		Port_Id
//			NOTE 1 - While nothing forbids the existence of several GEM port network CTPs with the same
//			port-ID value, downstream traffic is modelled as being delivered to all such GEM port network
//			CTPs. Be aware of potential difficulties associated with defining downstream flows and
//			aggregating PM statistics.
//
//		T_Cont Pointer
//			T-CONT pointer: This attribute points to a T-CONT instance. (R,-W, setbycreate) (mandatory)
//			(2-bytes)
//
//		Direction
//			Direction:	This attribute specifies whether the GEM port is used for UNI-to-ANI (1), ANI-to-UNI
//			(2), or bidirectional (3) connection. (R,-W, setbycreate) (mandatory) (1-byte)
//
//		Traffic Management Pointer For Upstream
//			Traffic management pointer for upstream: If the traffic management option attribute in the ONU-G
//			ME is 0 (priority controlled) or 2 (priority and rate controlled), this pointer specifies the
//			priority queue ME serving this GEM port network CTP. If the traffic management option attribute
//			is 1 (rate controlled), this attribute redundantly points to the TCONT serving this GEM port
//			network CTP. (R,-W, setbycreate) (mandatory) (2-bytes)
//
//		Traffic Descriptor Profile Pointer For Upstream
//			See also Appendix II.
//
//		Uni Counter
//			UNI counter: This attribute reports the number of instances of UNI-G ME associated with this GEM
//			port network CTP. (R) (optional) (1-byte)
//
//		Priority Queue Pointer For Down Stream
//			NOTE 2 - If the GEM port network CTP is associated with more than one UNI (downstream
//			multicast), the downstream priority queue pointer defines a pattern (e.g., queue number 3 for a
//			given UNI) to be replicated (i.e., to queue number 3) at the other affected UNIs.
//
//		Encryption State
//			Encryption state: This attribute indicates the current state of the GEM port network CTP's
//			encryption. Legal values are defined to be the same as those of the security mode attribute of
//			the ONU2-G, with the exception that attribute value 0 indicates an unencrypted GEM port. (R)
//			(optional) (1-byte)
//
//		Traffic Descriptor Profile Pointer For Downstream
//			See also Appendix II.
//
//		Encryption Key Ring
//			Other values are reserved.
//
type GemPortNetworkCtp struct {
	ManagedEntityDefinition
	Attributes AttributeValueMap
}

func init() {
	gemportnetworkctpBME = &ManagedEntityDefinition{
		Name:    "GemPortNetworkCtp",
		ClassID: 268,
		MessageTypes: mapset.NewSetWith(
			Create,
			Delete,
			Get,
			Set,
		),
		AllowedAttributeMask: 0xffc0,
		AttributeDefinitions: AttributeDefinitionMap{
			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
			1:  Uint16Field("PortId", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 1),
			2:  Uint16Field("TContPointer", PointerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 2),
			3:  ByteField("Direction", EnumerationAttributeType, 0x2000, 3, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 3),
			4:  Uint16Field("TrafficManagementPointerForUpstream", PointerAttributeType, 0x1000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 4),
			5:  Uint16Field("TrafficDescriptorProfilePointerForUpstream", PointerAttributeType, 0x0800, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 5),
			6:  ByteField("UniCounter", UnsignedIntegerAttributeType, 0x0400, 0, mapset.NewSetWith(Read), false, true, false, 6),
			7:  Uint16Field("PriorityQueuePointerForDownStream", PointerAttributeType, 0x0200, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 7),
			8:  ByteField("EncryptionState", EnumerationAttributeType, 0x0100, 0, mapset.NewSetWith(Read), false, true, false, 8),
			9:  Uint16Field("TrafficDescriptorProfilePointerForDownstream", PointerAttributeType, 0x0080, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 9),
			10: ByteField("EncryptionKeyRing", EnumerationAttributeType, 0x0040, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 10),
		},
		Access:  CreatedByOlt,
		Support: UnknownSupport,
	}
}

// NewGemPortNetworkCtp (class ID 268) creates the basic
// Managed Entity definition that is used to validate an ME of this type that
// is received from or transmitted to the OMCC.
func NewGemPortNetworkCtp(params ...ParamData) (*ManagedEntity, OmciErrors) {
	return NewManagedEntity(*gemportnetworkctpBME, params...)
}
