dpdk-cryptodev: fix coverity issues
[vpp.git] / src / plugins / linux-cp / lcp_mpls_sync.c
1 /*
2  * Copyright (c) 2023 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #define _GNU_SOURCE
17
18 #include <linux-cp/lcp_interface.h>
19
20 #include <vnet/plugin/plugin.h>
21 #include <vnet/mpls/mpls.h>
22 #include <vppinfra/linux/netns.h>
23
24 #include <fcntl.h>
25
26 vlib_log_class_t lcp_mpls_sync_logger;
27
28 #define LCP_MPLS_SYNC_DBG(...)                                                \
29   vlib_log_debug (lcp_mpls_sync_logger, __VA_ARGS__);
30
31 void
32 lcp_mpls_sync_pair_add_cb (lcp_itf_pair_t *lip)
33 {
34   u8 phy_is_enabled = mpls_sw_interface_is_enabled (lip->lip_phy_sw_if_index);
35   LCP_MPLS_SYNC_DBG ("pair_add_cb: mpls enabled %u, parent %U", phy_is_enabled,
36                      format_lcp_itf_pair, lip);
37   if (phy_is_enabled)
38     mpls_sw_interface_enable_disable (&mpls_main, lip->lip_host_sw_if_index,
39                                       1);
40 }
41
42 void
43 lcp_mpls_sync_state_cb (struct mpls_main_t *mm, uword opaque, u32 sw_if_index,
44                         u32 is_enable)
45 {
46   lcp_itf_pair_t *lip;
47   index_t lipi;
48   int curr_ns_fd = -1;
49   int vif_ns_fd = -1;
50   int ctl_fd = -1;
51   u8 *ctl_path = NULL;
52
53   LCP_MPLS_SYNC_DBG ("sync_state_cb: called for sw_if_index %u", sw_if_index);
54
55   // If device is LCP PHY, sync state to host tap.
56   lipi = lcp_itf_pair_find_by_phy (sw_if_index);
57   if (INDEX_INVALID != lipi)
58     {
59       lip = lcp_itf_pair_get (lipi);
60       LCP_MPLS_SYNC_DBG ("sync_state_cb: mpls enabled %u parent %U", is_enable,
61                          format_lcp_itf_pair, lip);
62       mpls_sw_interface_enable_disable (&mpls_main, lip->lip_host_sw_if_index,
63                                         is_enable);
64       return;
65     }
66
67   // If device is LCP host, toggle MPLS XC feature.
68   lipi = lcp_itf_pair_find_by_host (sw_if_index);
69   if (INDEX_INVALID == lipi)
70     return;
71   lip = lcp_itf_pair_get (lipi);
72
73   vnet_feature_enable_disable ("mpls-input", "linux-cp-xc-mpls", sw_if_index,
74                                is_enable, NULL, 0);
75
76   LCP_MPLS_SYNC_DBG ("sync_state_cb: mpls xc state %u parent %U", is_enable,
77                      format_lcp_itf_pair, lip);
78
79   // If syncing is enabled, sync Linux state as well.
80   // This can happen regardless of lcp_get_netlink_processing_active(),
81   // provided it does not generate Netlink messages.
82   if (!lcp_sync ())
83     return;
84
85   if (lip->lip_namespace)
86     {
87       curr_ns_fd = clib_netns_open (NULL /* self */);
88       vif_ns_fd = clib_netns_open (lip->lip_namespace);
89       if (vif_ns_fd != -1)
90         clib_setns (vif_ns_fd);
91     }
92
93   ctl_path = format (NULL, "/proc/sys/net/mpls/conf/%s/input%c",
94                      lip->lip_host_name, NULL);
95   if (NULL == ctl_path)
96     {
97       LCP_MPLS_SYNC_DBG ("sync_state_cb: failed to format sysctl");
98       goto SYNC_CLEANUP;
99     }
100
101   ctl_fd = open ((char *) ctl_path, O_WRONLY);
102   if (ctl_fd < 0)
103     {
104       LCP_MPLS_SYNC_DBG ("sync_state_cb: failed to open %s for writing",
105                          ctl_path);
106       goto SYNC_CLEANUP;
107     }
108
109   if (fdformat (ctl_fd, "%u", is_enable) < 1)
110     {
111       LCP_MPLS_SYNC_DBG ("sync_state_cb: failed to write to %s", ctl_path);
112       goto SYNC_CLEANUP;
113     }
114
115   LCP_MPLS_SYNC_DBG ("sync_state_cb: set mpls input for %s",
116                      lip->lip_host_name);
117
118 SYNC_CLEANUP:
119   if (ctl_fd > -1)
120     close (ctl_fd);
121
122   if (NULL != ctl_path)
123     vec_free (ctl_path);
124
125   if (vif_ns_fd != -1)
126     close (vif_ns_fd);
127
128   if (curr_ns_fd != -1)
129     {
130       clib_setns (curr_ns_fd);
131       close (curr_ns_fd);
132     }
133 }
134
135 static clib_error_t *
136 lcp_mpls_sync_init (vlib_main_t *vm)
137 {
138   lcp_itf_pair_vft_t mpls_sync_itf_pair_vft = {
139     .pair_add_fn = lcp_mpls_sync_pair_add_cb,
140   };
141   lcp_itf_pair_register_vft (&mpls_sync_itf_pair_vft);
142
143   mpls_interface_state_change_add_callback (lcp_mpls_sync_state_cb, 0);
144
145   lcp_mpls_sync_logger = vlib_log_register_class ("linux-cp", "mpls-sync");
146
147   return NULL;
148 }
149
150 VLIB_INIT_FUNCTION (lcp_mpls_sync_init) = {
151   .runs_after = VLIB_INITS ("lcp_interface_init", "mpls_init"),
152 };
153
154 /*
155  * fd.io coding-style-patch-verification: ON
156  *
157  * Local Variables:
158  * eval: (c-set-style "gnu")
159  * End:
160  */