// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * BGP Link-State NLRI (RFC 9552)
 * Copyright (C) 2025 Carmine Scarpitta
 */

#ifndef _FRR_BGP_LS_NLRI_H
#define _FRR_BGP_LS_NLRI_H

#define UNKNOWN LS_UNKNOWN
#include "link_state.h"
#undef UNKNOWN
#include "prefix.h"
#include "bgpd/bgpd.h"

/* Memory types */
DECLARE_MTYPE(BGP_LS_ATTR);

/*
 * ===========================================================================
 * Protocol and NLRI Type Definitions
 * ===========================================================================
 */

/*
 * BGP-LS Protocol-ID values
 * IANA: https://www.iana.org/assignments/bgp-ls-parameters/bgp-ls-parameters.xhtml#protocol-ids
 */
enum bgp_ls_protocol_id {
	BGP_LS_PROTO_RESERVED = 0, /* Reserved - RFC 9552 */
	BGP_LS_PROTO_ISIS_L1 = 1,  /* IS-IS Level 1 - RFC 9552 */
	BGP_LS_PROTO_ISIS_L2 = 2,  /* IS-IS Level 2 - RFC 9552 */
	BGP_LS_PROTO_OSPFV2 = 3,   /* OSPFv2 - RFC 9552 */
	BGP_LS_PROTO_DIRECT = 4,   /* Direct - RFC 9552 */
	BGP_LS_PROTO_STATIC = 5,   /* Static configuration - RFC 9552 */
	BGP_LS_PROTO_OSPFV3 = 6,   /* OSPFv3 - RFC 9552 */
	BGP_LS_PROTO_BGP = 7,	   /* BGP - RFC 9086 */
};

/*
 * BGP-LS NLRI Types
 * IANA: https://www.iana.org/assignments/bgp-ls-parameters/bgp-ls-parameters.xhtml#nlri-types
 */
enum bgp_ls_nlri_type {
	BGP_LS_NLRI_TYPE_RESERVED = 0,	  /* Reserved - RFC 9552 */
	BGP_LS_NLRI_TYPE_NODE = 1,	  /* Node NLRI - RFC 9552 */
	BGP_LS_NLRI_TYPE_LINK = 2,	  /* Link NLRI - RFC 9552 */
	BGP_LS_NLRI_TYPE_IPV4_PREFIX = 3, /* IPv4 Topology Prefix NLRI - RFC 9552 */
	BGP_LS_NLRI_TYPE_IPV6_PREFIX = 4, /* IPv6 Topology Prefix NLRI - RFC 9552 */
	BGP_LS_NLRI_TYPE_SRV6_SID = 6,	  /* SRv6 SID NLRI - RFC 9514 */
};

/*
 * ===========================================================================
 * TLV Type Definitions
 * ===========================================================================
 */

/*
 * Node Descriptor TLV Types
 * IANA: https://www.iana.org/assignments/bgp-ls-parameters/bgp-ls-parameters.xhtml#node-descriptor-link-descriptor-prefix-descriptor-attribute-tlv
 */
enum bgp_ls_node_descriptor_tlv {
	BGP_LS_TLV_LOCAL_NODE_DESC = 256,  /* Local Node Descriptors - RFC 9552, Section 5.2.1.2 */
	BGP_LS_TLV_REMOTE_NODE_DESC = 257, /* Remote Node Descriptors - RFC 9552, Section 5.2.1.3 */
	BGP_LS_TLV_AS_NUMBER = 512,	   /* Autonomous System - RFC 9552, Section 5.2.1.4 */
	BGP_LS_TLV_BGP_LS_ID = 513, /* BGP-LS Identifier (deprecated) - RFC 9552, Section 5.2.1.4 */
	BGP_LS_TLV_OSPF_AREA_ID = 514,	/* OSPF Area-ID - RFC 9552, Section 5.2.1.4 */
	BGP_LS_TLV_IGP_ROUTER_ID = 515, /* IGP Router-ID - RFC 9552, Section 5.2.1.4 */
	BGP_LS_TLV_BGP_ROUTER_ID = 516, /* BGP Router-ID - RFC 9086 */
};

/*
 * Link Descriptor TLV Types
 * IANA: https://www.iana.org/assignments/bgp-ls-parameters/bgp-ls-parameters.xhtml#node-descriptor-link-descriptor-prefix-descriptor-attribute-tlv
 */
enum bgp_ls_link_descriptor_tlv {
	BGP_LS_TLV_LINK_ID = 258, /* Link Local/Remote Identifiers - RFC 9552, Section 5.2.2 */
	BGP_LS_TLV_IPV4_INTF_ADDR = 259,  /* IPv4 interface address - RFC 9552, Section 5.2.2 */
	BGP_LS_TLV_IPV4_NEIGH_ADDR = 260, /* IPv4 neighbor address - RFC 9552, Section 5.2.2 */
	BGP_LS_TLV_IPV6_INTF_ADDR = 261,  /* IPv6 interface address - RFC 9552, Section 5.2.2 */
	BGP_LS_TLV_IPV6_NEIGH_ADDR = 262, /* IPv6 neighbor address - RFC 9552, Section 5.2.2 */
	BGP_LS_TLV_MT_ID = 263, /* Multi-Topology Identifier - RFC 9552, Section 5.2.2.1 */
	BGP_LS_TLV_REMOTE_AS_NUMBER = 270, /* Remote AS Number - draft-ietf-idr-bgpls-inter-as-topology-ext */
};

/*
 * SRv6 SID Descriptor TLV Types (RFC 9514, Section 6)
 * Used in the SRv6 SID NLRI SID Descriptors field
 */
enum bgp_ls_srv6_sid_descriptor_tlv {
	BGP_LS_TLV_SRV6_SID_INFO = 518, /* SRv6 SID Information - RFC 9514, Section 6.1 */
};

/*
 * Prefix Descriptor TLV Types
 * IANA: https://www.iana.org/assignments/bgp-ls-parameters/bgp-ls-parameters.xhtml#node-descriptor-link-descriptor-prefix-descriptor-attribute-tlv
 */
enum bgp_ls_prefix_descriptor_tlv {
	BGP_LS_TLV_OSPF_ROUTE_TYPE = 264, /* OSPF Route Type - RFC 9552, Section 5.2.3.1 */
	BGP_LS_TLV_IP_REACH_INFO = 265, /* IP Reachability Information - RFC 9552, Section 5.2.3.2 */
	BGP_LS_TLV_BGP_ROUTE_TYPE = 535, /* BGP Route Type - draft-ietf-idr-bgp-ls-bgp-only-fabric */
};

/*
 * OSPF Route Type Values (for TLV 264)
 * RFC 9552, Section 5.2.3.1
 */
enum bgp_ls_ospf_route_type {
	BGP_LS_OSPF_RT_INTRA_AREA = 1, /* Intra-Area */
	BGP_LS_OSPF_RT_INTER_AREA = 2, /* Inter-Area */
	BGP_LS_OSPF_RT_EXTERNAL_1 = 3, /* External Type 1 */
	BGP_LS_OSPF_RT_EXTERNAL_2 = 4, /* External Type 2 */
	BGP_LS_OSPF_RT_NSSA_1 = 5,     /* NSSA Type 1 */
	BGP_LS_OSPF_RT_NSSA_2 = 6,     /* NSSA Type 2 */
};

/*
 * BGP Route Type Values
 * draft-ietf-idr-bgp-ls-bgp-only-fabric-04, Section 4.3
 */
enum bgp_ls_bgp_route_type {
	BGP_LS_BGP_RT_LOCAL = 1,	 /* Local interface prefix (e.g., Loopback) */
	BGP_LS_BGP_RT_ATTACHED = 2,	 /* Directly attached node's prefix (e.g., host) */
	BGP_LS_BGP_RT_EXTERNAL_BGP = 3,	 /* Prefix learned via EBGP */
	BGP_LS_BGP_RT_INTERNAL_BGP = 4,	 /* Prefix learned via IBGP */
	BGP_LS_BGP_RT_REDISTRIBUTED = 5, /* Prefix redistributed into BGP */
};


/*
 * ===========================================================================
 * SRv6 Structures (RFC 9514)
 * ===========================================================================
 */


/*
 * SRv6 SID Structure TLV (RFC 9514, Section 8, Type 1252)
 * Also used as sub-TLV of SRv6 End.X SID and LAN End.X SID TLVs
 */
struct bgp_ls_srv6_sid_structure {
	uint8_t lb_len;  /* Locator Block length in bits */
	uint8_t ln_len;  /* Locator Node length in bits */
	uint8_t fun_len; /* Function length in bits */
	uint8_t arg_len; /* Argument length in bits */
};

/*
 * SRv6 End.X SID entry (RFC 9514, Section 4.1, Type 1106)
 * Multiple instances may appear in the BGP-LS Attribute of a Link NLRI.
 */
/* SRv6 End.X SID (TLV 1106, RFC 9514 Section 4.1) - point-to-point adjacency */
struct bgp_ls_srv6_endx_sid {
	uint16_t endpoint_behavior; /* Endpoint Behavior code point (RFC 8986) */
	uint8_t flags;		    /* Flags (B/S/P for BGP EPE, or from IS-IS/OSPFv3) */
	uint8_t algo;		    /* Algorithm */
	uint8_t weight;		    /* Weight for load balancing */
	struct in6_addr sid;	    /* 128-bit SRv6 SID */
	bool has_structure;	    /* SID Structure sub-TLV present */
	struct bgp_ls_srv6_sid_structure structure; /* SID Structure sub-TLV */
};

/* SRv6 LAN End.X SID (TLV 1107 IS-IS / TLV 1108 OSPFv3, RFC 9514 Section 4.2) - LAN adjacency */
struct bgp_ls_srv6_lan_endx_sid {
	uint16_t endpoint_behavior; /* Endpoint Behavior code point (RFC 8986) */
	uint8_t flags;		    /* Flags */
	uint8_t algo;		    /* Algorithm */
	uint8_t weight;		    /* Weight for load balancing */
	bool is_isis;		    /* true = IS-IS (TLV 1107), false = OSPFv3 (TLV 1108) */
	struct in6_addr sid;	    /* 128-bit SRv6 SID */
	union {
		uint8_t sysid[ISO_SYS_ID_LEN]; /* IS-IS Neighbor System ID (TLV 1107) */
		struct in_addr router_id;      /* OSPFv3 Neighbor Router-ID (TLV 1108) */
	} neighbor;
	bool has_structure;	    /* SID Structure sub-TLV present */
	struct bgp_ls_srv6_sid_structure structure; /* SID Structure sub-TLV */
};

/*
 * BGP-LS Attribute TLV Types
 * IANA: https://www.iana.org/assignments/bgp-ls-parameters/bgp-ls-parameters.xhtml#node-descriptor-link-descriptor-prefix-descriptor-attribute-tlv
 */

enum bgp_ls_attr_tlv {
	/* Node Attribute TLVs (RFC 9552 Section 5.3.1) */
	BGP_LS_ATTR_NODE_FLAG_BITS = 1024,  /* Node Flag Bits */
	BGP_LS_ATTR_NODE_NAME = 1026,	    /* Node Name */
	BGP_LS_ATTR_ISIS_AREA_ID = 1027,    /* IS-IS Area Identifier */

	/* Node Attribute TLVs (RFC 9085 Section 2.1) */
	BGP_LS_ATTR_SR_CAPABILITIES = 1034, /* SR Capabilities */
	BGP_LS_ATTR_SR_ALGORITHM = 1035,    /* SR Algorithm */
	BGP_LS_ATTR_SR_LOCAL_BLOCK = 1036,  /* SR Local Block */
	BGP_LS_ATTR_SRMS_PREFERENCE = 1037, /* SRMS Preference */

	/* Node Attribute TLVs (RFC 9514 Section 3.1) */
	BGP_LS_ATTR_SRV6_CAPABILITIES = 1038, /* SRv6 Capabilities */

	/* Node Attribute TLVs (RFC 8814) */
	BGP_LS_ATTR_NODE_MSD = 266,         /* Node MSD */

	/* Link Attribute TLVs (RFC 9552 Section 4.3) */
	BGP_LS_ATTR_IPV4_ROUTER_ID_LOCAL = 1028,      /* IPv4 Router-ID of Local Node */
	BGP_LS_ATTR_IPV6_ROUTER_ID_LOCAL = 1029,      /* IPv6 Router-ID of Local Node */
	BGP_LS_ATTR_IPV4_ROUTER_ID_REMOTE = 1030,     /* IPv4 Router-ID of Remote Node */
	BGP_LS_ATTR_IPV6_ROUTER_ID_REMOTE = 1031,     /* IPv6 Router-ID of Remote Node */
	BGP_LS_ATTR_ADMIN_GROUP = 1088,		      /* Administrative Group (Color) */
	BGP_LS_ATTR_MAX_LINK_BW = 1089,		      /* Maximum Link Bandwidth */
	BGP_LS_ATTR_MAX_RESV_BW = 1090,		      /* Maximum Reservable Link Bandwidth */
	BGP_LS_ATTR_UNRESV_BW = 1091,		      /* Unreserved Bandwidth */
	BGP_LS_ATTR_TE_DEFAULT_METRIC = 1092,	      /* TE Default Metric */
	BGP_LS_ATTR_LINK_PROTECTION_TYPE = 1093,      /* Link Protection Type */
	BGP_LS_ATTR_MPLS_PROTOCOL_MASK = 1094,	      /* MPLS Protocol Mask */
	BGP_LS_ATTR_IGP_METRIC = 1095,		      /* IGP Metric */
	BGP_LS_ATTR_SRLG = 1096,		      /* Shared Risk Link Group */
	BGP_LS_ATTR_OPAQUE_LINK_ATTR = 1097,	      /* Opaque Link Attribute */
	BGP_LS_ATTR_LINK_NAME = 1098,		      /* Link Name */
	BGP_LS_ATTR_ADJ_SID = 1099,		      /* Adjacency SID */
	BGP_LS_ATTR_LAN_ADJ_SID = 1100,		      /* LAN Adjacency SID */
	BGP_LS_ATTR_PEER_NODE_SID = 1101,	      /* PeerNode SID */
	BGP_LS_ATTR_PEER_ADJ_SID = 1102,	      /* PeerAdj SID */
	BGP_LS_ATTR_PEER_SET_SID = 1103,	      /* PeerSet SID */
	BGP_LS_ATTR_LINK_MSD = 1104,		      /* Link MSD */

	/* Link Attribute TLVs (RFC 9514 Section 4) */
	BGP_LS_ATTR_SRV6_ENDX_SID = 1106,	      /* SRv6 End.X SID */
	BGP_LS_ATTR_SRV6_LAN_ENDX_SID_ISIS = 1107,   /* SRv6 LAN End.X SID (IS-IS) */
	BGP_LS_ATTR_SRV6_LAN_ENDX_SID_OSPF = 1108,   /* SRv6 LAN End.X SID (OSPFv3) */

	BGP_LS_ATTR_UNIDIRECTIONAL_LINK_DELAY = 1114, /* Unidirectional Link Delay */
	BGP_LS_ATTR_MIN_MAX_UNIDIRECTIONAL_LINK_DELAY = 1115, /* Min/Max Unidirectional Link Delay */
	BGP_LS_ATTR_UNIDIRECTIONAL_DELAY_VARIATION = 1116,    /* Unidirectional Delay Variation */
	BGP_LS_ATTR_UNIDIRECTIONAL_LINK_LOSS = 1117,	      /* Unidirectional Link Loss */
	BGP_LS_ATTR_UNIDIRECTIONAL_RESIDUAL_BANDWIDTH = 1118, /* Unidirectional Residual Bandwidth */
	BGP_LS_ATTR_UNIDIRECTIONAL_AVAILABLE_BANDWIDTH = 1119, /* Unidirectional Available Bandwidth */
	BGP_LS_ATTR_UNIDIRECTIONAL_UTILIZED_BANDWIDTH = 1120, /* Unidirectional Utilized Bandwidth */
	BGP_LS_ATTR_EXTENDED_ADMIN_GROUP = 1173,	      /* Extended Administrative Group */

	/* Prefix Attribute TLVs (RFC 9552 Section 4.3) */
	BGP_LS_ATTR_IGP_FLAGS = 1152,	       /* IGP Flags */
	BGP_LS_ATTR_ROUTE_TAG = 1153,	       /* Route Tag */
	BGP_LS_ATTR_EXTENDED_TAG = 1154,       /* Extended Tag */
	BGP_LS_ATTR_PREFIX_METRIC = 1155,      /* Prefix Metric */
	BGP_LS_ATTR_OSPF_FWD_ADDR = 1156,      /* OSPF Forwarding Address */
	BGP_LS_ATTR_OPAQUE_PREFIX_ATTR = 1157, /* Opaque Prefix Attribute */
	BGP_LS_ATTR_PREFIX_SID = 1158,	       /* Prefix SID */
	BGP_LS_ATTR_RANGE = 1159,	       /* Range */
	BGP_LS_ATTR_SID_LABEL = 1161,	       /* SID/Label */
	BGP_LS_ATTR_PREFIX_ATTR_FLAGS = 1170,  /* Prefix Attribute Flags */
	BGP_LS_ATTR_SRV6_LOCATOR = 1162,       /* SRv6 Locator - RFC 9514, Section 5.1 */

	/* SRv6 SID Attribute TLVs (RFC 9514 Section 7.1) */
	BGP_LS_ATTR_SRV6_ENDPOINT_BEHAVIOR = 1250,  /* SRv6 Endpoint Behavior */
	BGP_LS_ATTR_SRV6_SID_STRUCTURE = 1252,	     /* SRv6 SID Structure */
};

/*
 * ===========================================================================
 * Constants and Macros
 * ===========================================================================
 */

/* Bit positions for Node Descriptor TLVs */
#define BGP_LS_NODE_DESC_AS_BIT             (1ULL << 0)
#define BGP_LS_NODE_DESC_BGP_LS_ID_BIT      (1ULL << 1)
#define BGP_LS_NODE_DESC_OSPF_AREA_BIT      (1ULL << 2)
#define BGP_LS_NODE_DESC_IGP_ROUTER_BIT     (1ULL << 3)
#define BGP_LS_NODE_DESC_BGP_ROUTER_ID_BIT  (1ULL << 4)

/* Bit positions for Link Descriptor TLVs */
#define BGP_LS_LINK_DESC_LINK_ID_BIT     (1ULL << 0)
#define BGP_LS_LINK_DESC_IPV4_INTF_BIT   (1ULL << 1)
#define BGP_LS_LINK_DESC_IPV4_NEIGH_BIT  (1ULL << 2)
#define BGP_LS_LINK_DESC_IPV6_INTF_BIT   (1ULL << 3)
#define BGP_LS_LINK_DESC_IPV6_NEIGH_BIT  (1ULL << 4)
#define BGP_LS_LINK_DESC_MT_ID_BIT       (1ULL << 5)
#define BGP_LS_LINK_DESC_REMOTE_AS_BIT   (1ULL << 6)

/* Bit positions for Prefix Descriptor TLVs */
#define BGP_LS_PREFIX_DESC_MT_ID_BIT           (1ULL << 0)
#define BGP_LS_PREFIX_DESC_OSPF_ROUTE_BIT      (1ULL << 1)
#define BGP_LS_PREFIX_DESC_IP_REACH_BIT        (1ULL << 2)
#define BGP_LS_PREFIX_DESC_BGP_ROUTE_TYPE_BIT  (1ULL << 3)

/* Bit positions for SRv6 SID Descriptor TLVs */
#define BGP_LS_SRV6_SID_DESC_INFO_BIT          (1ULL << 0)
#define BGP_LS_SRV6_SID_DESC_MT_ID_BIT         (1ULL << 1)

/* Maximum number of MT-IDs per descriptor */
#define BGP_LS_MAX_MT_ID 16

/*
 * IGP Router-ID Length Constants (RFC 9552 Section 5.2.1.4)
 */
#define BGP_LS_IGP_ROUTER_ID_OSPF_LEN	     4 /* OSPFv2/v3 non-pseudonode: Router-ID */
#define BGP_LS_IGP_ROUTER_ID_ISIS_LEN	     6 /* IS-IS non-pseudonode: ISO System-ID */
#define BGP_LS_IGP_ROUTER_ID_ISIS_PSEUDO_LEN 7 /* IS-IS pseudonode: System-ID + PSN */
#define BGP_LS_IGP_ROUTER_ID_OSPF_PSEUDO_LEN 8 /* OSPFv2/v3 pseudonode: Router-ID + Interface ID */
#define BGP_LS_IGP_ROUTER_ID_DIRECT_IPV4_LEN IPV4_MAX_BYTELEN /* Direct/Static: IPv4 address */
#define BGP_LS_IGP_ROUTER_ID_DIRECT_IPV6_LEN IPV6_MAX_BYTELEN /* Direct/Static: IPv6 address */
#define BGP_LS_IGP_ROUTER_ID_MIN_SIZE	     BGP_LS_IGP_ROUTER_ID_OSPF_LEN /* Minimum size (4 bytes) */
#define BGP_LS_IGP_ROUTER_ID_MAX_SIZE                                                             \
	BGP_LS_IGP_ROUTER_ID_DIRECT_IPV6_LEN /* Maximum size (16 bytes) */

/*
 * TLV Size Constants (for wire format size calculation)
 */
#define BGP_LS_TLV_HDR_SIZE	4 /* TLV Type (2) + Length (2) */
#define BGP_LS_PROTOCOL_ID_SIZE 1 /* Protocol-ID field */
#define BGP_LS_IDENTIFIER_SIZE	8 /* Identifier field (Instance ID) */
#define BGP_LS_NLRI_HDR_SIZE                                                                      \
	(BGP_LS_PROTOCOL_ID_SIZE + BGP_LS_IDENTIFIER_SIZE) /* Protocol-ID + Identifier */
#define BGP_LS_NLRI_TYPE_SIZE	2			   /* NLRI Type field */
#define BGP_LS_NLRI_LENGTH_SIZE 2			   /* NLRI Length field */
/* Minimum NLRI length: Protocol-ID + Identifier + Node Descriptor TLV header + min descriptor */
#define BGP_LS_NLRI_MIN_LENGTH                                                                    \
	(BGP_LS_PROTOCOL_ID_SIZE + BGP_LS_IDENTIFIER_SIZE + BGP_LS_TLV_HDR_SIZE)
#define BGP_LS_AS_NUMBER_SIZE	    4		     /* AS Number value */
#define BGP_LS_BGP_LS_ID_SIZE	    4		     /* BGP-LS Identifier value */
#define BGP_LS_OSPF_AREA_ID_SIZE    4		     /* OSPF Area-ID value */
#define BGP_LS_LINK_ID_SIZE	    8		     /* Link Local ID (4) + Remote ID (4) */
#define BGP_LS_IPV4_ADDR_SIZE	    IPV4_MAX_BYTELEN /* IPv4 address */
#define BGP_LS_IPV6_ADDR_SIZE	    IPV6_MAX_BYTELEN /* IPv6 address */
#define BGP_LS_OSPF_ROUTE_TYPE_SIZE 1		     /* OSPF Route Type value */
#define BGP_LS_MT_ID_SIZE	    2		     /* Multi-Topology ID (per entry) */
#define BGP_LS_PREFIX_LEN_SIZE	    1		     /* IP prefix length field */
#define BGP_LS_BGP_ROUTER_ID_SIZE   4		     /* BGP Router-ID value */
#define BGP_LS_BGP_ROUTE_TYPE_SIZE  1		     /* BGP Route Type value */

/*
 * IGP Metric can be 1, 2, or 3 bytes
 */
#define BGP_LS_IGP_METRIC_MAX_LEN 3

/*
 * IGP MSD Type
 * RFC 8491 Section 6, Figure 6
 */
#define BGP_LS_IGP_MSD_TYPE_BASE_MPLS 1

/*
 * SRv6 TLV fixed payload sizes (RFC 9514)
 */
#define BGP_LS_SRV6_CAPABILITIES_SIZE 4 /* Flags (2) + Reserved (2) */
#define BGP_LS_SRV6_SID_STRUCTURE_SIZE		4  /* LB Length (1) + LN Length (1) + Fun Length (1) + Arg Length (1) */
#define BGP_LS_SRV6_ENDX_SID_MIN_SIZE		  22 /* Behavior (2) + Flags (1) + Algo (1) + Weight (1) + Rsvd (1) + SID (16) */
#define BGP_LS_SRV6_LAN_ENDX_SID_ISIS_MIN_SIZE	  28 /* Behavior (2) + Flags (1) + Algo (1) + Weight (1) + Rsvd (1) + SID (16) + Neighbor Sys-ID (6) */
#define BGP_LS_SRV6_LAN_ENDX_SID_OSPF_MIN_SIZE	  26 /* Behavior (2) + Flags (1) + Algo (1) + Weight (1) + Rsvd (1) + SID (16) + Neighbor Router-ID (4) */
#define BGP_LS_SRV6_LOCATOR_MIN_SIZE		8  /* Flags (1) + Algo (1) + Reserved (2) + Metric (4) */
#define BGP_LS_SRV6_ENDPOINT_BEHAVIOR_SIZE	4  /* Behavior (2) + Flags (1) + Algo (1) */
#define BGP_LS_SRV6_SID_INFO_SIZE		16 /* 128-bit SRv6 SID */

/*
 * Maximum values for arrays
 */
#define BGP_LS_MAX_SRLG	      64 /* Maximum SRLGs per link */
#define BGP_LS_MAX_UNRESV_BW  8	 /* 8 priority classes */
#define BGP_LS_MAX_ROUTE_TAGS 16 /* Maximum route tags */
#define BGP_LS_MAX_EXT_ADMIN_GROUPS 256 /* Maximum number of admin groups in Extended Admin Group TLV */
#define BGP_LS_MAX_NODE_NAME_LEN 255	/* Maximum node name length */
#define BGP_LS_MAX_LINK_NAME_LEN 255	/* Maximum link name length */
#define BGP_LS_MAX_SRV6_SIDS	 256	/* Maximum SRv6 SIDs per TLV type */

/*
 * Bit positions for attribute presence bitmasks
 */
#define BGP_LS_ATTR_NODE_FLAGS_BIT             (1ULL << 0)
#define BGP_LS_ATTR_NODE_NAME_BIT              (1ULL << 1)
#define BGP_LS_ATTR_ISIS_AREA_BIT              (1ULL << 2)
#define BGP_LS_ATTR_SR_CAPABILITIES_BIT        (1ULL << 3)
#define BGP_LS_ATTR_SR_ALGORITHM_BIT           (1ULL << 4)
#define BGP_LS_ATTR_SR_LOCAL_BLOCK_BIT         (1ULL << 5)
#define BGP_LS_ATTR_NODE_MSD_BIT               (1ULL << 6)
#define BGP_LS_ATTR_IPV4_ROUTER_ID_LOCAL_BIT   (1ULL << 7)
#define BGP_LS_ATTR_IPV6_ROUTER_ID_LOCAL_BIT   (1ULL << 8)
#define BGP_LS_ATTR_IPV4_ROUTER_ID_REMOTE_BIT  (1ULL << 9)
#define BGP_LS_ATTR_IPV6_ROUTER_ID_REMOTE_BIT  (1ULL << 10)
#define BGP_LS_ATTR_ADMIN_GROUP_BIT            (1ULL << 11)
#define BGP_LS_ATTR_MAX_LINK_BW_BIT            (1ULL << 12)
#define BGP_LS_ATTR_MAX_RESV_BW_BIT            (1ULL << 13)
#define BGP_LS_ATTR_UNRESV_BW_BIT              (1ULL << 14)
#define BGP_LS_ATTR_TE_METRIC_BIT              (1ULL << 15)
#define BGP_LS_ATTR_LINK_PROTECTION_BIT        (1ULL << 16)
#define BGP_LS_ATTR_MPLS_PROTOCOL_BIT          (1ULL << 17)
#define BGP_LS_ATTR_IGP_METRIC_BIT             (1ULL << 18)
#define BGP_LS_ATTR_SRLG_BIT                   (1ULL << 19)
#define BGP_LS_ATTR_LINK_NAME_BIT              (1ULL << 20)
#define BGP_LS_ATTR_ADJ_SID_BIT                (1ULL << 21)
#define BGP_LS_ATTR_LINK_MSD_BIT               (1ULL << 22)
#define BGP_LS_ATTR_EXT_ADMIN_GROUP_BIT        (1ULL << 23)
#define BGP_LS_ATTR_DELAY_BIT                  (1ULL << 24)
#define BGP_LS_ATTR_MIN_MAX_DELAY_BIT          (1ULL << 25)
#define BGP_LS_ATTR_JITTER_BIT                 (1ULL << 26)
#define BGP_LS_ATTR_PKT_LOSS_BIT               (1ULL << 27)
#define BGP_LS_ATTR_RESIDUAL_BW_BIT            (1ULL << 28)
#define BGP_LS_ATTR_AVAILABLE_BW_BIT           (1ULL << 29)
#define BGP_LS_ATTR_UTILIZED_BW_BIT            (1ULL << 30)
#define BGP_LS_ATTR_IGP_FLAGS_BIT              (1ULL << 31)
#define BGP_LS_ATTR_ROUTE_TAG_BIT              (1ULL << 32)
#define BGP_LS_ATTR_EXTENDED_TAG_BIT           (1ULL << 33)
#define BGP_LS_ATTR_PREFIX_METRIC_BIT          (1ULL << 34)
#define BGP_LS_ATTR_OSPF_FWD_ADDR_BIT          (1ULL << 35)
#define BGP_LS_ATTR_PREFIX_SID_BIT             (1ULL << 36)
#define BGP_LS_ATTR_RANGE_BIT                  (1ULL << 37)
#define BGP_LS_ATTR_SID_LABEL_BIT              (1ULL << 38)
#define BGP_LS_ATTR_SRV6_LOCATOR_BIT           (1ULL << 39)
/* SRv6 attribute bits (RFC 9514) */
#define BGP_LS_ATTR_SRV6_CAPABILITIES_BIT      (1ULL << 40)
#define BGP_LS_ATTR_SRV6_ENDX_SID_BIT	       (1ULL << 41)
#define BGP_LS_ATTR_SRV6_LAN_ENDX_SID_BIT      (1ULL << 42)
#define BGP_LS_ATTR_SRV6_ENDPOINT_BEHAVIOR_BIT (1ULL << 43)
#define BGP_LS_ATTR_SRV6_SID_STRUCTURE_BIT     (1ULL << 44)
/* Multi-Topology IDs - RFC 9552 §5.2.1.4 */
#define BGP_LS_ATTR_MT_ID_BIT                  (1ULL << 45)

/*
 * Node Flag Bits (TLV 1024)
 * RFC 9552 Section 4.3.1
 */
#define BGP_LS_NODE_FLAG_OVERLOAD 0x80 /* Overload Bit */
#define BGP_LS_NODE_FLAG_ATTACHED 0x40 /* Attached Bit */
#define BGP_LS_NODE_FLAG_EXTERNAL 0x20 /* External Bit */
#define BGP_LS_NODE_FLAG_ABR	  0x10 /* ABR Bit */
#define BGP_LS_NODE_FLAG_ROUTER	  0x08 /* Router Bit */
#define BGP_LS_NODE_FLAG_V6	  0x04 /* V6 Bit */

/*
 * IGP Prefix Flags (TLV 1152)
 * RFC 9552 Section 4.3.4.1
 */
#define BGP_LS_PREFIX_FLAG_DOWN	      0x80 /* IS-IS Down Bit */
#define BGP_LS_PREFIX_FLAG_NO_UNICAST 0x40 /* OSPF No-Unicast Bit */
#define BGP_LS_PREFIX_FLAG_LOCAL      0x20 /* OSPF Local Address Bit */
#define BGP_LS_PREFIX_FLAG_PROPAGATE  0x10 /* OSPF Propagate NSSA Bit */
#define BGP_LS_PREFIX_FLAG_NODE	      0x08 /* Node Prefix Attached Flag */

/*
 * IGP Prefix SID Flags (TLV 1158)
 * RFC 9085 Section 2.3.1
 */
#define BGP_LS_PREFIX_SID_FLAG_VALUE 0x08 /* Same for IS-IS, OSPFv2, OSPFv3 */
#define BGP_LS_PREFIX_SID_FLAG_LOCAL 0x04 /* Same for IS-IS, OSPFv2, OSPFv3 */

/*
 * ===========================================================================
 * Descriptor Structures (RFC 9552 Section 5.2)
 * ===========================================================================
 *
 * These structures identify topology elements (nodes, links, prefixes)
 * per RFC 9552 Section 5.2
 */

/*
 * Node Descriptor - Identifies a router/node in the topology
 * RFC 9552, Section 5.2.1
 */
struct bgp_ls_node_descriptor {
	uint16_t present_tlvs;	   /* Bitmask of present TLVs */
	as_t asn;		   /* Autonomous System Number */
	uint32_t bgp_ls_id;	   /* BGP-LS Identifier (deprecated) */
	uint32_t ospf_area_id;	   /* OSPF Area ID */
	uint8_t igp_router_id_len; /* Length of IGP Router ID (4-16 bytes) */
	union {
		uint8_t sysid[BGP_LS_IGP_ROUTER_ID_ISIS_LEN]; /* IS-IS non-pseudonode: 6-byte ISO System-ID */
		struct {
			uint8_t sysid[BGP_LS_IGP_ROUTER_ID_ISIS_LEN]; /* IS-IS pseudonode: ISO System-ID */
			uint8_t psn; /* IS-IS pseudonode: Pseudonode ID (non-zero) */
		} pseudo_isis;
		struct in_addr ospf; /* OSPFv2 non-pseudonode: Router-ID */
		struct {
			struct in_addr router_id; /* OSPFv2 pseudonode: DIS Router-ID */
			struct in_addr ifaddr;	  /* OSPFv2 pseudonode: Interface IP Address */
		} pseudo_ospf;
		struct in_addr ipv4;			    /* Direct/Static: IPv4 address */
		struct in6_addr ipv6;			    /* Direct/Static: IPv6 address */
		uint8_t raw[BGP_LS_IGP_ROUTER_ID_MAX_SIZE]; /* Raw access / encode-decode */
	} igp_router_id;
	struct in_addr bgp_router_id;			      /* BGP Router-ID (TLV 516) */
};

/*
 * Link Descriptor - Identifies a link between two nodes
 * RFC 9552, Section 5.2.2
 */
struct bgp_ls_link_descriptor {
	uint32_t present_tlvs;		 /* Bitmask of present TLVs */
	uint32_t link_local_id;		 /* Link Local Identifier */
	uint32_t link_remote_id;	 /* Link Remote Identifier */
	struct in_addr ipv4_intf_addr;	 /* IPv4 Interface Address */
	struct in_addr ipv4_neigh_addr;	 /* IPv4 Neighbor Address */
	struct in6_addr ipv6_intf_addr;	 /* IPv6 Interface Address */
	struct in6_addr ipv6_neigh_addr; /* IPv6 Neighbor Address */
	as_t remote_asn;		 /* Remote AS Number */
	uint16_t mt_id;			 /* Multi-Topology ID (TLV 263) */
};

/*
 * Prefix Descriptor - Identifies an IP prefix advertised by a node
 * RFC 9552, Section 5.2.3
 */
struct bgp_ls_prefix_descriptor {
	uint16_t present_tlvs;			     /* Bitmask of present TLVs */
	uint16_t mt_id;				     /* Multi-Topology ID (TLV 263) */
	enum bgp_ls_ospf_route_type ospf_route_type; /* OSPF Route Type */
	enum bgp_ls_bgp_route_type bgp_route_type;   /* BGP Route Type */
	struct prefix prefix;			     /* IP prefix (IPv4 or IPv6) */
};

/*
 * SRv6 SID Descriptor (RFC 9514, Section 6)
 * Identifies a specific SRv6 SID within an SRv6 SID NLRI.
 * MUST contain exactly one SRv6 SID Information TLV (518).
 */
struct bgp_ls_srv6_sid_descriptor {
	uint16_t present_tlvs;		      /* Bitmask of present SID descriptor TLVs */
	struct in6_addr sid;		      /* 128-bit SRv6 SID (from TLV 518) */
	uint16_t mt_id;			      /* Multi-Topology ID (from TLV 263) */
};

/*
 * ===========================================================================
 * BGP-LS NLRI Structures (RFC 9552 Section 5.2)
 * ===========================================================================
 *
 * These structures represent complete BGP-LS NLRIs as exchanged in UPDATE
 * messages. Each NLRI consists of:
 *   1. Protocol-ID - IGP protocol that originated the information
 *   2. Identifier - 64-bit instance identifier for disambiguation
 *   3. NLRI-specific descriptors that identify the topology element
 */

/*
 * Node NLRI (Type 1) - Identifies a router/node in the topology
 * RFC 9552, Section 5.2
 *
 *  0                   1                   2                   3
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 * +-+-+-+-+-+-+-+-+
 * |  Protocol-ID  |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                           Identifier                          |
 * |                            (64 bits)                          |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * //               Local Node Descriptors (variable)             //
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */
struct bgp_ls_node_nlri {
	enum bgp_ls_protocol_id protocol_id;	  /* IGP protocol */
	uint64_t identifier;			  /* Instance identifier */
	struct bgp_ls_node_descriptor local_node; /* Node identity */
};

/*
 * Link NLRI (Type 2) - Identifies a link between two nodes
 * RFC 9552, Section 5.2
 *
 *  0                   1                   2                   3
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 * +-+-+-+-+-+-+-+-+
 * |  Protocol-ID  |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                           Identifier                          |
 * |                            (64 bits)                          |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * //               Local Node Descriptors (variable)             //
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * //               Remote Node Descriptors (variable)            //
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * //                  Link Descriptors (variable)                //
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */
struct bgp_ls_link_nlri {
	enum bgp_ls_protocol_id protocol_id;	   /* IGP protocol */
	uint64_t identifier;			   /* Instance identifier */
	struct bgp_ls_node_descriptor local_node;  /* Source node */
	struct bgp_ls_node_descriptor remote_node; /* Destination node */
	struct bgp_ls_link_descriptor link_desc;   /* Link identity */
};

/*
 * Prefix NLRI (Type 3/4) - Identifies an IP prefix advertised by a node
 * RFC 9552, Section 5.2
 *
 *  0                   1                   2                   3
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 * +-+-+-+-+-+-+-+-+
 * |  Protocol-ID  |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                           Identifier                          |
 * |                            (64 bits)                          |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * //               Local Node Descriptors (variable)             //
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * //                Prefix Descriptors (variable)                //
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 * Note: Same structure used for both IPv4 (Type 3) and IPv6 (Type 4)
 *       The prefix_desc.prefix.family field distinguishes between them
 */
struct bgp_ls_prefix_nlri {
	enum bgp_ls_protocol_id protocol_id;	     /* IGP protocol */
	uint64_t identifier;			     /* Instance identifier */
	struct bgp_ls_node_descriptor local_node;    /* Advertising node */
	struct bgp_ls_prefix_descriptor prefix_desc; /* Prefix identity */
};

/*
 * SRv6 SID NLRI (Type 6) - RFC 9514, Section 6
 *
 *  0                   1                   2                   3
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 * +-+-+-+-+-+-+-+-+
 * |  Protocol-ID  |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                         Identifier                            |
 * |                          (8 octets)                           |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * //              Local Node Descriptors (variable)              //
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * //              SRv6 SID Descriptors (variable)                //
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */
struct bgp_ls_srv6_sid_nlri {
	enum bgp_ls_protocol_id protocol_id;	    /* IGP/BGP protocol */
	uint64_t identifier;					    /* Instance identifier */
	struct bgp_ls_node_descriptor local_node;   /* Local node descriptors */
	struct bgp_ls_srv6_sid_descriptor sid_desc; /* SRv6 SID descriptors */
};

/* Forward declare the hash table */
PREDECL_HASH(bgp_ls_nlri_hash);

/*
 * Top-level BGP-LS NLRI structure (RFC 9552 Section 5.2)
 *
 * BGP-LS NLRI encoding in UPDATE message:
 *
 *  0                   1                   2                   3
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |              Type             |            Length             |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                                                               |
 * //                   NLRI Value (variable)                     //
 * |                                                               |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 * Where:
 *   Type   = NLRI Type (1=Node, 2=Link, 3=IPv4 Prefix, 4=IPv6 Prefix)
 *   Length = Length of NLRI Value in octets
 *   Value  = Type-specific NLRI data (see struct bgp_ls_*_nlri)
 *
 * This structure represents the decoded NLRI after parsing the wire format.
 */
struct bgp_ls_nlri {
	enum bgp_ls_nlri_type nlri_type; /* Discriminator */
	union {
		struct bgp_ls_node_nlri node;	  /* Node NLRI (Type 1) */
		struct bgp_ls_link_nlri link;	  /* Link NLRI (Type 2) */
		struct bgp_ls_prefix_nlri prefix; /* Prefix NLRI (Type 3/4) */
		struct bgp_ls_srv6_sid_nlri srv6_sid; /* SRv6 SID NLRI (Type 6, RFC 9514) */
	} nlri_data;

	unsigned long refcnt; /* Reference count */
	uint32_t id;

	/* Hash table linkage */
	struct bgp_ls_nlri_hash_item hash_item;
};

/* Forward declare the hash table */
PREDECL_HASH(bgp_ls_attr_hash);

/* BGP-LS Attribute (Type 29) */
struct bgp_ls_attr {
	uint64_t present_tlvs; /* Bitmask of present TLVs */

	/* Node Flag Bits (TLV 1024) */
	uint8_t node_flags;

	/* Node Name (TLV 1026) */
	char *node_name;

	/* IS-IS Area Identifier (TLV 1027) */
	uint8_t isis_area_id_len;
	uint8_t *isis_area_id;

	/* SR Capabilities (TLV 1034), only one range supported */
	struct bgp_ls_srgb {
		uint32_t lower_bound; /* MPLS label lower bound */
		uint32_t range_size;  /* MPLS label range size */
		uint8_t flag;	      /* IS-IS SRGB flags */
	} srgb;

	/* Node MSD (TLV 266) */
	uint8_t msd;

	/* Multi-Topology IDs (multiple TLVs, same as descriptor) */
	uint8_t mt_id_count;
	uint16_t *mt_id;

	/* IPv4/IPv6 Router-IDs (TLVs 1028-1031) */
	struct in_addr ipv4_router_id_local;
	struct in6_addr ipv6_router_id_local;
	struct in_addr ipv4_router_id_remote;
	struct in6_addr ipv6_router_id_remote;

	/* Administrative Group (TLV 1088) */
	uint32_t admin_group;

	/* Maximum Link Bandwidth (TLV 1089) - IEEE floating point */
	float max_link_bw;

	/* Maximum Reservable Bandwidth (TLV 1090) */
	float max_resv_bw;

	/* Unreserved Bandwidth (TLV 1091) - 8 priority levels */
	float unreserved_bw[BGP_LS_MAX_UNRESV_BW];

	/* TE Default Metric (TLV 1092) */
	uint32_t te_metric;

	/* Link Protection Type (TLV 1093) */
	uint16_t link_protection;

	/* MPLS Protocol Mask (TLV 1094) */
	uint8_t mpls_protocol_mask;

	/* IGP Metric (TLV 1095) - Variable length 1-3 bytes */
	uint8_t igp_metric_len;
	uint32_t igp_metric;

	/* Shared Risk Link Group (TLV 1096) */
	uint16_t srlg_count;
	uint32_t *srlg_values;

	/* Link Name (TLV 1098) */
	char *link_name;

	/* Extended Administrative Group (TLV 1173) */
	struct admin_group ext_admin_group;

	/* Performance Metrics - Unidirectional Link Delay (TLV 1114) */
	uint32_t delay;

	/* Min/Max Unidirectional Link Delay (TLV 1115) */
	uint32_t min_delay;
	uint32_t max_delay;

	/* Unidirectional Delay Variation (TLV 1116) */
	uint32_t jitter;

	/* Unidirectional Packet Loss (TLV 1117) */
	uint32_t pkt_loss;

	/* Unidirectional Residual Bandwidth (TLV 1118) */
	float residual_bw;

	/* Unidirectional Available Bandwidth (TLV 1119) */
	float available_bw;

	/* Unidirectional Utilized Bandwidth (TLV 1120) */
	float utilized_bw;

	/* IGP Flags (TLV 1152) */
	uint8_t igp_flags;

	/* Route Tags (TLV 1153) */
	uint16_t route_tag_count;
	uint32_t *route_tags;

	/* Extended Tags (TLV 1154) */
	uint8_t extended_tag_count;
	uint64_t *extended_tags;

	/* Prefix Metric (TLV 1155) */
	uint32_t prefix_metric;

	/* OSPF Forwarding Address (TLV 1156) */
	struct in_addr ospf_fwd_addr;	/* IPv4 */
	struct in6_addr ospf_fwd_addr6; /* IPv6 */

	/* Prefix-SID (TLV 1158) */
	struct prefix_sid {
		uint8_t sid_flag; /* Segment Routing Flags */
		uint8_t algo;	  /* Algorithm for Segment Routing */
		uint32_t sid;	  /* Segment Routing ID */
	} prefix_sid;

	/* Opaque Node Attribute (TLV 1025/1097/1157) */
	uint16_t opaque_len;
	uint8_t *opaque_data;

	/* SRv6 Capabilities (TLV 1038, RFC 9514 Section 3.1) */
	uint16_t srv6_cap_flags; /* SRv6 capability flags */

	/* SRv6 SID Structure (TLV 1252, RFC 9514 Section 8) */
	struct bgp_ls_srv6_sid_structure srv6_sid_structure;

	/* SRv6 End.X SID (TLV 1106, RFC 9514 Section 4.1) */
	uint16_t srv6_endx_sid_count;
	struct bgp_ls_srv6_endx_sid *srv6_endx_sid;

	/* SRv6 LAN End.X SID (TLV 1107/1108, RFC 9514 Section 4.2) */
	uint16_t srv6_lan_endx_sid_count;
	struct bgp_ls_srv6_lan_endx_sid *srv6_lan_endx_sid;

	/* SRv6 Locator attributes (TLV 1162, RFC 9514 Section 5.1) */
	uint8_t srv6_locator_flags;
	uint8_t srv6_locator_algo;
	uint32_t srv6_locator_metric;

	/* SRv6 Endpoint Behavior (TLV 1250, RFC 9514 Section 7.1) */
	uint16_t srv6_endpoint_behavior;
	uint8_t srv6_endpoint_flags;
	uint8_t srv6_endpoint_algo;

	unsigned long refcnt; /* Reference count */

	/* Hash table linkage */
	struct bgp_ls_attr_hash_item hash_item;
};

/* Function prototypes */

/* Descriptor comparison functions */
extern int bgp_ls_node_descriptor_cmp(const struct bgp_ls_node_descriptor *d1,
				      const struct bgp_ls_node_descriptor *d2);
extern int bgp_ls_link_descriptor_cmp(const struct bgp_ls_link_descriptor *d1,
				      const struct bgp_ls_link_descriptor *d2);
extern int bgp_ls_prefix_descriptor_cmp(const struct bgp_ls_prefix_descriptor *d1,
					const struct bgp_ls_prefix_descriptor *d2);

/* NLRI comparison functions */
extern int bgp_ls_nlri_cmp(const struct bgp_ls_nlri *nlri1, const struct bgp_ls_nlri *nlri2);
extern int bgp_ls_attr_cmp(const struct bgp_ls_attr *attr1, const struct bgp_ls_attr *attr2);
extern bool bgp_ls_attr_same(const struct bgp_ls_attr *attr1, const struct bgp_ls_attr *attr2);

/* NLRI memory management functions */
extern struct bgp_ls_nlri *bgp_ls_nlri_alloc(void);
extern void bgp_ls_nlri_free(struct bgp_ls_nlri *nlri);
extern struct bgp_ls_attr *bgp_ls_attr_alloc(void);
extern void bgp_ls_attr_free(struct bgp_ls_attr *attr);
extern struct bgp_ls_nlri *bgp_ls_nlri_copy(const struct bgp_ls_nlri *nlri);
struct bgp_ls_attr *bgp_ls_attr_copy(const struct bgp_ls_attr *src);

/* NLRI validation functions */
extern bool bgp_ls_nlri_validate(const struct bgp_ls_nlri *nlri);

/* NLRI size calculation helpers */
extern size_t bgp_ls_nlri_size(const struct bgp_ls_nlri *nlri);

/* String conversion helpers */
extern const char *bgp_ls_protocol_id_str(enum bgp_ls_protocol_id proto_id);
extern const char *bgp_ls_nlri_type_str(enum bgp_ls_nlri_type nlri_type);
extern const char *bgp_ls_node_descriptor_tlv_str(enum bgp_ls_node_descriptor_tlv tlv_type);
extern const char *bgp_ls_link_descriptor_tlv_str(enum bgp_ls_link_descriptor_tlv tlv_type);
extern const char *bgp_ls_prefix_descriptor_tlv_str(enum bgp_ls_prefix_descriptor_tlv tlv_type);
extern const char *bgp_ls_ospf_route_type_str(enum bgp_ls_ospf_route_type route_type);
extern const char *bgp_ls_bgp_route_type_str(enum bgp_ls_bgp_route_type route_type);

/* Json conversion helpers */
extern const char *bgp_ls_ospf_route_type_str_json(enum bgp_ls_ospf_route_type route_type);
extern const char *bgp_ls_bgp_route_type_str_json(enum bgp_ls_bgp_route_type route_type);

/*
 * ===========================================================================
 * Hash Table Management
 * ===========================================================================
 */

/* Unified hash functions - dispatch internally based on nlri_type */
extern unsigned int bgp_ls_nlri_hash_key(const struct bgp_ls_nlri *nlri);
extern int bgp_ls_nlri_hash_cmp(const struct bgp_ls_nlri *n1, const struct bgp_ls_nlri *n2);

extern unsigned int bgp_ls_attr_hash_key(const struct bgp_ls_attr *ls_attr);
extern int bgp_ls_attr_hash_cmp(const struct bgp_ls_attr *a1, const struct bgp_ls_attr *a2);

/* Declare the typesafe hash table */
DECLARE_HASH(bgp_ls_nlri_hash, struct bgp_ls_nlri, hash_item, bgp_ls_nlri_hash_cmp,
	     bgp_ls_nlri_hash_key);

/* Declare the typesafe hash table */
DECLARE_HASH(bgp_ls_attr_hash, struct bgp_ls_attr, hash_item, bgp_ls_attr_hash_cmp,
	     bgp_ls_attr_hash_key);

/*
 * ===========================================================================
 * BGP-LS NLRI Hash Table Management Functions
 * ===========================================================================
 */

/* Insert NLRI into unified hash table */
extern struct bgp_ls_nlri *bgp_ls_nlri_get(struct bgp_ls_nlri_hash_head *hash, struct bgp *bgp,
					   struct bgp_ls_nlri *nlri);

/* Lookup NLRI in unified hash table */
extern struct bgp_ls_nlri *bgp_ls_nlri_lookup(struct bgp_ls_nlri_hash_head *hash,
					      struct bgp_ls_nlri *nlri);

/* NLRI interning (lookup + lock/unlock) */
extern struct bgp_ls_nlri *bgp_ls_nlri_intern(struct bgp_ls_nlri *ls_nlri);
extern void bgp_ls_nlri_unintern(struct bgp_ls_nlri **pls_nlri);

/* Insert BGP-LS attribute into unified hash table */
extern struct bgp_ls_attr *bgp_ls_attr_get(struct bgp_ls_attr_hash_head *hash, struct bgp *bgp,
					   struct bgp_ls_attr *ls_attr);

/* Lookup BGP-LS attribute in unified hash table */
extern struct bgp_ls_attr *bgp_ls_attr_lookup(struct bgp_ls_attr_hash_head *hash,
					      const struct bgp_ls_attr *ls_attr);

/* BGP-LS attribute interning (lookup + lock/unlock) */
extern struct bgp_ls_attr *bgp_ls_attr_intern(struct bgp_ls_attr *ls_attr);
extern void bgp_ls_attr_unintern(struct bgp_ls_attr **pls_attr);

/*
 * ===========================================================================
 * NLRI Encoding Functions
 * ===========================================================================
 */

/* Encode Node Descriptor TLVs into stream */
extern int bgp_ls_encode_node_descriptor(struct stream *s,
					 const struct bgp_ls_node_descriptor *desc,
					 uint16_t tlv_type);

/* Encode Link Descriptor TLVs into stream */
extern int bgp_ls_encode_link_descriptor(struct stream *s,
					 const struct bgp_ls_link_descriptor *desc);

/* Encode Prefix Descriptor TLVs into stream */
extern int bgp_ls_encode_prefix_descriptor(struct stream *s,
					   const struct bgp_ls_prefix_descriptor *desc);

/* Encode Node NLRI to wire format */
extern int bgp_ls_encode_node_nlri(struct stream *s, const struct bgp_ls_node_nlri *nlri);

/* Encode Link NLRI to wire format */
extern int bgp_ls_encode_link_nlri(struct stream *s, const struct bgp_ls_link_nlri *nlri);

/* Encode Prefix NLRI to wire format */
extern int bgp_ls_encode_prefix_nlri(struct stream *s, const struct bgp_ls_prefix_nlri *nlri,
				     enum bgp_ls_nlri_type nlri_type);

/* Encode complete NLRI */
extern int bgp_ls_encode_nlri(struct stream *s, const struct bgp_ls_nlri *nlri);

/* Encode BGP-LS Attributes (Type 29 TLVs) */
extern int bgp_ls_encode_attr(struct stream *s, const struct bgp_ls_attr *attr);

/*
 * Get Prefix-SID attribute SID length by flags
 *
 * @return 3 or 4 in normal case, -1 in error case
 */
extern int bgp_ls_attr_prefix_sid_len(uint8_t flags);

/*
 * ===========================================================================
 * NLRI Decoding Functions
 * ===========================================================================
 */

/* Decode Node Descriptor TLVs from stream */
extern int bgp_ls_decode_node_descriptor(struct stream *s, struct bgp_ls_node_descriptor *desc,
					 uint16_t desc_length);

/* Decode Link Descriptor TLVs from stream */
extern int bgp_ls_decode_link_descriptor(struct stream *s, struct bgp_ls_link_descriptor *desc,
					 size_t total_length);

/* Decode Prefix Descriptor TLVs from stream */
extern int bgp_ls_decode_prefix_descriptor(struct stream *s, struct bgp_ls_prefix_descriptor *desc,
					   size_t total_length, bool is_ipv6);

/* Decode Node NLRI from wire format */
extern int bgp_ls_decode_node_nlri(struct stream *s, struct bgp_ls_nlri *nlri,
				   uint16_t nlri_length);

/* Decode Link NLRI from wire format */
extern int bgp_ls_decode_link_nlri(struct stream *s, struct bgp_ls_nlri *nlri,
				   uint16_t nlri_length);

/* Decode Prefix NLRI from wire format */
extern int bgp_ls_decode_prefix_nlri(struct stream *s, struct bgp_ls_nlri *nlri,
				     uint16_t nlri_type, uint16_t nlri_length);

/* Encode SRv6 SID NLRI to wire format (RFC 9514) */
extern int bgp_ls_encode_srv6_sid_nlri(struct stream *s, const struct bgp_ls_srv6_sid_nlri *nlri);

/* Decode SRv6 SID NLRI from wire format (RFC 9514) */
extern int bgp_ls_decode_srv6_sid_nlri(struct stream *s, struct bgp_ls_nlri *nlri,
				       uint16_t nlri_length);

/* Decode complete NLRI */
extern int bgp_ls_decode_nlri(struct stream *s, struct bgp_ls_nlri *nlri);

/*
 * Parse BGP-LS Attributes (Type 29 TLVs)
 *
 * @param s Stream containing the attribute TLVs
 * @param total_length Total length of all TLVs in bytes
 * @param attr Pointer to node attribute structure to populate
 * @return 0 on success, -1 on error
 */
extern int bgp_ls_parse_attr(struct stream *s, uint16_t total_length, struct bgp_ls_attr *attr);

/*
 * Convert BGP-LS Attributes to JSON object
 *
 * @param ls_attr Pointer to BGP-LS attribute structure to convert
 *
 * Used for "show bgp" commands to display link-state topology information in json
 *
 * @return json object
 */
extern struct json_object *bgp_ls_attr_to_json(struct bgp_ls_attr *ls_attr);

/*
 * Display BGP-LS Attributes to VTY output
 *
 * @param vty VTY output context
 * @param ls_attr Pointer to BGP-LS attribute structure to display
 *
 * Used for "show bgp" commands to display link-state topology information
 */
extern void bgp_ls_attr_display(struct vty *vty, struct bgp_ls_attr *ls_attr);

/*
 * Display BGP-LS NLRI details to VTY output
 *
 * @param vty VTY output context
 * @param nlri Pointer to BGP-LS NLRI structure to display
 *
 * Displays Node/Link/Prefix NLRI information including descriptors,
 * protocol information, and multi-topology details
 */
extern void bgp_ls_nlri_display(struct vty *vty, struct bgp_ls_nlri *nlri);

#endif /* _FRR_BGP_LS_NLRI_H */
