/*
 * 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"

// VirtualEthernetInterfacePointClassID is the 16-bit ID for the OMCI
// Managed entity Virtual Ethernet interface point
const VirtualEthernetInterfacePointClassID ClassID = ClassID(329)

var virtualethernetinterfacepointBME *ManagedEntityDefinition

// VirtualEthernetInterfacePoint (class ID #329)
//	This ME represents the data plane hand-off point in an ONU to a separate (non-OMCI) management
//	domain. The VEIP is managed by the OMCI, and is potentially known to the non-OMCI management
//	domain. One or more Ethernet traffic flows are present at this boundary.
//
//	Instances of this ME are automatically created and deleted by the ONU. This is necessary because
//	the required downstream priority queues are subject to physical implementation constraints. The
//	OLT may use one or more of the VEIPs created by the ONU.
//
//	It is expected that the ONU will create one VEIP for each non-OMCI management domain. At the
//	vendor's discretion, a VEIP may be created for each traffic class.
//
//	Relationships
//		An instance of this ME is associated with an instance of a virtual Ethernet interface between
//		OMCI and non-OMCI management domains.
//
//	Attributes
//		Managed Entity Id
//			Managed entity ID: This attribute uniquely identifies each instance of this ME. When used
//			independently of a cardholder and circuit pack, the ONU should assign IDs in the sequence 1, 2,
//			.... When used in conjunction with a cardholder and circuit pack, this 2 byte number indicates
//			the physical position of the VEIP. The first byte is the slot ID (defined in clause 9.1.5). The
//			second byte is the port ID, with the range 1..255. The values 0 and 0xFFFF are reserved. (R)
//			(mandatory) (2 bytes)
//
//		Administrative State
//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by this
//			ME. Administrative state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
//
//		Operational State
//			Operational state: This attribute indicates whether the ME is capable of performing its
//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
//
//		Interdomain Name
//			Interdomain name: This attribute is a character string that provides an optional way to identify
//			the VEIP to a non-OMCI management domain. The interface may also be identified by its ME ID,
//			[b-IANA] assigned port and possibly other ways. If the vendor offers no information in this
//			attribute, it should be set to a sequence of null bytes. (R,-W) (optional) (25-bytes)
//
//		Tcp_Udp Pointer
//			TCP/UDP pointer: This attribute points to an instance of the TCP/UDP config data ME, which
//			provides for OMCI management of the non-OMCI management domain's IP connectivity. If no OMCI
//			management of the non-OMCI domain's IP connectivity is required, this attribute may be omitted
//			or set to its default, a null pointer. (R,-W) (optional) (2-bytes)
//
//		Iana Assigned Port
//			IANA assigned port: This attribute contains the TCP or UDP port value as assigned by  [b-IANA]
//			for the management protocol associated with this virtual Ethernet interface. This attribute is
//			to be regarded as a hint, not as a requirement that management communications use this port; the
//			actual port and protocol are specified in the associated TCP/UDP config data ME. If no port has
//			been assigned or if the management protocol is free to be chosen at run-time, this attribute
//			should be set to 0xFFFF. (R) (mandatory) (2-bytes)
//
type VirtualEthernetInterfacePoint struct {
	ManagedEntityDefinition
	Attributes AttributeValueMap
}

func init() {
	virtualethernetinterfacepointBME = &ManagedEntityDefinition{
		Name:    "VirtualEthernetInterfacePoint",
		ClassID: 329,
		MessageTypes: mapset.NewSetWith(
			Get,
			Set,
		),
		AllowedAttributeMask: 0xf800,
		AttributeDefinitions: AttributeDefinitionMap{
			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
			1: ByteField("AdministrativeState", EnumerationAttributeType, 0x8000, 0, mapset.NewSetWith(Read, Write), false, false, false, 1),
			2: ByteField("OperationalState", EnumerationAttributeType, 0x4000, 0, mapset.NewSetWith(Read), true, true, false, 2),
			3: MultiByteField("InterdomainName", StringAttributeType, 0x2000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 3),
			4: Uint16Field("TcpUdpPointer", PointerAttributeType, 0x1000, 0, mapset.NewSetWith(Read, Write), false, true, false, 4),
			5: Uint16Field("IanaAssignedPort", UnsignedIntegerAttributeType, 0x0800, 65535, mapset.NewSetWith(Read), false, false, false, 5),
		},
		Access:  CreatedByOnu,
		Support: UnknownSupport,
		Alarms: AlarmMap{
			0: "Connecting function fail",
		},
	}
}

// NewVirtualEthernetInterfacePoint (class ID 329) 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 NewVirtualEthernetInterfacePoint(params ...ParamData) (*ManagedEntity, OmciErrors) {
	return NewManagedEntity(*virtualethernetinterfacepointBME, params...)
}
