1 /*------------------------------------------------------------------------------------------------*/
2 /* UNICENS V2.1.0-3491 */
3 /* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG. */
5 /* This program is free software: you can redistribute it and/or modify */
6 /* it under the terms of the GNU General Public License as published by */
7 /* the Free Software Foundation, either version 2 of the License, or */
8 /* (at your option) any later version. */
10 /* This program is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
13 /* GNU General Public License for more details. */
15 /* You should have received a copy of the GNU General Public License */
16 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* You may also obtain this software under a propriety license from Microchip. */
19 /* Please contact Microchip for further information. */
20 /*------------------------------------------------------------------------------------------------*/
24 * \brief Implementation of the Route Management.
26 * \cond UCS_INTERNAL_DOC
31 /*------------------------------------------------------------------------------------------------*/
33 /*------------------------------------------------------------------------------------------------*/
36 /*------------------------------------------------------------------------------------------------*/
37 /* Service parameters */
38 /*------------------------------------------------------------------------------------------------*/
39 /*! \brief Priority of the RSM service used by scheduler */
40 static const uint8_t RTM_SRV_PRIO = 250U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */
41 /*! \brief Event for resuming the handling of routes */
42 static const Srv_Event_t RTM_EVENT_HANDLE_NEXTROUTE = 0x01U;
43 /*! \brief Event for pausing the processing of routes */
44 static const Srv_Event_t RTM_EVENT_PROCESS_PAUSE = 0x02U;
45 /*! \brief Interval (in ms) for checking the RoutingJob queue */
46 static const uint16_t RTM_JOB_CHECK_INTERVAL = 50U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */
48 /*------------------------------------------------------------------------------------------------*/
49 /* Internal Constants */
50 /*------------------------------------------------------------------------------------------------*/
51 /*! \brief Mask for the Network Availability Info */
52 static const uint32_t RTM_MASK_NETWORK_AVAILABILITY = 0x0002U;
54 /*------------------------------------------------------------------------------------------------*/
55 /* Internal prototypes */
56 /*------------------------------------------------------------------------------------------------*/
57 static void Rtm_Service(void *self);
58 static void Rtm_HandleNextRoute(CRouteManagement * self);
59 static void Rtm_BuildRoute(CRouteManagement * self);
60 static void Rtm_DestroyRoute(CRouteManagement * self);
61 static bool Rtm_SetNextRouteIndex(CRouteManagement * self);
62 static void Rtm_HandleRoutingError(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr);
63 static void Rtm_ApiLocking(CRouteManagement *self, bool status);
64 static bool Rtm_IsApiFree(CRouteManagement *self);
65 static Ucs_Return_t Rtm_BuildEndPoint(CRouteManagement * self, Ucs_Rm_EndPoint_t * endpoint_ptr);
66 static Ucs_Return_t Rtm_DeactivateRouteEndPoint(CRouteManagement * self, Ucs_Rm_EndPoint_t * endpoint_ptr);
67 static Ucs_Rm_Route_t * Rtm_GetNextRoute(CRouteManagement * self);
68 static bool Rtm_IsRouteBuildable(CRouteManagement * self);
69 static bool Rtm_IsRouteDestructible(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr);
70 static bool Rtm_IsRouteActivatable(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr);
71 static void Rtm_DisableRoute(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr);
72 static void Rtm_EnableRoute(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr);
73 static bool Rtm_CheckEpResultSeverity(CRouteManagement * self, Ucs_Rm_Route_t * tgt_route_ptr, Ucs_Rm_EndPoint_t * endpoint_ptr);
74 static void Rtm_EndPointDeterioredCb(void *self, void *result_ptr);
75 static void Rtm_StartTmr4HandlingRoutes(CRouteManagement * self);
76 static void Rtm_ExecRoutesHandling(void * self);
77 static void Rtm_HandleProcessTermination(CRouteManagement * self);
78 static void Rtm_StopRoutesHandling(CRouteManagement * self);
79 static void Rtm_StartRoutingTimer (CRouteManagement * self);
80 static void Rtm_ResetNodesAvailable(CRouteManagement * self);
81 static bool Rtm_AreRouteNodesAvailable(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr);
82 static bool Rtm_UnlockPossibleBlockings(CRouteManagement * self, Ucs_Rm_Route_t * tgt_route_ptr, Ucs_Rm_EndPoint_t * endpoint_ptr);
83 static void Rtm_ReleaseSuspendedRoutes(CRouteManagement * self, Ucs_Rm_Node_t *node_ptr);
84 static void Rtm_ForcesRouteToIdle(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr);
85 static void Rtm_UcsInitSucceededCb(void *self, void *event_ptr);
86 static void Rtm_MnsNwStatusInfosCb(void *self, void *event_ptr);
87 static void Rtm_UninitializeService(void *self, void *error_code_ptr);
89 /*------------------------------------------------------------------------------------------------*/
90 /* Implementation of class CRouteManagement */
91 /*------------------------------------------------------------------------------------------------*/
92 /*------------------------------------------------------------------------------------------------*/
93 /* Initialization Methods */
94 /*------------------------------------------------------------------------------------------------*/
95 /*! \brief Constructor of the Remote Sync Manager class.
96 * \param self Instance pointer
97 * \param init_ptr init data_ptr
99 void Rtm_Ctor(CRouteManagement *self, Rtm_InitData_t *init_ptr)
101 MISC_MEM_SET(self, 0, sizeof(CRouteManagement));
103 /* Init all reference instances */
104 self->base_ptr = init_ptr->base_ptr;
105 self->epm_ptr = init_ptr->epm_ptr;
106 self->tm_ptr = &init_ptr->base_ptr->tm;
107 self->net_ptr = init_ptr->net_ptr;
108 self->report_fptr = init_ptr->report_fptr;
110 /* Initialize Route Management service */
111 Srv_Ctor(&self->rtm_srv, RTM_SRV_PRIO, self, &Rtm_Service);
113 /* Add Observer for UCS initialization Result */
114 Mobs_Ctor(&self->ucsinit_observer, self, EH_E_INIT_SUCCEEDED, &Rtm_UcsInitSucceededCb);
115 Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->ucsinit_observer);
117 /* Init and Add observer to the UCS termination event */
118 Mobs_Ctor(&self->ucstermination_observer, self, EH_M_TERMINATION_EVENTS, &Rtm_UninitializeService);
119 Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->ucstermination_observer);
121 /* Add RTM service to scheduler */
122 (void)Scd_AddService(&self->base_ptr->scd, &self->rtm_srv);
125 /*------------------------------------------------------------------------------------------------*/
127 /*------------------------------------------------------------------------------------------------*/
128 /*! \brief Starts the process to buildup the given routes list.
130 * This function shall only be called once.
131 * \param self Instance pointer
132 * \param routes_list Routes list to be built
133 * \param size Size of the routes list
134 * \return Possible return values are
135 * - \c UCS_RET_ERR_API_LOCKED the API is locked.
136 * - \c UCS_RET_SUCCESS if the transmission was started successfully
137 * - \c UCS_RET_ERR_BUFFER_OVERFLOW if no TxHandles available
138 * - \c UCS_RET_ERR_PARAM At least one parameter is wrong
140 Ucs_Return_t Rtm_StartProcess(CRouteManagement * self, Ucs_Rm_Route_t routes_list[], uint16_t size)
142 Ucs_Return_t result = UCS_RET_ERR_API_LOCKED;
144 if (Rtm_IsApiFree(self) != false)
146 result = UCS_RET_ERR_PARAM;
147 if ((self != NULL) && (routes_list != NULL) && (size > 0U))
150 /* Function remains from now locked */
151 Rtm_ApiLocking(self, true);
153 /* Initializes private variables */
154 self->routes_list_size = size;
155 self->curr_route_index = 0U;
156 self->routes_list_ptr = &routes_list[0];
158 /* Initializes internal data structure */
159 for (; k < size; k++)
161 MISC_MEM_SET(&routes_list[k].internal_infos, 0, sizeof(Ucs_Rm_RouteInt_t));
164 Rtm_StartTmr4HandlingRoutes(self);
165 result = UCS_RET_SUCCESS;
172 /*! \brief Deactivates respectively destroys the given route reference
173 * \param self Instance pointer
174 * \param route_ptr Reference to the route to be destroyed
175 * \return Possible return values are
176 * - \c UCS_RET_SUCCESS if the transmission was started successfully
177 * - \c UCS_RET_ERR_PARAM At least one parameter is NULL
178 * - \c UCS_RET_ERR_ALREADY_SET Route is already inactive
180 Ucs_Return_t Rtm_DeactivateRoute (CRouteManagement * self, Ucs_Rm_Route_t * route_ptr)
182 Ucs_Return_t result = UCS_RET_ERR_PARAM;
184 if ((self != NULL) && (route_ptr != NULL))
186 if (Rtm_IsRouteDestructible(self, route_ptr))
188 Rtm_DisableRoute(self, route_ptr);
189 Rtm_StartTmr4HandlingRoutes(self);
190 result = UCS_RET_SUCCESS;
194 result = UCS_RET_ERR_ALREADY_SET;
201 /*! \brief Builds respectively activates the given route reference
202 * \param self Instance pointer
203 * \param route_ptr Reference to the route to be destroyed
204 * \return Possible return values are
205 * - \c UCS_RET_SUCCESS if the transmission was started successfully
206 * - \c UCS_RET_ERR_PARAM At least one parameter is NULL
207 * - \c UCS_RET_ERR_ALREADY_SET Route is already active
209 Ucs_Return_t Rtm_ActivateRoute(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr)
211 Ucs_Return_t result = UCS_RET_ERR_PARAM;
213 if ((self != NULL) && (route_ptr != NULL))
215 if (Rtm_IsRouteActivatable(self, route_ptr))
217 Rtm_EnableRoute(self, route_ptr);
218 Rtm_StartTmr4HandlingRoutes(self);
219 result = UCS_RET_SUCCESS;
223 result = UCS_RET_ERR_ALREADY_SET;
230 /*! \brief Sets the given node to \c available or \c not \c available and triggers the routing process to handle this change.
231 * \details In case of \c Available the function starts the routing process that checks whether there are endpoints to build on this node.
232 * In case of \c Unavailable the function informs sub modules like XRM to check whether there are resources to release and simultaneously unlock \c suspended routes that
234 * \param self The routing instance pointer
235 * \param node_ptr Reference to the node to be looked for.
236 * \param available Specifies whether the node is available or not
237 * \return Possible return values are shown in the table below.
238 * Value | Description
239 * --------------------------- | ---------------------------------------------------------------------
240 * UCS_RET_SUCCESS | No error
241 * UCS_RET_ERR_ALREADY_SET | Node is already set to "available" or "not available"
242 * UCS_RET_ERR_PARAM | At least one parameter is NULL.
243 * UCS_RET_ERR_NOT_INITIALIZED | UNICENS is not initialized
244 * UCS_RET_ERR_NOT_AVAILABLE | The function cannot be processed because the network is not available
246 Ucs_Return_t Rtm_SetNodeAvailable(CRouteManagement * self, Ucs_Rm_Node_t *node_ptr, bool available)
248 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
250 if ((self != NULL) && (node_ptr != NULL) && (node_ptr->signature_ptr != NULL))
252 ret_val = UCS_RET_ERR_NOT_AVAILABLE;
253 if (self->nw_available)
255 ret_val = UCS_RET_ERR_ALREADY_SET;
258 if (node_ptr->internal_infos.available == 0x00U)
260 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Node with Addr {%X} is available", 1U, node_ptr->signature_ptr->node_address));
261 node_ptr->internal_infos.available = 0x01U;
262 Rtm_StartRoutingTimer(self);
263 ret_val = UCS_RET_SUCCESS;
268 if (node_ptr->internal_infos.available == 0x01U)
270 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Node with Addr {%X} is not available", 1U, node_ptr->signature_ptr->node_address));
271 node_ptr->internal_infos.available = 0x00U;
272 Rtm_ReleaseSuspendedRoutes(self, node_ptr);
273 Epm_ReportInvalidDevice (self->epm_ptr, node_ptr->signature_ptr->node_address);
274 ret_val = UCS_RET_SUCCESS;
283 /*! \brief Retrieves the "available" flag of the given node.
284 * \param self The routing instance pointer
285 * \param node_ptr Reference to the node to be looked for.
286 * \return The "available" flag of the node.
288 bool Rtm_GetNodeAvailable(CRouteManagement * self, Ucs_Rm_Node_t *node_ptr)
290 bool ret_val = false;
294 if (node_ptr != NULL)
296 ret_val = (node_ptr->internal_infos.available == 0x01U) ? true:false;
302 /*! \brief Retrieves currently references of all routes attached to the given endpoint and stores It into an external routes table provided by user application.
303 * Thus, User application should provide an external reference to an empty routes table where the potential routes will be stored.
304 * That is, user application is responsible to allocate enough space to store the found routes. Otherwise, the max routes found will
305 * equal the list size.
306 * \param self The routing instance pointer
307 * \param ep_inst Reference to the endpoint to be looked for.
308 * \param ext_routes_list External empty table allocated by user application
309 * \param size_list Size of the provided list
310 * \return Possible return values are shown in the table below.
311 * Value | Description
312 * --------------------------- | ---------------------------------------------------------------------
313 * UCS_RET_SUCCESS | No error
314 * UCS_RET_ERR_PARAM | At least one parameter is NULL.
316 Ucs_Return_t Rtm_GetAttachedRoutes(CRouteManagement * self, Ucs_Rm_EndPoint_t * ep_inst,
317 Ucs_Rm_Route_t * ext_routes_list[], uint16_t size_list)
319 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
323 if ((ep_inst != NULL) && (ext_routes_list != NULL) && (size_list > 0U))
325 bool curr_index_empty = true;
326 uint8_t k = 0U, num_attached_routes = Sub_GetNumObservers(&ep_inst->internal_infos.subject_obj);
327 CDlNode *n_tmp = (&(ep_inst->internal_infos.subject_obj))->list.head;
328 Ucs_Rm_Route_t * tmp_rt = NULL;
329 ret_val = UCS_RET_SUCCESS;
331 for (; ((k < size_list) && (num_attached_routes > 0U) && (n_tmp != NULL)); k++)
333 ext_routes_list[k] = NULL;
336 CObserver *o_tmp = (CObserver *)n_tmp->data_ptr;
337 tmp_rt = (Ucs_Rm_Route_t *)o_tmp->inst_ptr;
338 if ((tmp_rt != NULL) && ((tmp_rt->internal_infos.route_state == UCS_RM_ROUTE_BUILT) ||
339 (tmp_rt->internal_infos.route_state == UCS_RM_ROUTE_CONSTRUCTION) ||
340 (tmp_rt->internal_infos.route_state == UCS_RM_ROUTE_DESTRUCTION)))
342 curr_index_empty = false;
343 ext_routes_list[k] = tmp_rt;
346 num_attached_routes--;
348 } while ((curr_index_empty) && (num_attached_routes > 0U));
349 curr_index_empty = true;
354 ext_routes_list[k] = NULL;
361 /*! \brief Retrieves the \c ConnectionLabel of the given route.
362 * \param self The routing instance pointer
363 * \param route_ptr Reference to the route to be looked for.
364 * \return The "ConnectionLabel" of this route.
366 uint16_t Rtm_GetConnectionLabel (CRouteManagement * self, Ucs_Rm_Route_t * route_ptr)
368 uint16_t conn_label = 0U;
370 if ((self != NULL) && (route_ptr != NULL) && (route_ptr->internal_infos.route_state == UCS_RM_ROUTE_BUILT))
372 conn_label = Epm_GetConnectionLabel(self->epm_ptr, route_ptr->source_endpoint_ptr);
378 /*------------------------------------------------------------------------------------------------*/
379 /* Private Methods */
380 /*------------------------------------------------------------------------------------------------*/
381 /*! \brief Service function of the Sync management.
382 * \param self Instance pointer
384 static void Rtm_Service(void *self)
386 CRouteManagement *self_ = (CRouteManagement *)self;
387 Srv_Event_t event_mask;
388 Srv_GetEvent(&self_->rtm_srv, &event_mask);
390 /* Event to process list of routes */
391 if((event_mask & RTM_EVENT_HANDLE_NEXTROUTE) == RTM_EVENT_HANDLE_NEXTROUTE)
393 Srv_ClearEvent(&self_->rtm_srv, RTM_EVENT_HANDLE_NEXTROUTE);
394 Rtm_HandleNextRoute(self_);
397 /* Event to pause processing of routes list */
398 if ((event_mask & RTM_EVENT_PROCESS_PAUSE) == RTM_EVENT_PROCESS_PAUSE)
400 Srv_ClearEvent(&self_->rtm_srv, RTM_EVENT_PROCESS_PAUSE);
401 Rtm_StopRoutesHandling(self_);
405 /*! \brief This function starts the routing timer.
407 * Whenever this function is called the routing management process will resume in case it has been paused.
408 * \param self Instance pointer
410 static void Rtm_StartRoutingTimer (CRouteManagement * self)
412 if ((NULL != self) && (NULL != self->routes_list_ptr) &&
413 (0U < self->routes_list_size))
415 Rtm_StartTmr4HandlingRoutes(self);
419 /*! \brief Handles the next route in the list.
420 * \param self Instance pointer
422 static void Rtm_HandleNextRoute(CRouteManagement * self)
424 Ucs_Rm_Route_t * tmp_route;
425 self->curr_route_ptr = Rtm_GetNextRoute(self);
426 tmp_route = self->curr_route_ptr;
428 switch (tmp_route->internal_infos.route_state)
430 case UCS_RM_ROUTE_IDLE:
431 if (Rtm_IsRouteBuildable(self) == true)
433 Rtm_BuildRoute(self);
437 case UCS_RM_ROUTE_CONSTRUCTION:
438 Rtm_BuildRoute(self);
441 case UCS_RM_ROUTE_DETERIORATED:
442 Rtm_HandleRoutingError(self, tmp_route);
445 case UCS_RM_ROUTE_DESTRUCTION:
446 Rtm_DestroyRoute(self);
449 case UCS_RM_ROUTE_SUSPENDED:
450 case UCS_RM_ROUTE_BUILT:
451 if (tmp_route->active == false)
453 Rtm_DestroyRoute(self);
462 /*! \brief Checks whether the given route is buildable.
463 * \param self Instance pointer
464 * \return \c true if the route is buildable, otherwise \c false.
466 static bool Rtm_IsRouteBuildable(CRouteManagement * self)
468 bool result_check = false;
470 if (self->curr_route_ptr != NULL)
472 if ((self->curr_route_ptr->internal_infos.route_state == UCS_RM_ROUTE_IDLE) &&
473 (self->curr_route_ptr->active == true) &&
474 (self->curr_route_ptr->source_endpoint_ptr != NULL) &&
475 (self->curr_route_ptr->sink_endpoint_ptr != NULL))
484 /*! \brief Checks whether the given route is destructible.
485 * \param self Instance pointer
486 * \param route_ptr Reference route to be checked
487 * \return \c true if the route is destructible, otherwise \c false.
489 static bool Rtm_IsRouteDestructible(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr)
491 bool result_check = false;
494 if ((route_ptr != NULL) && (route_ptr->active == 0x01U) && ((route_ptr->internal_infos.route_state == UCS_RM_ROUTE_BUILT) ||
495 (route_ptr->internal_infos.route_state == UCS_RM_ROUTE_SUSPENDED)))
503 /*! \brief Checks whether the given route can be activated.
504 * \param self Instance pointer
505 * \param route_ptr Reference route to be checked
506 * \return \c true if the route is destructible, otherwise \c false.
508 static bool Rtm_IsRouteActivatable(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr)
510 bool result_check = false;
513 if ((route_ptr != NULL) && (route_ptr->internal_infos.route_state == UCS_RM_ROUTE_IDLE) && (route_ptr->active == 0x0U))
521 /*! \brief Deactivates the given route reference.
522 * \param self Instance pointer
523 * \param route_ptr Reference route to be deactivated
525 static void Rtm_DisableRoute(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr)
529 if (route_ptr != NULL)
531 route_ptr->active = false;
535 /*! \brief Activates the given route reference.
536 * \param self Instance pointer
537 * \param route_ptr Reference route to be activated
539 static void Rtm_EnableRoute(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr)
543 if (route_ptr != NULL)
545 route_ptr->active = true;
549 /*! \brief Builds the current Route.
550 * \param self Instance pointer
552 static void Rtm_BuildRoute(CRouteManagement * self)
554 bool result_critical = false;
555 Ucs_Rm_EndPointState_t ep_state = Epm_GetState(self->epm_ptr, self->curr_route_ptr->source_endpoint_ptr);
559 result_critical = Rtm_CheckEpResultSeverity(self, self->curr_route_ptr, self->curr_route_ptr->source_endpoint_ptr);
560 if (!result_critical)
562 if (self->curr_route_ptr->internal_infos.src_obsvr_initialized == 0U)
564 self->curr_route_ptr->internal_infos.src_obsvr_initialized = 1U;
565 Epm_DelObserver(self->curr_route_ptr->source_endpoint_ptr, &self->curr_route_ptr->internal_infos.source_ep_observer);
566 Obs_Ctor(&self->curr_route_ptr->internal_infos.source_ep_observer, self->curr_route_ptr, &Rtm_EndPointDeterioredCb);
567 /* Initializes source endpoint internal data */
568 Epm_InitInternalInfos (self->epm_ptr, self->curr_route_ptr->source_endpoint_ptr);
570 (void)Rtm_BuildEndPoint(self, self->curr_route_ptr->source_endpoint_ptr);
574 case UCS_RM_EP_BUILT:
575 /* In case of shared source endpoint by another route */
576 if (self->curr_route_ptr->internal_infos.src_obsvr_initialized == 0U)
578 self->curr_route_ptr->internal_infos.src_obsvr_initialized = 1U;
579 Epm_DelObserver(self->curr_route_ptr->source_endpoint_ptr, &self->curr_route_ptr->internal_infos.source_ep_observer);
580 Obs_Ctor(&self->curr_route_ptr->internal_infos.source_ep_observer, self->curr_route_ptr, &Rtm_EndPointDeterioredCb);
581 Epm_AddObserver(self->curr_route_ptr->source_endpoint_ptr, &self->curr_route_ptr->internal_infos.source_ep_observer);
583 ep_state = Epm_GetState(self->epm_ptr, self->curr_route_ptr->sink_endpoint_ptr);
587 result_critical = Rtm_CheckEpResultSeverity(self, self->curr_route_ptr, self->curr_route_ptr->sink_endpoint_ptr);
588 if (!result_critical)
590 if (self->curr_route_ptr->internal_infos.sink_obsvr_initialized == 0U)
592 self->curr_route_ptr->internal_infos.sink_obsvr_initialized = 1U;
593 Obs_Ctor(&self->curr_route_ptr->internal_infos.sink_ep_observer, self->curr_route_ptr, &Rtm_EndPointDeterioredCb);
594 /* Initializes sink endpoint internal data */
595 Epm_InitInternalInfos (self->epm_ptr, self->curr_route_ptr->sink_endpoint_ptr);
597 Epm_SetConnectionLabel(self->epm_ptr, self->curr_route_ptr->sink_endpoint_ptr, Epm_GetConnectionLabel(self->epm_ptr, self->curr_route_ptr->source_endpoint_ptr));
598 (void)Rtm_BuildEndPoint(self, self->curr_route_ptr->sink_endpoint_ptr);
602 case UCS_RM_EP_BUILT:
603 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Route id {%X} is built", 1U, self->curr_route_ptr->route_id));
604 self->curr_route_ptr->internal_infos.route_state = UCS_RM_ROUTE_BUILT;
605 if (self->report_fptr != NULL)
607 self->report_fptr(self->curr_route_ptr, UCS_RM_ROUTE_INFOS_BUILT, self->base_ptr->ucs_user_ptr);
611 case UCS_RM_EP_XRMPROCESSING:
613 result_critical = Rtm_UnlockPossibleBlockings(self, self->curr_route_ptr, self->curr_route_ptr->sink_endpoint_ptr);
618 case UCS_RM_EP_XRMPROCESSING:
620 result_critical = Rtm_UnlockPossibleBlockings(self, self->curr_route_ptr, self->curr_route_ptr->source_endpoint_ptr);
626 self->curr_route_ptr->internal_infos.route_state = UCS_RM_ROUTE_DETERIORATED;
630 /*! \brief Destroys the current Route.
631 * \param self Instance pointer
633 static void Rtm_DestroyRoute(CRouteManagement * self)
635 bool result_critical = false;
636 bool destruction_completed = false;
638 Ucs_Rm_EndPointState_t ep_state = Epm_GetState(self->epm_ptr, self->curr_route_ptr->sink_endpoint_ptr);
641 case UCS_RM_EP_BUILT:
642 (void)Rtm_DeactivateRouteEndPoint(self, self->curr_route_ptr->sink_endpoint_ptr);
646 ep_state = Epm_GetState(self->epm_ptr, self->curr_route_ptr->source_endpoint_ptr);
649 case UCS_RM_EP_BUILT:
650 /* if source endpoint cannot be built since it's used in another route(s), however consider that the route is destroyed. */
651 if (Rtm_DeactivateRouteEndPoint(self, self->curr_route_ptr->source_endpoint_ptr) == UCS_RET_ERR_INVALID_SHADOW)
653 destruction_completed = true;
658 destruction_completed = true;
661 case UCS_RM_EP_XRMPROCESSING:
663 result_critical = Rtm_UnlockPossibleBlockings(self, self->curr_route_ptr, self->curr_route_ptr->source_endpoint_ptr);
668 case UCS_RM_EP_XRMPROCESSING:
670 result_critical = Rtm_UnlockPossibleBlockings(self, self->curr_route_ptr, self->curr_route_ptr->sink_endpoint_ptr);
676 self->curr_route_ptr->internal_infos.route_state = UCS_RM_ROUTE_DETERIORATED;
678 else if (destruction_completed)
680 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Route id {%X} has been destroyed", 1U, self->curr_route_ptr->route_id));
681 self->curr_route_ptr->internal_infos.route_state = UCS_RM_ROUTE_IDLE;
682 self->curr_route_ptr->internal_infos.src_obsvr_initialized = 0U;
684 if (self->report_fptr != NULL)
686 self->report_fptr(self->curr_route_ptr, UCS_RM_ROUTE_INFOS_DESTROYED, self->base_ptr->ucs_user_ptr);
691 /*! \brief Builds the given endpoint.
692 * \param self Instance pointer
693 * \param endpoint_ptr Reference to the endpoint to be looked for
694 * \return Possible return values are
695 * - \c UCS_RET_ERR_API_LOCKED the API is locked. Endpoint is currently being processed.
696 * - \c UCS_RET_SUCCESS the build process was set successfully
697 * - \c UCS_RET_ERR_PARAM NULL pointer detected in the parameter list
698 * - \c UCS_RET_ERR_ALREADY_SET the endpoint has already been set
700 static Ucs_Return_t Rtm_BuildEndPoint(CRouteManagement * self, Ucs_Rm_EndPoint_t * endpoint_ptr)
702 Ucs_Return_t result = UCS_RET_ERR_PARAM;
704 if ((self != NULL) && (endpoint_ptr != NULL))
706 result = Epm_SetBuildProcess(self->epm_ptr, endpoint_ptr);
707 if (result == UCS_RET_SUCCESS)
709 Epm_AddObserver (endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? &self->curr_route_ptr->internal_infos.source_ep_observer: &self->curr_route_ptr->internal_infos.sink_ep_observer);
710 self->curr_route_ptr->internal_infos.route_state = UCS_RM_ROUTE_CONSTRUCTION;
711 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Start Building Endpoint {%X} of type %s for route id %X", 3U, endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source":"Sink", self->curr_route_ptr->route_id));
713 else if (result == UCS_RET_ERR_ALREADY_SET)
715 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Endpoint {%X} of type %s for route id %X has already been built", 3U, endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source":"Sink", self->curr_route_ptr->route_id));
722 /*! \brief Destroys the given endpoint.
723 * \param self Instance pointer
724 * \param endpoint_ptr Reference to the endpoint to be looked for
725 * \return Possible return values are
726 * - \c UCS_RET_ERR_API_LOCKED the API is locked. Endpoint is currently being processed.
727 * - \c UCS_RET_SUCCESS the build process was set successfully
728 * - \c UCS_RET_ERR_PARAM NULL pointer detected in the parameter list
729 * - \c UCS_RET_ERR_ALREADY_SET the endpoint has already been set
730 * - \c UCS_RET_ERR_NOT_AVAILABLE the endpoint is no more available.
731 * - \c UCS_RET_ERR_INVALID_SHADOW the endpoint cannot be destroyed since it's still in use by another routes.
733 static Ucs_Return_t Rtm_DeactivateRouteEndPoint(CRouteManagement * self, Ucs_Rm_EndPoint_t * endpoint_ptr)
735 Ucs_Return_t result = UCS_RET_ERR_PARAM;
737 if ((self != NULL) && (endpoint_ptr != NULL) && (endpoint_ptr->node_obj_ptr != NULL) &&
738 (endpoint_ptr->node_obj_ptr->signature_ptr != NULL))
740 if ((endpoint_ptr->node_obj_ptr->internal_infos.available == 1U) ||
741 (endpoint_ptr->node_obj_ptr->signature_ptr->node_address == UCS_ADDR_LOCAL_DEV))
743 result = Epm_SetDestroyProcess(self->epm_ptr, endpoint_ptr);
744 if (result == UCS_RET_SUCCESS)
746 self->curr_route_ptr->internal_infos.route_state = UCS_RM_ROUTE_DESTRUCTION;
747 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Start Destroying Endpoint {%X} of type %s for route id %X", 3U, endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source":"Sink", self->curr_route_ptr->route_id));
749 else if (result == UCS_RET_ERR_ALREADY_SET)
751 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Endpoint {%X} of type %s for route id %X has already been destroyed", 3U, endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source":"Sink", self->curr_route_ptr->route_id));
753 else if (result == UCS_RET_ERR_INVALID_SHADOW)
755 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Endpoint {%X} of type %s for route id %X cannot be destroyed since it's still used", 3U, endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source":"Sink", self->curr_route_ptr->route_id));
757 else if (result == UCS_RET_ERR_NOT_AVAILABLE)
759 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Endpoint {%X} of type %s for route id %X is no more available", 3U, endpoint_ptr, (endpoint_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source" : "Sink", self->curr_route_ptr->route_id));
765 Epm_ResetState(self->epm_ptr, endpoint_ptr);
772 /*! \brief Classifies and sets the corresponding route error and then informs user about the new state.
773 * \param self Instance pointer
774 * \param route_ptr Reference to the route to be looked for
776 static void Rtm_HandleRoutingError(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr)
778 Ucs_Rm_Route_t * tmp_route = route_ptr;
779 Ucs_Rm_RouteInfos_t result_route = UCS_RM_ROUTE_INFOS_DESTROYED;
780 Ucs_Rm_RouteResult_t res_rt = tmp_route->internal_infos.last_route_result;
782 tmp_route->internal_infos.route_state = UCS_RM_ROUTE_IDLE;
783 tmp_route->internal_infos.last_route_result = UCS_RM_ROUTE_NOERROR;
785 if (res_rt != UCS_RM_ROUTE_CRITICAL)
787 if (tmp_route->source_endpoint_ptr->internal_infos.endpoint_state == UCS_RM_EP_IDLE)
789 if (Rtm_CheckEpResultSeverity(self, tmp_route, tmp_route->source_endpoint_ptr))
791 Epm_ResetState(self->epm_ptr, tmp_route->source_endpoint_ptr);
792 tmp_route->internal_infos.route_state = UCS_RM_ROUTE_SUSPENDED;
793 result_route = UCS_RM_ROUTE_INFOS_SUSPENDED;
794 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Route id {%X} is suspended", 1U, tmp_route->route_id));
797 else if (tmp_route->sink_endpoint_ptr->internal_infos.endpoint_state == UCS_RM_EP_IDLE)
799 if (Rtm_CheckEpResultSeverity(self, tmp_route, tmp_route->sink_endpoint_ptr))
801 Epm_ResetState(self->epm_ptr, tmp_route->sink_endpoint_ptr);
802 tmp_route->internal_infos.route_state = UCS_RM_ROUTE_SUSPENDED;
803 result_route = UCS_RM_ROUTE_INFOS_SUSPENDED;
804 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Route id {%X} is suspended", 1U, tmp_route->route_id));
809 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Route id {%X} is destroyed", 1U, tmp_route->route_id));
814 Epm_ResetState(self->epm_ptr, tmp_route->source_endpoint_ptr);
815 Epm_ResetState(self->epm_ptr, tmp_route->sink_endpoint_ptr);
816 tmp_route->internal_infos.route_state = UCS_RM_ROUTE_SUSPENDED;
817 result_route = UCS_RM_ROUTE_INFOS_SUSPENDED;
818 TR_INFO((self->base_ptr->ucs_user_ptr, "[RTM]", "Route id {%X} is suspended", 1U, tmp_route->route_id));
821 if (self->report_fptr != NULL)
823 self->report_fptr(tmp_route, result_route, self->base_ptr->ucs_user_ptr);
827 /*! \brief Checks whether the endpoint's result is critical or not and stores the result into the target route.
828 * \param self Instance pointer
829 * \param tgt_route_ptr Reference to the route that contains the endpoint to be looked for
830 * \param endpoint_ptr Reference to the endpoint to be looked for
831 * \return \c true if the endpoint result is critical, otherwise \c false.
833 static bool Rtm_CheckEpResultSeverity(CRouteManagement * self, Ucs_Rm_Route_t * tgt_route_ptr, Ucs_Rm_EndPoint_t * endpoint_ptr)
835 bool result_check = false;
836 Ucs_Rm_RouteResult_t result = UCS_RM_ROUTE_NOERROR;
837 /*! \brief Maximum number of retries allowed in error situation */
838 uint8_t RTM_MAX_NUM_RETRIES_IN_ERR = 0xFFU;
840 if ((endpoint_ptr != NULL) && (tgt_route_ptr != NULL))
842 switch (endpoint_ptr->internal_infos.xrm_result.code)
844 case UCS_XRM_RES_ERR_BUILD:
845 case UCS_XRM_RES_ERR_DESTROY:
846 case UCS_XRM_RES_ERR_SYNC:
847 switch (endpoint_ptr->internal_infos.xrm_result.details.result_type)
849 case UCS_XRM_RESULT_TYPE_TX:
850 if ((UCS_MSG_STAT_ERROR_CFG_NO_RCVR == endpoint_ptr->internal_infos.xrm_result.details.tx_result) ||
851 (UCS_MSG_STAT_ERROR_FATAL_OA == endpoint_ptr->internal_infos.xrm_result.details.tx_result) ||
852 (endpoint_ptr->internal_infos.num_retries == RTM_MAX_NUM_RETRIES_IN_ERR))
854 result = UCS_RM_ROUTE_CRITICAL;
855 TR_ERROR((self->base_ptr->ucs_user_ptr, "[RTM]", "Critical error occurred on route id {%X} due to the transmission error code {Ucs_MsgTxStatus_t:0x%02X} observed in XRM.", 2U,
856 tgt_route_ptr->route_id, endpoint_ptr->internal_infos.xrm_result.details.tx_result));
858 else if ((UCS_MSG_STAT_ERROR_UNKNOWN == endpoint_ptr->internal_infos.xrm_result.details.tx_result) ||
859 (UCS_MSG_STAT_ERROR_FATAL_WT == endpoint_ptr->internal_infos.xrm_result.details.tx_result) ||
860 (UCS_MSG_STAT_ERROR_TIMEOUT == endpoint_ptr->internal_infos.xrm_result.details.tx_result) ||
861 (UCS_MSG_STAT_ERROR_BF == endpoint_ptr->internal_infos.xrm_result.details.tx_result) ||
862 (UCS_MSG_STAT_ERROR_CRC == endpoint_ptr->internal_infos.xrm_result.details.tx_result) ||
863 (UCS_MSG_STAT_ERROR_NA_TRANS == endpoint_ptr->internal_infos.xrm_result.details.tx_result) ||
864 (UCS_MSG_STAT_ERROR_ACK == endpoint_ptr->internal_infos.xrm_result.details.tx_result) ||
865 (UCS_MSG_STAT_ERROR_ID == endpoint_ptr->internal_infos.xrm_result.details.tx_result))
867 endpoint_ptr->internal_infos.num_retries++;
868 result = UCS_RM_ROUTE_UNCRITICAL;
872 case UCS_XRM_RESULT_TYPE_TGT:
873 if ((UCS_RES_ERR_CONFIGURATION == endpoint_ptr->internal_infos.xrm_result.details.inic_result.code) ||
874 (UCS_RES_ERR_MOST_STANDARD == endpoint_ptr->internal_infos.xrm_result.details.inic_result.code) ||
875 (UCS_RES_ERR_SYSTEM == endpoint_ptr->internal_infos.xrm_result.details.inic_result.code) ||
876 (endpoint_ptr->internal_infos.num_retries == RTM_MAX_NUM_RETRIES_IN_ERR))
878 result = UCS_RM_ROUTE_CRITICAL;
879 TR_ERROR((self->base_ptr->ucs_user_ptr, "[RTM]", "Critical error occurred on route id {%X} due to the INIC result code {Ucs_Result_t:0x%02X} observed in XRM.", 2U,
880 tgt_route_ptr->route_id, endpoint_ptr->internal_infos.xrm_result.details.inic_result.code));
882 else if ((UCS_RES_ERR_BUSY == endpoint_ptr->internal_infos.xrm_result.details.inic_result.code) ||
883 (UCS_RES_ERR_TIMEOUT == endpoint_ptr->internal_infos.xrm_result.details.inic_result.code) ||
884 (UCS_RES_ERR_PROCESSING == endpoint_ptr->internal_infos.xrm_result.details.inic_result.code))
886 endpoint_ptr->internal_infos.num_retries++;
887 result = UCS_RM_ROUTE_UNCRITICAL;
891 case UCS_XRM_RESULT_TYPE_INT:
892 if ((endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_NOT_AVAILABLE) ||
893 (endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_NOT_SUPPORTED) ||
894 (endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_PARAM) ||
895 (endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_NOT_INITIALIZED) ||
896 (endpoint_ptr->internal_infos.num_retries == RTM_MAX_NUM_RETRIES_IN_ERR))
898 result = UCS_RM_ROUTE_CRITICAL;
899 TR_ERROR((self->base_ptr->ucs_user_ptr, "[RTM]", "Critical error occurred on route id {%X} due to the internal error code {Ucs_Return_t:0x%02X} observed in XRM.", 2U,
900 tgt_route_ptr->route_id, endpoint_ptr->internal_infos.xrm_result.details.int_result));
902 else if ((endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_BUFFER_OVERFLOW) ||
903 (endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_API_LOCKED) ||
904 (endpoint_ptr->internal_infos.xrm_result.details.int_result == UCS_RET_ERR_INVALID_SHADOW))
906 endpoint_ptr->internal_infos.num_retries++;
907 result = UCS_RM_ROUTE_UNCRITICAL;
916 case UCS_XRM_RES_ERR_CONFIG:
917 result = UCS_RM_ROUTE_CRITICAL;
920 case UCS_XRM_RES_SUCCESS_BUILD:
921 case UCS_XRM_RES_SUCCESS_DESTROY:
922 endpoint_ptr->internal_infos.num_retries = 0U;
929 /* Sets route result */
930 tgt_route_ptr->internal_infos.last_route_result = result;
931 if (result == UCS_RM_ROUTE_CRITICAL)
942 /*! \brief Sets curr_route_ptr to the next route.
943 * \param self Instance pointer
944 * \return \c true if the endpoint result is critical, otherwise \c false.
946 static bool Rtm_SetNextRouteIndex(CRouteManagement * self)
950 if ((self->routes_list_size > 0U) && (self->nw_available))
953 self->curr_route_index++;
954 self->curr_route_index = self->curr_route_index%self->routes_list_size;
955 tmp_idx = self->curr_route_index;
959 if (((self->routes_list_ptr[self->curr_route_index].internal_infos.route_state == UCS_RM_ROUTE_SUSPENDED) &&
960 (self->routes_list_ptr[self->curr_route_index].active == true)) ||
961 ((self->routes_list_ptr[self->curr_route_index].active == true) &&
962 (self->routes_list_ptr[self->curr_route_index].internal_infos.route_state == UCS_RM_ROUTE_BUILT)) ||
963 ((self->routes_list_ptr[self->curr_route_index].active == false) &&
964 (self->routes_list_ptr[self->curr_route_index].internal_infos.route_state == UCS_RM_ROUTE_IDLE)) ||
965 ((Rtm_AreRouteNodesAvailable(self, &self->routes_list_ptr[self->curr_route_index]) == false) &&
966 (self->routes_list_ptr[self->curr_route_index].internal_infos.route_state == UCS_RM_ROUTE_IDLE)))
968 self->curr_route_index++;
969 self->curr_route_index = self->curr_route_index%self->routes_list_size;
976 while ((tmp_idx != self->curr_route_index) &&
983 /*! \brief Starts the timer for handling routes.
984 * \param self Instance pointer
986 static void Rtm_StartTmr4HandlingRoutes(CRouteManagement * self)
988 if((T_IsTimerInUse(&self->route_check) == false) &&
989 (!self->ucs_is_stopping))
991 Tm_SetTimer(self->tm_ptr,
993 &Rtm_ExecRoutesHandling,
995 RTM_JOB_CHECK_INTERVAL,
996 RTM_JOB_CHECK_INTERVAL);
1000 /*! \brief Gets the next route.
1001 * \param self Instance pointer
1002 * \return the next route to be handled
1004 static Ucs_Rm_Route_t * Rtm_GetNextRoute(CRouteManagement * self)
1006 self->routes_list_ptr[self->curr_route_index].internal_infos.rtm_inst = (Rtm_Inst_t *)(void *)self;
1007 return &self->routes_list_ptr[self->curr_route_index];
1010 /*! \brief Checks if the API is locked.
1011 * \param self Instance pointer
1012 * \return \c true if the API is not locked and the UCS are initialized, otherwise \c false.
1014 static bool Rtm_IsApiFree(CRouteManagement *self)
1016 return (self->lock_api == false);
1019 /*! \brief Locks/Unlocks the RTM API.
1020 * \param self Instance pointer
1021 * \param status Locking status. \c true = Lock, \c false = Unlock
1023 static void Rtm_ApiLocking(CRouteManagement *self, bool status)
1025 self->lock_api = status;
1028 /*! \brief Checks whether the nodes (source and sink) of the current route is available.
1029 * \param self Instance pointer
1030 * \param route_ptr Reference to the Route to be looked for
1031 * \return \c true if the source endpoint's node is available, otherwise \c false.
1033 static bool Rtm_AreRouteNodesAvailable(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr)
1035 bool result = false;
1038 if ((route_ptr->source_endpoint_ptr != NULL) && (route_ptr->sink_endpoint_ptr != NULL))
1040 if ((route_ptr->source_endpoint_ptr->node_obj_ptr != NULL) &&
1041 (route_ptr->source_endpoint_ptr->node_obj_ptr->signature_ptr != NULL) &&
1042 (route_ptr->sink_endpoint_ptr->node_obj_ptr != NULL) &&
1043 (route_ptr->sink_endpoint_ptr->node_obj_ptr->signature_ptr != NULL))
1045 if (((1U == route_ptr->source_endpoint_ptr->node_obj_ptr->internal_infos.available) ||
1046 (route_ptr->source_endpoint_ptr->node_obj_ptr->signature_ptr->node_address == UCS_ADDR_LOCAL_DEV) ||
1047 (Net_IsOwnAddress(self->net_ptr, route_ptr->source_endpoint_ptr->node_obj_ptr->signature_ptr->node_address) == NET_IS_OWN_ADDR_NODE)) &&
1048 ((Net_IsOwnAddress(self->net_ptr, route_ptr->sink_endpoint_ptr->node_obj_ptr->signature_ptr->node_address) == NET_IS_OWN_ADDR_NODE) ||
1049 (route_ptr->sink_endpoint_ptr->node_obj_ptr->signature_ptr->node_address == UCS_ADDR_LOCAL_DEV) ||
1050 (1U == route_ptr->sink_endpoint_ptr->node_obj_ptr->internal_infos.available)))
1058 TR_ERROR((self->base_ptr->ucs_user_ptr, "[RTM]", "ERROR PARAMETER on route id {%X}: At least one endpoint is NULL.", 1U, route_ptr->route_id));
1064 /*! \brief Checks if we encountered a deadlock situation with the given route and if we do, resolves It by resetting the endpoint concerned.
1066 * Since we can encounter the situation that the construction of an endpoint fails and the routing management is not aware of that (synchronous vs asynchronous response)
1067 * and still consider that the route is processing. In such a case the RTM process will never get a response and will wait in vain for It.
1068 * Therefore, the role of this function is to release the blocking situation in resetting the concerned endpoint.
1069 * \param self Instance pointer
1070 * \param tgt_route_ptr Reference to the route that contains the endpoint to be looked for
1071 * \param endpoint_ptr Reference to the endpoint to be looked for
1072 * \return \c true if the endpoint's result is critical, otherwise \c false
1074 static bool Rtm_UnlockPossibleBlockings(CRouteManagement * self, Ucs_Rm_Route_t * tgt_route_ptr, Ucs_Rm_EndPoint_t * endpoint_ptr)
1076 bool result_critical = Rtm_CheckEpResultSeverity(self, tgt_route_ptr, endpoint_ptr);
1077 if (!result_critical)
1079 if (UCS_RM_ROUTE_UNCRITICAL == self->curr_route_ptr->internal_infos.last_route_result)
1081 Epm_ResetState(self->epm_ptr, endpoint_ptr);
1084 return result_critical;
1087 /*! \brief Stops routes handling.
1088 * \param self Instance pointer
1090 static void Rtm_StopRoutesHandling(CRouteManagement * self)
1092 Tm_ClearTimer(self->tm_ptr, &self->route_check);
1095 /*! \brief Releases all routes endpoints and notifies that the process is terminated for all "active" routes, which are not built or suspended.
1096 * \param self Instance pointer
1098 static void Rtm_HandleProcessTermination(CRouteManagement * self)
1100 if ((self->routes_list_ptr != NULL) && (self->routes_list_size > 0U))
1104 for (; k < self->routes_list_size; k++)
1106 Epm_ClearIntInfos(self->epm_ptr, self->routes_list_ptr[k].source_endpoint_ptr);
1107 Epm_ClearIntInfos(self->epm_ptr, self->routes_list_ptr[k].sink_endpoint_ptr);
1109 if ((self->routes_list_ptr[k].active == 1U) &&
1110 (self->routes_list_ptr[k].internal_infos.notify_termination == 0U) &&
1111 (self->routes_list_ptr[k].internal_infos.route_state != UCS_RM_ROUTE_BUILT) &&
1112 (self->routes_list_ptr[k].internal_infos.route_state != UCS_RM_ROUTE_SUSPENDED))
1114 if ((self->routes_list_ptr[k].internal_infos.route_state == UCS_RM_ROUTE_CONSTRUCTION) ||
1115 (self->routes_list_ptr[k].internal_infos.route_state == UCS_RM_ROUTE_DESTRUCTION))
1117 self->routes_list_ptr[k].internal_infos.route_state = UCS_RM_ROUTE_IDLE;
1120 self->routes_list_ptr[k].internal_infos.notify_termination = 0x01U;
1121 if (self->report_fptr != NULL)
1123 self->report_fptr(&self->routes_list_ptr[k], UCS_RM_ROUTE_INFOS_PROCESS_STOP, self->base_ptr->ucs_user_ptr);
1130 /*! \brief Resets the availability flag of all nodes involved in routing process.
1131 * \param self Instance pointer
1133 static void Rtm_ResetNodesAvailable(CRouteManagement * self)
1137 if ((self->routes_list_ptr != NULL) && (self->routes_list_size > 0U))
1139 for (; k < self->routes_list_size; k++)
1141 if ((self->routes_list_ptr[k].sink_endpoint_ptr != NULL) &&
1142 (self->routes_list_ptr[k].sink_endpoint_ptr->node_obj_ptr != NULL))
1144 self->routes_list_ptr[k].sink_endpoint_ptr->node_obj_ptr->internal_infos.available = 0U;
1147 if ((self->routes_list_ptr[k].source_endpoint_ptr != NULL) &&
1148 (self->routes_list_ptr[k].source_endpoint_ptr->node_obj_ptr != NULL))
1150 self->routes_list_ptr[k].source_endpoint_ptr->node_obj_ptr->internal_infos.available = 0U;
1156 /*! \brief Releases all suspended routes of the given node.
1157 * \details This function should only be called when the provided node, on which the suspended routes are,
1158 * is set to "not available".
1159 * \param self Instance pointer
1160 * \param node_ptr Reference to the node to be looked for
1162 static void Rtm_ReleaseSuspendedRoutes(CRouteManagement * self, Ucs_Rm_Node_t *node_ptr)
1165 bool is_ep_result_critical = false;
1167 if ((self != NULL) && (self->routes_list_ptr != NULL) &&
1168 (self->routes_list_size > 0U) && (node_ptr != NULL))
1170 for (; k < self->routes_list_size; k++)
1172 is_ep_result_critical = Rtm_CheckEpResultSeverity(self, &self->routes_list_ptr[k], self->routes_list_ptr[k].sink_endpoint_ptr);
1173 if ((self->routes_list_ptr[k].internal_infos.route_state == UCS_RM_ROUTE_SUSPENDED) ||
1174 ((self->routes_list_ptr[k].internal_infos.route_state == UCS_RM_ROUTE_DETERIORATED) &&
1175 (self->routes_list_ptr[k].internal_infos.last_route_result == UCS_RM_ROUTE_CRITICAL)) ||
1176 ((self->routes_list_ptr[k].internal_infos.route_state == UCS_RM_ROUTE_CONSTRUCTION) &&
1177 (is_ep_result_critical)))
1179 if (((self->routes_list_ptr[k].source_endpoint_ptr != NULL) &&
1180 (self->routes_list_ptr[k].source_endpoint_ptr->node_obj_ptr == node_ptr)) ||
1181 ((self->routes_list_ptr[k].sink_endpoint_ptr != NULL) &&
1182 (self->routes_list_ptr[k].sink_endpoint_ptr->node_obj_ptr == node_ptr)))
1184 Rtm_ForcesRouteToIdle(self, &self->routes_list_ptr[k]);
1191 /*! \brief Sets the given routes to the "Idle" state and resets its internal variables.
1192 * \details This function is risky and should only be used in Rtm_ReleaseSuspendedRoutes(). Because it forces a route's state to "Idle"
1193 * without any external events.
1194 * \param self Instance pointer
1195 * \param route_ptr Reference to the route to be set
1197 static void Rtm_ForcesRouteToIdle(CRouteManagement * self, Ucs_Rm_Route_t * route_ptr)
1199 if ((self != NULL) && (route_ptr != NULL))
1201 route_ptr->internal_infos.route_state = UCS_RM_ROUTE_IDLE;
1202 route_ptr->internal_infos.last_route_result = UCS_RM_ROUTE_NOERROR;
1203 if (route_ptr->source_endpoint_ptr != NULL)
1205 if (Rtm_CheckEpResultSeverity(self, route_ptr, route_ptr->source_endpoint_ptr))
1207 Epm_ResetState(self->epm_ptr, route_ptr->source_endpoint_ptr);
1210 if (route_ptr->sink_endpoint_ptr != NULL)
1212 if (Rtm_CheckEpResultSeverity(self, route_ptr, route_ptr->sink_endpoint_ptr))
1214 Epm_ResetState(self->epm_ptr, route_ptr->sink_endpoint_ptr);
1220 /*------------------------------------------------------------------------------------------------*/
1221 /* Callback Functions */
1222 /*------------------------------------------------------------------------------------------------*/
1223 /*! \brief Called if UCS initialization has been succeeded.
1224 * \param self Instance pointer
1225 * \param event_ptr Reference to reported event
1227 static void Rtm_UcsInitSucceededCb(void *self, void *event_ptr)
1229 CRouteManagement *self_ = (CRouteManagement *)self;
1230 MISC_UNUSED(event_ptr);
1232 /* Remove ucsinit_observer */
1233 Eh_DelObsrvInternalEvent(&self_->base_ptr->eh, &self_->ucsinit_observer);
1235 /* Add network status observer */
1236 Mobs_Ctor(&self_->nwstatus_observer, self, RTM_MASK_NETWORK_AVAILABILITY, &Rtm_MnsNwStatusInfosCb);
1237 Net_AddObserverNetworkStatus(self_->net_ptr, &self_->nwstatus_observer);
1240 /*! \brief Handle internal errors and un-initialize RTM service.
1241 * \param self Instance pointer
1242 * \param error_code_ptr Reference to internal error code
1244 static void Rtm_UninitializeService(void *self, void *error_code_ptr)
1246 CRouteManagement *self_ = (CRouteManagement *)self;
1247 MISC_UNUSED(error_code_ptr);
1249 self_->ucs_is_stopping = true;
1251 /* Notify destruction of current routes */
1252 Rtm_HandleProcessTermination(self_);
1254 /* Remove RTM service from schedulers list */
1255 (void)Scd_RemoveService(&self_->base_ptr->scd, &self_->rtm_srv);
1256 /* Remove error/event observers */
1257 Eh_DelObsrvInternalEvent(&self_->base_ptr->eh, &self_->ucstermination_observer);
1258 Net_DelObserverNetworkStatus(self_->net_ptr, &self_->nwstatus_observer);
1261 Rtm_ApiLocking(self_, false);
1264 /*! \brief Event Callback function for the network status.
1265 * \param self Instance pointer
1266 * \param event_ptr Reference to the events
1268 static void Rtm_MnsNwStatusInfosCb(void *self, void *event_ptr)
1270 CRouteManagement *self_ = (CRouteManagement *)self;
1271 Net_NetworkStatusParam_t *result_ptr_ = (Net_NetworkStatusParam_t *)event_ptr;
1273 if (RTM_MASK_NETWORK_AVAILABILITY == (RTM_MASK_NETWORK_AVAILABILITY & result_ptr_->change_mask))
1275 if (UCS_NW_NOT_AVAILABLE == result_ptr_->availability)
1277 self_->nw_available = false;
1278 /* Resets Nodes availability flag */
1279 Rtm_ResetNodesAvailable(self_);
1280 /* Reports Network Status "NotAvailabe" */
1281 Epm_ReportShutDown(self_->epm_ptr);
1285 self_->nw_available = true;
1286 /* Check whether there are routes to be processed */
1287 Rtm_StartRoutingTimer (self_);
1292 /*! \brief Event Callback function that signals that an endpoint is unavailable.
1293 * \param self Instance pointer
1294 * \param result_ptr Reference to the results
1296 static void Rtm_EndPointDeterioredCb(void *self, void *result_ptr)
1298 Ucs_Rm_Route_t * route_ptr = (Ucs_Rm_Route_t *)self;
1299 Ucs_Rm_EndPoint_t * ep_ptr = (Ucs_Rm_EndPoint_t *)result_ptr;
1301 if ((route_ptr->source_endpoint_ptr == ep_ptr) ||
1302 (route_ptr->sink_endpoint_ptr == ep_ptr))
1304 if (route_ptr->internal_infos.route_state == UCS_RM_ROUTE_BUILT)
1306 TR_INFO((((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst)->base_ptr->ucs_user_ptr, "[RTM]", "Route id %X is deteriorated", 1U, route_ptr->route_id));
1307 if (ep_ptr->endpoint_type == UCS_RM_EP_SOURCE)
1309 route_ptr->internal_infos.src_obsvr_initialized = 0U;
1312 Rtm_HandleRoutingError((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst, route_ptr);
1314 if ((((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst)->nw_available) &&
1315 (!((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst)->ucs_is_stopping))
1317 Rtm_StartTmr4HandlingRoutes((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst);
1319 else if (((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst)->ucs_is_stopping)
1321 Rtm_HandleProcessTermination((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst);
1327 TR_ERROR((((CRouteManagement *)(void *)route_ptr->internal_infos.rtm_inst)->base_ptr->ucs_user_ptr, "[RTM]", "Wrong endpoint {%X} of type %s on route id {%X}.", 3U,
1328 ep_ptr, (ep_ptr->endpoint_type == UCS_RM_EP_SOURCE) ? "Source":"Sink", route_ptr->route_id));
1332 /*! \brief Processes the handling of all routes. This method is the callback function of the routing timer
1334 * \param self Instance pointer
1336 static void Rtm_ExecRoutesHandling(void* self)
1338 CRouteManagement *self_ = (CRouteManagement *)self;
1339 if (!self_->ucs_is_stopping)
1341 bool index_set = Rtm_SetNextRouteIndex(self_);
1344 Srv_SetEvent(&self_->rtm_srv, RTM_EVENT_HANDLE_NEXTROUTE);
1348 Srv_SetEvent(&self_->rtm_srv, RTM_EVENT_PROCESS_PAUSE);
1349 TR_INFO((self_->base_ptr->ucs_user_ptr, "[RTM]", "Handling process of routes is paused", 0U));
1354 Rtm_HandleProcessTermination(self_);
1363 /*------------------------------------------------------------------------------------------------*/
1365 /*------------------------------------------------------------------------------------------------*/