/*
 * 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(329) // 0x0149

var virtualethernetinterfacepointBME *ManagedEntityDefinition

// VirtualEthernetInterfacePoint (Class ID: #329 / 0x0149)
//	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
//			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
//			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
//			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
//			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
//			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...)
}
