From 2c7cac91ed6e7db0f6937923d2b57f97dbdbc337 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 11:53:30 +0200 Subject: Adding upstream version 8.4.4. Signed-off-by: Daniel Baumann --- pceplib/pcep_msg_tlvs.c | 468 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 468 insertions(+) create mode 100644 pceplib/pcep_msg_tlvs.c (limited to 'pceplib/pcep_msg_tlvs.c') diff --git a/pceplib/pcep_msg_tlvs.c b/pceplib/pcep_msg_tlvs.c new file mode 100644 index 0000000..6298ed4 --- /dev/null +++ b/pceplib/pcep_msg_tlvs.c @@ -0,0 +1,468 @@ +/* + * This file is part of the PCEPlib, a PCEP protocol library. + * + * Copyright (C) 2020 Volta Networks https://voltanet.io/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Author : Brady Johnson + * + */ + + +/* + * This is the implementation of a High Level PCEP message object TLV API. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "pcep_msg_tlvs.h" +#include "pcep_msg_encoding.h" +#include "pcep_utils_memory.h" + +static struct pcep_object_tlv_header * +pcep_tlv_common_create(enum pcep_object_tlv_types type, uint16_t size) +{ + struct pcep_object_tlv_header *tlv = + pceplib_malloc(PCEPLIB_MESSAGES, size); + memset(tlv, 0, size); + tlv->type = type; + + return tlv; +} + +/* + * Open Object TLVs + */ + +struct pcep_object_tlv_stateful_pce_capability * +pcep_tlv_create_stateful_pce_capability( + bool flag_u_lsp_update_capability, bool flag_s_include_db_version, + bool flag_i_lsp_instantiation_capability, bool flag_t_triggered_resync, + bool flag_d_delta_lsp_sync, bool flag_f_triggered_initial_sync) +{ + struct pcep_object_tlv_stateful_pce_capability *tlv = + (struct pcep_object_tlv_stateful_pce_capability *) + pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY, + sizeof(struct + pcep_object_tlv_stateful_pce_capability)); + tlv->flag_u_lsp_update_capability = flag_u_lsp_update_capability; + tlv->flag_s_include_db_version = flag_s_include_db_version; + tlv->flag_i_lsp_instantiation_capability = + flag_i_lsp_instantiation_capability; + tlv->flag_t_triggered_resync = flag_t_triggered_resync; + tlv->flag_d_delta_lsp_sync = flag_d_delta_lsp_sync; + tlv->flag_f_triggered_initial_sync = flag_f_triggered_initial_sync; + + return tlv; +} + +struct pcep_object_tlv_lsp_db_version * +pcep_tlv_create_lsp_db_version(uint64_t lsp_db_version) +{ + struct pcep_object_tlv_lsp_db_version *tlv = + (struct pcep_object_tlv_lsp_db_version *)pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION, + sizeof(struct pcep_object_tlv_lsp_db_version)); + tlv->lsp_db_version = lsp_db_version; + + return tlv; +} + +struct pcep_object_tlv_speaker_entity_identifier * +pcep_tlv_create_speaker_entity_id(double_linked_list *speaker_entity_id_list) +{ + if (speaker_entity_id_list == NULL) { + return NULL; + } + + if (speaker_entity_id_list->num_entries == 0) { + return NULL; + } + + struct pcep_object_tlv_speaker_entity_identifier *tlv = + (struct pcep_object_tlv_speaker_entity_identifier *) + pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID, + sizeof(struct + pcep_object_tlv_speaker_entity_identifier)); + tlv->speaker_entity_id_list = speaker_entity_id_list; + + return tlv; +} + +struct pcep_object_tlv_path_setup_type * +pcep_tlv_create_path_setup_type(uint8_t pst) +{ + struct pcep_object_tlv_path_setup_type *tlv = + (struct pcep_object_tlv_path_setup_type *) + pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE, + sizeof(struct pcep_object_tlv_path_setup_type)); + tlv->path_setup_type = pst; + + return tlv; +} + +struct pcep_object_tlv_path_setup_type_capability * +pcep_tlv_create_path_setup_type_capability(double_linked_list *pst_list, + double_linked_list *sub_tlv_list) +{ + if (pst_list == NULL) { + return NULL; + } + + if (pst_list->num_entries == 0) { + return NULL; + } + + struct pcep_object_tlv_path_setup_type_capability *tlv = + (struct pcep_object_tlv_path_setup_type_capability *) + pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY, + sizeof(struct + pcep_object_tlv_path_setup_type_capability)); + + tlv->pst_list = pst_list; + tlv->sub_tlv_list = sub_tlv_list; + + return tlv; +} + +struct pcep_object_tlv_sr_pce_capability * +pcep_tlv_create_sr_pce_capability(bool flag_n, bool flag_x, + uint8_t max_sid_depth) +{ + struct pcep_object_tlv_sr_pce_capability *tlv = + (struct pcep_object_tlv_sr_pce_capability *) + pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY, + sizeof(struct + pcep_object_tlv_sr_pce_capability)); + tlv->flag_n = flag_n; + tlv->flag_x = flag_x; + tlv->max_sid_depth = max_sid_depth; + + return tlv; +} + +struct pcep_object_tlv_of_list * +pcep_tlv_create_of_list(double_linked_list *of_list) +{ + if (of_list == NULL) { + return NULL; + } + + struct pcep_object_tlv_of_list *tlv = + (struct pcep_object_tlv_of_list *)pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_OBJECTIVE_FUNCTION_LIST, + sizeof(struct pcep_object_tlv_of_list)); + + tlv->of_list = of_list; + + return tlv; +} + +/* + * LSP Object TLVs + */ + +struct pcep_object_tlv_ipv4_lsp_identifier * +pcep_tlv_create_ipv4_lsp_identifiers(struct in_addr *ipv4_tunnel_sender, + struct in_addr *ipv4_tunnel_endpoint, + uint16_t lsp_id, uint16_t tunnel_id, + struct in_addr *extended_tunnel_id) +{ + if (ipv4_tunnel_sender == NULL || ipv4_tunnel_endpoint == NULL) { + return NULL; + } + + struct pcep_object_tlv_ipv4_lsp_identifier *tlv = + (struct pcep_object_tlv_ipv4_lsp_identifier *) + pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS, + sizeof(struct + pcep_object_tlv_ipv4_lsp_identifier)); + tlv->ipv4_tunnel_sender.s_addr = ipv4_tunnel_sender->s_addr; + tlv->ipv4_tunnel_endpoint.s_addr = ipv4_tunnel_endpoint->s_addr; + tlv->lsp_id = lsp_id; + tlv->tunnel_id = tunnel_id; + tlv->extended_tunnel_id.s_addr = + (extended_tunnel_id == NULL ? INADDR_ANY + : extended_tunnel_id->s_addr); + + return tlv; +} + +struct pcep_object_tlv_ipv6_lsp_identifier * +pcep_tlv_create_ipv6_lsp_identifiers(struct in6_addr *ipv6_tunnel_sender, + struct in6_addr *ipv6_tunnel_endpoint, + uint16_t lsp_id, uint16_t tunnel_id, + struct in6_addr *extended_tunnel_id) +{ + if (ipv6_tunnel_sender == NULL || ipv6_tunnel_endpoint == NULL) { + return NULL; + } + + struct pcep_object_tlv_ipv6_lsp_identifier *tlv = + (struct pcep_object_tlv_ipv6_lsp_identifier *) + pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS, + sizeof(struct + pcep_object_tlv_ipv6_lsp_identifier)); + + memcpy(&tlv->ipv6_tunnel_sender, ipv6_tunnel_sender, + sizeof(struct in6_addr)); + + tlv->tunnel_id = tunnel_id; + tlv->lsp_id = lsp_id; + + memcpy(&tlv->extended_tunnel_id, extended_tunnel_id, + sizeof(struct in6_addr)); + + memcpy(&tlv->ipv6_tunnel_endpoint, ipv6_tunnel_endpoint, + sizeof(struct in6_addr)); + + return tlv; +} + +struct pcep_object_tlv_symbolic_path_name * +pcep_tlv_create_symbolic_path_name(const char *symbolic_path_name, + uint16_t symbolic_path_name_length) +{ + /* symbolic_path_name_length should NOT include the null terminator and + * cannot be zero */ + if (symbolic_path_name == NULL || symbolic_path_name_length == 0) { + return NULL; + } + + struct pcep_object_tlv_symbolic_path_name *tlv = + (struct pcep_object_tlv_symbolic_path_name *) + pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME, + sizeof(struct + pcep_object_tlv_symbolic_path_name)); + + uint16_t length = (symbolic_path_name_length > MAX_SYMBOLIC_PATH_NAME) + ? MAX_SYMBOLIC_PATH_NAME + : symbolic_path_name_length; + memcpy(tlv->symbolic_path_name, symbolic_path_name, length); + tlv->symbolic_path_name_length = length; + + return tlv; +} + +struct pcep_object_tlv_lsp_error_code * +pcep_tlv_create_lsp_error_code(enum pcep_tlv_lsp_error_codes lsp_error_code) +{ + struct pcep_object_tlv_lsp_error_code *tlv = + (struct pcep_object_tlv_lsp_error_code *)pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE, + sizeof(struct pcep_object_tlv_lsp_error_code)); + tlv->lsp_error_code = lsp_error_code; + + return tlv; +} + +struct pcep_object_tlv_rsvp_error_spec * +pcep_tlv_create_rsvp_ipv4_error_spec(struct in_addr *error_node_ip, + uint8_t error_code, uint16_t error_value) +{ + if (error_node_ip == NULL) { + return NULL; + } + + struct pcep_object_tlv_rsvp_error_spec *tlv = + (struct pcep_object_tlv_rsvp_error_spec *) + pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC, + sizeof(struct pcep_object_tlv_rsvp_error_spec)); + + tlv->c_type = RSVP_ERROR_SPEC_IPV4_CTYPE; + tlv->class_num = RSVP_ERROR_SPEC_CLASS_NUM; + tlv->error_code = error_code; + tlv->error_value = error_value; + tlv->error_spec_ip.ipv4_error_node_address.s_addr = + error_node_ip->s_addr; + + return tlv; +} + +struct pcep_object_tlv_rsvp_error_spec * +pcep_tlv_create_rsvp_ipv6_error_spec(struct in6_addr *error_node_ip, + uint8_t error_code, uint16_t error_value) +{ + if (error_node_ip == NULL) { + return NULL; + } + + struct pcep_object_tlv_rsvp_error_spec *tlv = + (struct pcep_object_tlv_rsvp_error_spec *) + pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC, + sizeof(struct pcep_object_tlv_rsvp_error_spec)); + + tlv->c_type = RSVP_ERROR_SPEC_IPV6_CTYPE; + tlv->class_num = RSVP_ERROR_SPEC_CLASS_NUM; + tlv->error_code = error_code; + tlv->error_value = error_value; + memcpy(&tlv->error_spec_ip, error_node_ip, sizeof(struct in6_addr)); + + return tlv; +} + +struct pcep_object_tlv_nopath_vector * +pcep_tlv_create_nopath_vector(uint32_t error_code) +{ + struct pcep_object_tlv_nopath_vector *tlv = + (struct pcep_object_tlv_nopath_vector *)pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR, + sizeof(struct pcep_object_tlv_nopath_vector)); + + tlv->error_code = error_code; + + return tlv; +} + +struct pcep_object_tlv_vendor_info * +pcep_tlv_create_vendor_info(uint32_t enterprise_number, + uint32_t enterprise_specific_info) +{ + struct pcep_object_tlv_vendor_info *tlv = + (struct pcep_object_tlv_vendor_info *)pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_VENDOR_INFO, + sizeof(struct pcep_object_tlv_vendor_info)); + + tlv->enterprise_number = enterprise_number; + tlv->enterprise_specific_info = enterprise_specific_info; + + return tlv; +} + +/* + * SRPAG (SR Association Group) TLVs + */ + +struct pcep_object_tlv_srpag_pol_id * +pcep_tlv_create_srpag_pol_id_ipv4(uint32_t color, struct in_addr *ipv4) +{ + struct pcep_object_tlv_srpag_pol_id *tlv = + (struct pcep_object_tlv_srpag_pol_id *)pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID, + sizeof(struct pcep_object_tlv_srpag_pol_id)); + tlv->color = color; + tlv->is_ipv4 = true; + memcpy(&tlv->end_point.ipv4.s_addr, ipv4, sizeof(struct in_addr)); + + return tlv; +} + +struct pcep_object_tlv_srpag_pol_id * +pcep_tlv_create_srpag_pol_id_ipv6(uint32_t color, struct in6_addr *ipv6) +{ + struct pcep_object_tlv_srpag_pol_id *tlv = + (struct pcep_object_tlv_srpag_pol_id *)pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID, + sizeof(struct pcep_object_tlv_srpag_pol_id)); + tlv->color = color; + tlv->is_ipv4 = false; + memcpy(&tlv->end_point.ipv6, ipv6, sizeof(struct in6_addr)); + + return tlv; +} + + +struct pcep_object_tlv_srpag_pol_name * +pcep_tlv_create_srpag_pol_name(const char *pol_name, uint16_t pol_name_length) +{ + if (pol_name == NULL) { + return NULL; + } + struct pcep_object_tlv_srpag_pol_name *tlv = + (struct pcep_object_tlv_srpag_pol_name *)pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME, + sizeof(struct pcep_object_tlv_srpag_pol_name)); + uint16_t length = + (normalize_pcep_tlv_length(pol_name_length) > MAX_POLICY_NAME) + ? MAX_POLICY_NAME + : pol_name_length; + memcpy(tlv->name, pol_name, length); + tlv->name_length = length; + + return tlv; +} +struct pcep_object_tlv_srpag_cp_id * +pcep_tlv_create_srpag_cp_id(uint8_t proto_origin, uint32_t asn, + struct in6_addr *in6_addr_with_mapped_ipv4, + uint32_t discriminator) +{ + if (!in6_addr_with_mapped_ipv4) { + return NULL; + } + + struct pcep_object_tlv_srpag_cp_id *tlv = + (struct pcep_object_tlv_srpag_cp_id *)pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID, + sizeof(struct pcep_object_tlv_srpag_cp_id)); + tlv->proto = proto_origin; + tlv->orig_asn = asn; + memcpy(&(tlv->orig_addres), in6_addr_with_mapped_ipv4, + sizeof(*in6_addr_with_mapped_ipv4)); + tlv->discriminator = discriminator; + + return tlv; +} +struct pcep_object_tlv_srpag_cp_pref * +pcep_tlv_create_srpag_cp_pref(uint32_t pref) +{ + + struct pcep_object_tlv_srpag_cp_pref *tlv = + (struct pcep_object_tlv_srpag_cp_pref *)pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE, + sizeof(struct pcep_object_tlv_srpag_cp_pref)); + tlv->preference = pref; + + return tlv; +} + +struct pcep_object_tlv_arbitrary * +pcep_tlv_create_tlv_arbitrary(const char *data, uint16_t data_length, + int tlv_id) +{ + if (data == NULL || data_length == 0) { + return NULL; + } + + struct pcep_object_tlv_arbitrary *tlv = + (struct pcep_object_tlv_arbitrary *)pcep_tlv_common_create( + PCEP_OBJ_TLV_TYPE_ARBITRARY, + sizeof(struct pcep_object_tlv_arbitrary)); + + uint16_t length = (data_length > MAX_ARBITRARY_SIZE) + ? MAX_ARBITRARY_SIZE + : data_length; + memcpy(tlv->data, data, length); + tlv->data_length = length; + tlv->arbitraty_type = tlv_id; + + return tlv; +} -- cgit v1.2.3