2 * Copyright (C) 2020 NetDEF, Inc.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along
15 * with this program; see the file COPYING; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "lib_errors.h"
34 #include "pathd/pathd.h"
35 #include "pathd/path_ted.h"
36 #include "pathd/path_zebra.h"
37 #include "lib/command.h"
38 #include "lib/link_state.h"
40 static int path_zebra_opaque_msg_handler(ZAPI_CALLBACK_ARGS
);
42 struct zclient
*zclient
;
43 static struct zclient
*zclient_sync
;
45 /* Global Variables */
46 bool g_has_router_id_v4
= false;
47 bool g_has_router_id_v6
= false;
48 struct in_addr g_router_id_v4
;
49 struct in6_addr g_router_id_v6
;
50 pthread_mutex_t g_router_id_v4_mtx
= PTHREAD_MUTEX_INITIALIZER
;
51 pthread_mutex_t g_router_id_v6_mtx
= PTHREAD_MUTEX_INITIALIZER
;
54 * Gives the IPv4 router ID received from Zebra.
56 * @param router_id The in_addr strucure where to store the router id
57 * @return true if the router ID was available, false otherwise
59 bool get_ipv4_router_id(struct in_addr
*router_id
)
62 assert(router_id
!= NULL
);
63 pthread_mutex_lock(&g_router_id_v4_mtx
);
64 if (g_has_router_id_v4
) {
65 memcpy(router_id
, &g_router_id_v4
, sizeof(*router_id
));
68 pthread_mutex_unlock(&g_router_id_v4_mtx
);
73 * Gives the IPv6 router ID received from Zebra.
75 * @param router_id The in6_addr strucure where to store the router id
76 * @return true if the router ID was available, false otherwise
78 bool get_ipv6_router_id(struct in6_addr
*router_id
)
81 assert(router_id
!= NULL
);
82 pthread_mutex_lock(&g_router_id_v6_mtx
);
83 if (g_has_router_id_v6
) {
84 memcpy(router_id
, &g_router_id_v6
, sizeof(*router_id
));
87 pthread_mutex_unlock(&g_router_id_v6_mtx
);
91 static void path_zebra_connected(struct zclient
*zclient
)
93 struct srte_policy
*policy
;
95 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
96 zclient_send_router_id_update(zclient
, ZEBRA_ROUTER_ID_ADD
, AFI_IP6
,
99 RB_FOREACH (policy
, srte_policy_head
, &srte_policies
) {
100 struct srte_candidate
*candidate
;
101 struct srte_segment_list
*segment_list
;
103 candidate
= policy
->best_candidate
;
107 segment_list
= candidate
->lsp
->segment_list
;
111 path_zebra_add_sr_policy(policy
, segment_list
);
115 static int path_zebra_sr_policy_notify_status(ZAPI_CALLBACK_ARGS
)
117 struct zapi_sr_policy zapi_sr_policy
;
118 struct srte_policy
*policy
;
119 struct srte_candidate
*best_candidate_path
;
121 if (zapi_sr_policy_notify_status_decode(zclient
->ibuf
, &zapi_sr_policy
))
124 policy
= srte_policy_find(zapi_sr_policy
.color
,
125 &zapi_sr_policy
.endpoint
);
129 best_candidate_path
= policy
->best_candidate
;
130 if (!best_candidate_path
)
133 srte_candidate_status_update(best_candidate_path
,
134 zapi_sr_policy
.status
);
139 /* Router-id update message from zebra. */
140 static int path_zebra_router_id_update(ZAPI_CALLBACK_ARGS
)
144 char buf
[PREFIX2STR_BUFFER
];
145 zebra_router_id_update_read(zclient
->ibuf
, &pref
);
146 if (pref
.family
== AF_INET
) {
147 pthread_mutex_lock(&g_router_id_v4_mtx
);
148 memcpy(&g_router_id_v4
, &pref
.u
.prefix4
,
149 sizeof(g_router_id_v4
));
150 g_has_router_id_v4
= true;
151 inet_ntop(AF_INET
, &g_router_id_v4
, buf
, sizeof(buf
));
152 pthread_mutex_unlock(&g_router_id_v4_mtx
);
154 } else if (pref
.family
== AF_INET6
) {
155 pthread_mutex_lock(&g_router_id_v6_mtx
);
156 memcpy(&g_router_id_v6
, &pref
.u
.prefix6
,
157 sizeof(g_router_id_v6
));
158 g_has_router_id_v6
= true;
159 inet_ntop(AF_INET6
, &g_router_id_v6
, buf
, sizeof(buf
));
160 pthread_mutex_unlock(&g_router_id_v6_mtx
);
163 zlog_warn("Unexpected router ID address family for vrf %u: %u",
164 vrf_id
, pref
.family
);
167 zlog_info("%s Router Id updated for VRF %u: %s", family
, vrf_id
, buf
);
172 * Adds a segment routing policy to Zebra.
174 * @param policy The policy to add
175 * @param segment_list The segment list for the policy
177 void path_zebra_add_sr_policy(struct srte_policy
*policy
,
178 struct srte_segment_list
*segment_list
)
180 struct zapi_sr_policy zp
= {};
181 struct srte_segment_entry
*segment
;
183 zp
.color
= policy
->color
;
184 zp
.endpoint
= policy
->endpoint
;
185 strlcpy(zp
.name
, policy
->name
, sizeof(zp
.name
));
186 zp
.segment_list
.type
= ZEBRA_LSP_SRTE
;
187 zp
.segment_list
.local_label
= policy
->binding_sid
;
188 zp
.segment_list
.label_num
= 0;
189 RB_FOREACH (segment
, srte_segment_entry_head
, &segment_list
->segments
)
190 zp
.segment_list
.labels
[zp
.segment_list
.label_num
++] =
192 policy
->status
= SRTE_POLICY_STATUS_GOING_UP
;
194 (void)zebra_send_sr_policy(zclient
, ZEBRA_SR_POLICY_SET
, &zp
);
198 * Deletes a segment policy from Zebra.
200 * @param policy The policy to remove
202 void path_zebra_delete_sr_policy(struct srte_policy
*policy
)
204 struct zapi_sr_policy zp
= {};
206 zp
.color
= policy
->color
;
207 zp
.endpoint
= policy
->endpoint
;
208 strlcpy(zp
.name
, policy
->name
, sizeof(zp
.name
));
209 zp
.segment_list
.type
= ZEBRA_LSP_SRTE
;
210 zp
.segment_list
.local_label
= policy
->binding_sid
;
211 zp
.segment_list
.label_num
= 0;
212 policy
->status
= SRTE_POLICY_STATUS_DOWN
;
214 (void)zebra_send_sr_policy(zclient
, ZEBRA_SR_POLICY_DELETE
, &zp
);
218 * Allocates a label from Zebra's label manager.
220 * @param label the label to be allocated
221 * @return 0 if the label has been allocated, -1 otherwise
223 int path_zebra_request_label(mpls_label_t label
)
228 ret
= lm_get_label_chunk(zclient_sync
, 0, label
, 1, &start
, &end
);
230 zlog_warn("%s: error getting label range!", __func__
);
238 * Releases a previously allocated label from Zebra's label manager.
240 * @param label The label to release
241 * @return 0 ifthe label has beel released, -1 otherwise
243 void path_zebra_release_label(mpls_label_t label
)
247 ret
= lm_release_label_chunk(zclient_sync
, label
, label
);
249 zlog_warn("%s: error releasing label range!", __func__
);
252 static void path_zebra_label_manager_connect(void)
254 /* Connect to label manager. */
255 while (zclient_socket_connect(zclient_sync
) < 0) {
256 zlog_warn("%s: error connecting synchronous zclient!",
260 set_nonblocking(zclient_sync
->sock
);
262 /* Send hello to notify zebra this is a synchronous client */
263 while (zclient_send_hello(zclient_sync
) < 0) {
264 zlog_warn("%s: Error sending hello for synchronous zclient!",
269 while (lm_label_manager_connect(zclient_sync
, 0) != 0) {
270 zlog_warn("%s: error connecting to label manager!", __func__
);
275 static int path_zebra_opaque_msg_handler(ZAPI_CALLBACK_ARGS
)
279 struct zapi_opaque_msg info
;
283 if (zclient_opaque_decode(s
, &info
) != 0)
287 case LINK_STATE_UPDATE
:
288 case LINK_STATE_SYNC
:
289 /* Start receiving ls data so cancel request sync timer */
290 path_ted_timer_sync_cancel();
292 struct ls_message
*msg
= ls_parse_msg(s
);
295 zlog_debug("%s: [rcv ted] ls (%s) msg (%s)-(%s) !",
297 info
.type
== LINK_STATE_UPDATE
298 ? "LINK_STATE_UPDATE"
300 LS_MSG_TYPE_PRINT(msg
->type
),
301 LS_MSG_EVENT_PRINT(msg
->event
));
304 "%s: [rcv ted] Could not parse LinkState stream message.",
309 ret
= path_ted_rcvd_message(msg
);
311 /* Update local configuration after process update. */
312 path_ted_segment_list_refresh();
315 zlog_debug("%s: [rcv ted] unknown opaque event (%d) !",
316 __func__
, info
.type
);
323 static zclient_handler
*const path_handlers
[] = {
324 [ZEBRA_SR_POLICY_NOTIFY_STATUS
] = path_zebra_sr_policy_notify_status
,
325 [ZEBRA_ROUTER_ID_UPDATE
] = path_zebra_router_id_update
,
326 [ZEBRA_OPAQUE_MESSAGE
] = path_zebra_opaque_msg_handler
,
330 * Initializes Zebra asynchronous connection.
332 * @param master The master thread
334 void path_zebra_init(struct thread_master
*master
)
336 struct zclient_options options
= zclient_options_default
;
337 options
.synchronous
= true;
339 /* Initialize asynchronous zclient. */
340 zclient
= zclient_new(master
, &zclient_options_default
, path_handlers
,
341 array_size(path_handlers
));
342 zclient_init(zclient
, ZEBRA_ROUTE_SRTE
, 0, &pathd_privs
);
343 zclient
->zebra_connected
= path_zebra_connected
;
345 /* Initialize special zclient for synchronous message exchanges. */
346 zclient_sync
= zclient_new(master
, &options
, NULL
, 0);
347 zclient_sync
->sock
= -1;
348 zclient_sync
->redist_default
= ZEBRA_ROUTE_SRTE
;
349 zclient_sync
->instance
= 1;
350 zclient_sync
->privs
= &pathd_privs
;
352 /* Connect to the LM. */
353 path_zebra_label_manager_connect();