]> git.proxmox.com Git - mirror_frr.git/blobdiff - pathd/path_pcep_controller.c
Merge pull request #9899 from Drumato/zebra-srv6-locator-detail-json-support
[mirror_frr.git] / pathd / path_pcep_controller.c
index f4871a4d8dfc79aa51a9ca8f52f803618455ed75..162c53590f9c14dfac207c7ba70e610d435f5bf7 100644 (file)
@@ -22,7 +22,7 @@
 #include "command.h"
 #include "libfrr.h"
 #include "printfrr.h"
-#include "version.h"
+#include "lib/version.h"
 #include "northbound.h"
 #include "frr_pthread.h"
 #include "jhash.h"
 
 #define MAX_RECONNECT_DELAY 120
 
-#define min(a, b)                                                              \
-       ({                                                                     \
-               __typeof__(a) _a = (a);                                        \
-               __typeof__(b) _b = (b);                                        \
-               _a <= _b ? _a : _b;                                            \
-       })
-
-
 /* Event handling data structures */
 enum pcep_ctrl_event_type {
        EV_UPDATE_PCC_OPTS = 1,
@@ -55,7 +47,10 @@ enum pcep_ctrl_event_type {
        EV_SYNC_PATH,
        EV_SYNC_DONE,
        EV_PCEPLIB_EVENT,
-       EV_RESET_PCC_SESSION
+       EV_RESET_PCC_SESSION,
+       EV_SEND_REPORT,
+       EV_SEND_ERROR,
+       EV_PATH_REFINED
 };
 
 struct pcep_ctrl_event_data {
@@ -73,18 +68,20 @@ struct pcep_main_event_data {
        void *payload;
 };
 
-/* Synchronous call arguments */
-
-struct get_counters_args {
+struct pcep_refine_path_event_data {
        struct ctrl_state *ctrl_state;
        int pcc_id;
-       struct counters_group *counters;
+       pcep_refine_callback_t continue_lsp_update_handler;
+       struct path *path;
+       void *payload;
 };
 
-struct send_report_args {
+/* Synchronous call arguments */
+
+struct get_counters_args {
        struct ctrl_state *ctrl_state;
        int pcc_id;
-       struct path *path;
+       struct counters_group *counters;
 };
 
 struct get_pcep_session_args {
@@ -95,13 +92,10 @@ struct get_pcep_session_args {
 
 /* Internal Functions Called From Main Thread */
 static int pcep_ctrl_halt_cb(struct frr_pthread *fpt, void **res);
+static int pcep_refine_path_event_cb(struct thread *thread);
 
 /* Internal Functions Called From Controller Thread */
 static int pcep_thread_finish_event_handler(struct thread *thread);
-static int pcep_thread_get_counters_callback(struct thread *t);
-static int pcep_thread_send_report_callback(struct thread *t);
-static int pcep_thread_get_pcep_session_callback(struct thread *t);
-static int pcep_thread_get_pcc_info_callback(struct thread *t);
 
 /* Controller Thread Timer Handler */
 static int schedule_thread_timer(struct ctrl_state *ctrl_state, int pcc_id,
@@ -148,6 +142,9 @@ static int pcep_thread_event_sync_done(struct ctrl_state *ctrl_state,
 static int pcep_thread_event_pathd_event(struct ctrl_state *ctrl_state,
                                         enum pcep_pathd_event_type type,
                                         struct path *path);
+static void
+pcep_thread_path_refined_event(struct ctrl_state *ctrl_state,
+                              struct pcep_refine_path_event_data *data);
 
 /* Main Thread Event Handler */
 static int send_to_main(struct ctrl_state *ctrl_state, int pcc_id,
@@ -280,48 +277,58 @@ struct counters_group *pcep_ctrl_get_counters(struct frr_pthread *fpt,
                                              int pcc_id)
 {
        struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
-       struct get_counters_args args = {
-               .ctrl_state = ctrl_state, .pcc_id = pcc_id, .counters = NULL};
-       thread_execute(ctrl_state->self, pcep_thread_get_counters_callback,
-                      &args, 0);
-       return args.counters;
+       struct counters_group *counters = NULL;
+       struct pcc_state *pcc_state;
+       pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
+       if (pcc_state) {
+               counters = pcep_lib_copy_counters(pcc_state->sess);
+       }
+       return counters;
 }
 
 pcep_session *pcep_ctrl_get_pcep_session(struct frr_pthread *fpt, int pcc_id)
 {
        struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
-       struct get_pcep_session_args args = {.ctrl_state = ctrl_state,
-                                            .pcc_id = pcc_id,
-                                            .pcep_session = NULL};
-       thread_execute(ctrl_state->self, pcep_thread_get_pcep_session_callback,
-                      &args, 0);
-       return args.pcep_session;
+       struct pcc_state *pcc_state;
+       pcep_session *session = NULL;
+
+       pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
+       if (pcc_state) {
+               session = pcep_lib_copy_pcep_session(pcc_state->sess);
+       }
+       return session;
 }
 
 struct pcep_pcc_info *pcep_ctrl_get_pcc_info(struct frr_pthread *fpt,
                                             const char *pce_name)
 {
        struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
-       struct pcep_pcc_info *args = XCALLOC(MTYPE_PCEP, sizeof(*args));
-       args->ctrl_state = ctrl_state;
-       strncpy(args->pce_name, pce_name, sizeof(args->pce_name));
-       thread_execute(ctrl_state->self, pcep_thread_get_pcc_info_callback,
-                      args, 0);
+       struct pcep_pcc_info *pcc_info = XCALLOC(MTYPE_PCEP, sizeof(*pcc_info));
+       if( pcc_info && ctrl_state){
+               strlcpy(pcc_info->pce_name, pce_name, sizeof(pcc_info->pce_name));
+               pcep_pcc_copy_pcc_info(ctrl_state->pcc, pcc_info);
+       }
+
+       return pcc_info;
+}
 
-       return args;
+int pcep_ctrl_send_report(struct frr_pthread *fpt, int pcc_id,
+                         struct path *path, bool is_stable)
+{
+       struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
+       return send_to_thread(ctrl_state, pcc_id, EV_SEND_REPORT, is_stable,
+                             path);
 }
 
-void pcep_ctrl_send_report(struct frr_pthread *fpt, int pcc_id,
-                          struct path *path)
+
+int pcep_ctrl_send_error(struct frr_pthread *fpt, int pcc_id,
+                        struct pcep_error *error)
 {
-       /* Sends a report stynchronously */
        struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
-       struct send_report_args args = {
-               .ctrl_state = ctrl_state, .pcc_id = pcc_id, .path = path};
-       thread_execute(ctrl_state->self, pcep_thread_send_report_callback,
-                      &args, 0);
+       return send_to_thread(ctrl_state, pcc_id, EV_SEND_ERROR, 0, error);
 }
 
+
 /* ------------ Internal Functions Called from Main Thread ------------ */
 
 int pcep_ctrl_halt_cb(struct frr_pthread *fpt, void **res)
@@ -333,6 +340,20 @@ int pcep_ctrl_halt_cb(struct frr_pthread *fpt, void **res)
        return 0;
 }
 
+int pcep_refine_path_event_cb(struct thread *thread)
+{
+       struct pcep_refine_path_event_data *data = THREAD_ARG(thread);
+       assert(data != NULL);
+       struct ctrl_state *ctrl_state = data->ctrl_state;
+       struct path *path = data->path;
+       assert(path != NULL);
+       int pcc_id = data->pcc_id;
+
+
+       path_pcep_refine_path(path);
+       return send_to_thread(ctrl_state, pcc_id, EV_PATH_REFINED, 0, data);
+}
+
 
 /* ------------ API Functions Called From Controller Thread ------------ */
 
@@ -348,6 +369,13 @@ void pcep_thread_update_path(struct ctrl_state *ctrl_state, int pcc_id,
                     path);
 }
 
+void pcep_thread_initiate_path(struct ctrl_state *ctrl_state, int pcc_id,
+                              struct path *path)
+{
+       send_to_main(ctrl_state, pcc_id, PCEP_MAIN_EVENT_INITIATE_CANDIDATE,
+                    path);
+}
+
 void pcep_thread_remove_candidate_path_segments(struct ctrl_state *ctrl_state,
                                                struct pcc_state *pcc_state)
 {
@@ -442,6 +470,41 @@ int pcep_thread_pcc_count(struct ctrl_state *ctrl_state)
        return ctrl_state->pcc_count;
 }
 
+int pcep_thread_refine_path(struct ctrl_state *ctrl_state, int pcc_id,
+                           pcep_refine_callback_t cb, struct path *path,
+                           void *payload)
+{
+       struct pcep_refine_path_event_data *data;
+
+       data = XCALLOC(MTYPE_PCEP, sizeof(*data));
+       data->ctrl_state = ctrl_state;
+       data->path = path;
+       data->pcc_id = pcc_id;
+       data->continue_lsp_update_handler = cb;
+       data->payload = payload;
+
+       thread_add_event(ctrl_state->main, pcep_refine_path_event_cb,
+                        (void *)data, 0, NULL);
+       return 0;
+}
+
+void pcep_thread_path_refined_event(struct ctrl_state *ctrl_state,
+                                   struct pcep_refine_path_event_data *data)
+{
+       assert(data != NULL);
+       int pcc_id = data->pcc_id;
+       pcep_refine_callback_t continue_lsp_update_handler = data->continue_lsp_update_handler;
+       assert(continue_lsp_update_handler != NULL);
+       struct path *path = data->path;
+       void *payload = data->payload;
+       struct pcc_state *pcc_state = NULL;
+       XFREE(MTYPE_PCEP, data);
+
+       pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
+       continue_lsp_update_handler(ctrl_state, pcc_state, path, payload);
+}
+
+
 /* ------------ Internal Functions Called From Controller Thread ------------ */
 
 int pcep_thread_finish_event_handler(struct thread *thread)
@@ -467,78 +530,6 @@ int pcep_thread_finish_event_handler(struct thread *thread)
        return 0;
 }
 
-int pcep_thread_get_counters_callback(struct thread *t)
-{
-       struct get_counters_args *args = THREAD_ARG(t);
-       assert(args != NULL);
-       struct ctrl_state *ctrl_state = args->ctrl_state;
-       assert(ctrl_state != NULL);
-       struct pcc_state *pcc_state;
-
-       pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, args->pcc_id);
-       if (pcc_state) {
-               args->counters = pcep_lib_copy_counters(pcc_state->sess);
-       } else {
-               args->counters = NULL;
-       }
-
-       return 0;
-}
-
-int pcep_thread_send_report_callback(struct thread *t)
-{
-       struct send_report_args *args = THREAD_ARG(t);
-       assert(args != NULL);
-       struct ctrl_state *ctrl_state = args->ctrl_state;
-       assert(ctrl_state != NULL);
-       struct pcc_state *pcc_state;
-
-       if (args->pcc_id == 0) {
-               for (int i = 0; i < MAX_PCC; i++) {
-                       if (ctrl_state->pcc[i]) {
-                               pcep_pcc_send_report(ctrl_state,
-                                                    ctrl_state->pcc[i],
-                                                    args->path);
-                       }
-               }
-       } else {
-               pcc_state =
-                       pcep_pcc_get_pcc_by_id(ctrl_state->pcc, args->pcc_id);
-               pcep_pcc_send_report(ctrl_state, pcc_state, args->path);
-       }
-
-       return 0;
-}
-
-int pcep_thread_get_pcep_session_callback(struct thread *t)
-{
-       struct get_pcep_session_args *args = THREAD_ARG(t);
-       assert(args != NULL);
-       struct ctrl_state *ctrl_state = args->ctrl_state;
-       assert(ctrl_state != NULL);
-       struct pcc_state *pcc_state;
-
-       pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, args->pcc_id);
-       if (pcc_state) {
-               args->pcep_session =
-                       pcep_lib_copy_pcep_session(pcc_state->sess);
-       }
-
-       return 0;
-}
-
-int pcep_thread_get_pcc_info_callback(struct thread *t)
-{
-       struct pcep_pcc_info *args = THREAD_ARG(t);
-       assert(args != NULL);
-       struct ctrl_state *ctrl_state = args->ctrl_state;
-       assert(ctrl_state != NULL);
-
-       pcep_pcc_copy_pcc_info(ctrl_state->pcc, args);
-
-       return 0;
-}
-
 /* ------------ Controller Thread Timer Handler ------------ */
 
 int schedule_thread_timer_with_cb(struct ctrl_state *ctrl_state, int pcc_id,
@@ -752,11 +743,15 @@ int pcep_thread_event_handler(struct thread *thread)
        /* Possible sub-type values */
        enum pcep_pathd_event_type path_event_type = PCEP_PATH_UNDEFINED;
 
-       /* Possible payload values */
+       /* Possible payload values, maybe an union would be better... */
        struct path *path = NULL;
        struct pcc_opts *pcc_opts = NULL;
        struct pce_opts *pce_opts = NULL;
        struct pcc_state *pcc_state = NULL;
+       struct pcep_refine_path_event_data *refine_data = NULL;
+
+       struct path *path_copy = NULL;
+       struct pcep_error *error = NULL;
 
        switch (type) {
        case EV_UPDATE_PCC_OPTS:
@@ -808,6 +803,37 @@ int pcep_thread_event_handler(struct thread *thread)
                                  (const char *)payload);
                }
                break;
+       case EV_SEND_REPORT:
+               assert(payload != NULL);
+               path = (struct path *)payload;
+               if (pcc_id == 0) {
+                       for (int i = 0; i < MAX_PCC; i++) {
+                               if (ctrl_state->pcc[i]) {
+                                       path_copy = pcep_copy_path(path);
+                                       pcep_pcc_send_report(
+                                               ctrl_state, ctrl_state->pcc[i],
+                                               path_copy, (bool)sub_type);
+                               }
+                       }
+               } else {
+                       pcc_state =
+                               pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
+                       pcep_pcc_send_report(ctrl_state, pcc_state, path,
+                                            (bool)sub_type);
+               }
+               break;
+       case EV_PATH_REFINED:
+               assert(payload != NULL);
+               refine_data = (struct pcep_refine_path_event_data *)payload;
+               pcep_thread_path_refined_event(ctrl_state, refine_data);
+               break;
+       case EV_SEND_ERROR:
+               assert(payload != NULL);
+               error = (struct pcep_error *)payload;
+               pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
+               pcep_pcc_send_error(ctrl_state, pcc_state, error,
+                                   (bool)sub_type);
+               break;
        default:
                flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR,
                          "Unexpected event received in controller thread: %u",
@@ -984,6 +1010,7 @@ int pcep_main_event_handler(struct thread *thread)
 
 
 /* ------------ Helper functions ------------ */
+
 void set_ctrl_state(struct frr_pthread *fpt, struct ctrl_state *ctrl_state)
 {
        assert(fpt != NULL);
@@ -1043,7 +1070,7 @@ void remove_pcc_state(struct ctrl_state *ctrl_state,
 
 uint32_t backoff_delay(uint32_t max, uint32_t base, uint32_t retry_count)
 {
-       uint32_t a = min(max, base * (1 << retry_count));
+       uint32_t a = MIN(max, base * (1 << retry_count));
        uint64_t r = frr_weak_random(), m = RAND_MAX;
        uint32_t b = (a / 2) + (r * (a / 2)) / m;
        return b;