mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-10-31 21:46:33 +00:00 
			
		
		
		
	 2a034138d4
			
		
	
	
		2a034138d4
		
	
	
	
	
		
			
			Use a pcep-specific value for MD5SIG_MAXLEN, use the OS value if present. Signed-off-by: Mark Stapp <mjs@voltanet.io>
		
			
				
	
	
		
			291 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			291 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * 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 General Public License
 | |
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | |
|  *
 | |
|  * Author : Brady Johnson <brady@voltanet.io>
 | |
|  *
 | |
|  */
 | |
| 
 | |
| 
 | |
| #ifndef INCLUDE_PCEPSESSIONLOGIC_H_
 | |
| #define INCLUDE_PCEPSESSIONLOGIC_H_
 | |
| 
 | |
| #include <stdbool.h>
 | |
| #include <netinet/tcp.h>
 | |
| 
 | |
| #include "pcep_msg_encoding.h"
 | |
| #include "pcep_socket_comm.h"
 | |
| #include "pcep_msg_objects.h"
 | |
| #include "pcep_msg_tools.h"
 | |
| #include "pcep_timers.h"
 | |
| #include "pcep_utils_queue.h"
 | |
| #include "pcep_utils_memory.h"
 | |
| 
 | |
| #define PCEP_TCP_PORT 4189
 | |
| 
 | |
| typedef struct pcep_configuration_ {
 | |
| 	/* These are the configuration values that will
 | |
| 	 * be sent to the PCE in the PCEP Open message */
 | |
| 	int keep_alive_seconds;
 | |
| 	int dead_timer_seconds;
 | |
| 	int dead_timer_pce_negotiated_seconds; /* Config data negotiated with
 | |
| 						  PCE */
 | |
| 	int keep_alive_pce_negotiated_timer_seconds; /* Config data negotiated
 | |
| 							with PCE */
 | |
| 	int request_time_seconds;
 | |
| 
 | |
| 	/* These are the acceptable ranges of values received by
 | |
| 	 * the PCE in the initial PCEP Open Message. If a value is
 | |
| 	 * received outside of these ranges, then the Open message
 | |
| 	 * will be rejected. */
 | |
| 	int min_keep_alive_seconds;
 | |
| 	int max_keep_alive_seconds;
 | |
| 	int min_dead_timer_seconds;
 | |
| 	int max_dead_timer_seconds;
 | |
| 
 | |
| 	/* If more than this many unknown messages/requests are received
 | |
| 	 * per minute, then the session will be closed. */
 | |
| 	int max_unknown_messages;
 | |
| 	int max_unknown_requests;
 | |
| 
 | |
| 	/* Maximum amount of time to wait to connect to the
 | |
| 	 * PCE TCP socket before failing, in milliseconds. */
 | |
| 	uint32_t socket_connect_timeout_millis;
 | |
| 
 | |
| 	/* Set if the PCE/PCC will support stateful PCE LSP Updates
 | |
| 	 * according to RCF8231, section 7.1.1, defaults to true.
 | |
| 	 * Will cause an additional TLV to be sent from the PCC in
 | |
| 	 * the PCEP Open */
 | |
| 	bool support_stateful_pce_lsp_update;
 | |
| 
 | |
| 	/* RFC 8281: I-bit, the PCC allows instantiation of an LSP by a PCE */
 | |
| 	bool support_pce_lsp_instantiation;
 | |
| 
 | |
| 	/* RFC 8232: S-bit, the PCC will include the LSP-DB-VERSION
 | |
| 	 * TLV in each LSP object */
 | |
| 	bool support_include_db_version;
 | |
| 
 | |
| 	/* Only set if support_include_db_version is true and if the LSP-DB
 | |
| 	 * survived a restart and is available. If this has a value other than
 | |
| 	 * 0, then a LSP-DB-VERSION TLV will be sent in the OPEN object. This
 | |
| 	 * value will be copied over to the pcep_session upon init. */
 | |
| 	uint64_t lsp_db_version;
 | |
| 
 | |
| 	/* RFC 8232: T-bit, the PCE can trigger resynchronization of
 | |
| 	 * LSPs at any point in the life of the session */
 | |
| 	bool support_lsp_triggered_resync;
 | |
| 
 | |
| 	/* RFC 8232: D-bit, the PCEP speaker allows incremental (delta)
 | |
| 	 * State Synchronization */
 | |
| 	bool support_lsp_delta_sync;
 | |
| 
 | |
| 	/* RFC 8232: F-bit, the PCE SHOULD trigger initial (first)
 | |
| 	 * State Synchronization */
 | |
| 	bool support_pce_triggered_initial_sync;
 | |
| 
 | |
| 	/* draft-ietf-pce-segment-routing-16: Send a SR PCE Capability
 | |
| 	 * sub-TLV in a Path Setup Type Capability TLV with a PST = 1,
 | |
| 	 * Path is setup using SR TE. */
 | |
| 	bool support_sr_te_pst;
 | |
| 	/* Used in the SR PCE Capability sub-TLV */
 | |
| 	bool pcc_can_resolve_nai_to_sid;
 | |
| 	/* Used in the SR TE Capability sub-TLV, 0 means there are no max sid
 | |
| 	 * limits */
 | |
| 	uint8_t max_sid_depth;
 | |
| 
 | |
| 	/* If set to 0, then the default 4189 PCEP port will be used */
 | |
| 	uint16_t dst_pcep_port;
 | |
| 
 | |
| 	/* If set to 0, then the default 4189 PCEP port will be used.
 | |
| 	 * This is according to the RFC5440, Section 5 */
 | |
| 	uint16_t src_pcep_port;
 | |
| 
 | |
| 	union src_ip {
 | |
| 		struct in_addr src_ipv4;
 | |
| 		struct in6_addr src_ipv6;
 | |
| 	} src_ip;
 | |
| 	bool is_src_ipv6;
 | |
| 
 | |
| 	struct pcep_versioning *pcep_msg_versioning;
 | |
| 
 | |
| 	char tcp_authentication_str[PCEP_MD5SIG_MAXKEYLEN];
 | |
| 	bool is_tcp_auth_md5; /* true: RFC 2385, false: RFC 5925 */
 | |
| 
 | |
| } pcep_configuration;
 | |
| 
 | |
| 
 | |
| typedef enum pcep_session_state_ {
 | |
| 	SESSION_STATE_UNKNOWN = 0,
 | |
| 	SESSION_STATE_INITIALIZED = 1,
 | |
| 	SESSION_STATE_PCEP_CONNECTING = 2,
 | |
| 	SESSION_STATE_PCEP_CONNECTED = 3
 | |
| 
 | |
| } pcep_session_state;
 | |
| 
 | |
| 
 | |
| typedef struct pcep_session_ {
 | |
| 	int session_id;
 | |
| 	pcep_session_state session_state;
 | |
| 	int timer_id_open_keep_wait;
 | |
| 	int timer_id_open_keep_alive;
 | |
| 	int timer_id_dead_timer;
 | |
| 	int timer_id_keep_alive;
 | |
| 	bool pce_open_received;
 | |
| 	bool pce_open_rejected;
 | |
| 	bool pce_open_accepted;
 | |
| 	bool pce_open_keep_alive_sent;
 | |
| 	bool pcc_open_rejected;
 | |
| 	bool pcc_open_accepted;
 | |
| 	bool stateful_pce;
 | |
| 	time_t time_connected;
 | |
| 	uint64_t lsp_db_version;
 | |
| 	queue_handle *num_unknown_messages_time_queue;
 | |
| 	/* set this flag when finalizing the session */
 | |
| 	bool destroy_session_after_write;
 | |
| 	pcep_socket_comm_session *socket_comm_session;
 | |
| 	/* Configuration sent from the PCC to the PCE */
 | |
| 	pcep_configuration pcc_config;
 | |
| 	/* Configuration received from the PCE, to be used in the PCC */
 | |
| 	pcep_configuration pce_config;
 | |
| 	struct counters_group *pcep_session_counters;
 | |
| 
 | |
| } pcep_session;
 | |
| 
 | |
| 
 | |
| typedef enum pcep_event_type {
 | |
| 	MESSAGE_RECEIVED = 0,
 | |
| 	PCE_CLOSED_SOCKET = 1,
 | |
| 	PCE_SENT_PCEP_CLOSE = 2,
 | |
| 	PCE_DEAD_TIMER_EXPIRED = 3,
 | |
| 	PCE_OPEN_KEEP_WAIT_TIMER_EXPIRED = 4,
 | |
| 	PCC_CONNECTED_TO_PCE = 100,
 | |
| 	PCC_CONNECTION_FAILURE = 101,
 | |
| 	PCC_PCEP_SESSION_CLOSED = 102,
 | |
| 	PCC_RCVD_INVALID_OPEN = 103,
 | |
| 	PCC_SENT_INVALID_OPEN = 104,
 | |
| 	PCC_RCVD_MAX_INVALID_MSGS = 105,
 | |
| 	PCC_RCVD_MAX_UNKOWN_MSGS = 106
 | |
| 
 | |
| } pcep_event_type;
 | |
| 
 | |
| 
 | |
| typedef struct pcep_event {
 | |
| 	enum pcep_event_type event_type;
 | |
| 	time_t event_time;
 | |
| 	struct pcep_message *message;
 | |
| 	pcep_session *session;
 | |
| 
 | |
| } pcep_event;
 | |
| 
 | |
| typedef void (*pceplib_pcep_event_callback)(void *cb_data, pcep_event *);
 | |
| typedef int (*pthread_create_callback)(pthread_t *pthread_id,
 | |
| 				       const pthread_attr_t *attr,
 | |
| 				       void *(*start_routine)(void *),
 | |
| 				       void *data, const char *thread_name);
 | |
| 
 | |
| 
 | |
| typedef struct pcep_event_queue {
 | |
| 	/* The event_queue and event_callback are mutually exclusive.
 | |
| 	 * If the event_callback is configured, then the event_queue
 | |
| 	 * will not be used. */
 | |
| 	queue_handle *event_queue;
 | |
| 	pthread_mutex_t event_queue_mutex;
 | |
| 	pceplib_pcep_event_callback event_callback;
 | |
| 	void *event_callback_data;
 | |
| 
 | |
| } pcep_event_queue;
 | |
| 
 | |
| 
 | |
| typedef struct pceplib_infra_config {
 | |
| 	/* Memory infrastructure */
 | |
| 	void *pceplib_infra_mt;
 | |
| 	void *pceplib_messages_mt;
 | |
| 	pceplib_malloc_func malloc_func;
 | |
| 	pceplib_calloc_func calloc_func;
 | |
| 	pceplib_realloc_func realloc_func;
 | |
| 	pceplib_strdup_func strdup_func;
 | |
| 	pceplib_free_func free_func;
 | |
| 
 | |
| 	/* External Timer and Socket infrastructure */
 | |
| 	void *external_infra_data;
 | |
| 	ext_timer_create timer_create_func;
 | |
| 	ext_timer_cancel timer_cancel_func;
 | |
| 	ext_socket_write socket_write_func;
 | |
| 	ext_socket_read socket_read_func;
 | |
| 
 | |
| 	/* External pcep_event infrastructure */
 | |
| 	pceplib_pcep_event_callback pcep_event_func;
 | |
| 
 | |
| 	/* Callback to create pthreads */
 | |
| 	pthread_create_callback pthread_create_func;
 | |
| 
 | |
| } pceplib_infra_config;
 | |
| 
 | |
| /*
 | |
|  * Counters Sub-groups definitions
 | |
|  */
 | |
| typedef enum pcep_session_counters_subgroup_ids {
 | |
| 	COUNTER_SUBGROUP_ID_RX_MSG = 0,
 | |
| 	COUNTER_SUBGROUP_ID_TX_MSG = 1,
 | |
| 	COUNTER_SUBGROUP_ID_RX_OBJ = 2,
 | |
| 	COUNTER_SUBGROUP_ID_TX_OBJ = 3,
 | |
| 	COUNTER_SUBGROUP_ID_RX_SUBOBJ = 4,
 | |
| 	COUNTER_SUBGROUP_ID_TX_SUBOBJ = 5,
 | |
| 	COUNTER_SUBGROUP_ID_RX_RO_SR_SUBOBJ = 6,
 | |
| 	COUNTER_SUBGROUP_ID_TX_RO_SR_SUBOBJ = 7,
 | |
| 	COUNTER_SUBGROUP_ID_RX_TLV = 8,
 | |
| 	COUNTER_SUBGROUP_ID_TX_TLV = 9,
 | |
| 	COUNTER_SUBGROUP_ID_EVENT = 10
 | |
| 
 | |
| } pcep_session_counters_subgroup_ids;
 | |
| 
 | |
| bool run_session_logic(void);
 | |
| bool run_session_logic_with_infra(pceplib_infra_config *infra_config);
 | |
| 
 | |
| bool run_session_logic_wait_for_completion(void);
 | |
| 
 | |
| bool stop_session_logic(void);
 | |
| 
 | |
| /* Uses the standard PCEP TCP dest port = 4189 and an ephemeral src port.
 | |
|  * To use a specific dest or src port, set them other than 0 in the
 | |
|  * pcep_configuration. */
 | |
| pcep_session *create_pcep_session(pcep_configuration *config,
 | |
| 				  struct in_addr *pce_ip);
 | |
| pcep_session *create_pcep_session_ipv6(pcep_configuration *config,
 | |
| 				       struct in6_addr *pce_ip);
 | |
| 
 | |
| /* Send a PCEP close for this pcep_session */
 | |
| void close_pcep_session(pcep_session *session);
 | |
| void close_pcep_session_with_reason(pcep_session *session,
 | |
| 				    enum pcep_close_reason);
 | |
| 
 | |
| /* Destroy the PCEP session, a PCEP close should have
 | |
|  * already been sent with close_pcep_session() */
 | |
| void destroy_pcep_session(pcep_session *session);
 | |
| 
 | |
| void pcep_session_cancel_timers(pcep_session *session);
 | |
| 
 | |
| /* Increments transmitted message counters, additionally counters for the
 | |
|  * objects, sub-objects, and TLVs in the message will be incremented.  Received
 | |
|  * counters are incremented internally. */
 | |
| void increment_message_tx_counters(pcep_session *session,
 | |
| 				   struct pcep_message *message);
 | |
| 
 | |
| bool session_exists(pcep_session *session);
 | |
| 
 | |
| #endif /* INCLUDE_PCEPSESSIONLOGIC_H_ */
 |