Line data Source code
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 5 : lcp_mpls_sync_pair_add_cb (lcp_itf_pair_t *lip)
33 : {
34 5 : u8 phy_is_enabled = mpls_sw_interface_is_enabled (lip->lip_phy_sw_if_index);
35 5 : LCP_MPLS_SYNC_DBG ("pair_add_cb: mpls enabled %u, parent %U", phy_is_enabled,
36 : format_lcp_itf_pair, lip);
37 5 : if (phy_is_enabled)
38 0 : mpls_sw_interface_enable_disable (&mpls_main, lip->lip_host_sw_if_index,
39 : 1);
40 5 : }
41 :
42 : void
43 0 : 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 0 : int curr_ns_fd = -1;
49 0 : int vif_ns_fd = -1;
50 0 : int ctl_fd = -1;
51 0 : u8 *ctl_path = NULL;
52 :
53 0 : 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 0 : lipi = lcp_itf_pair_find_by_phy (sw_if_index);
57 0 : if (INDEX_INVALID != lipi)
58 : {
59 0 : lip = lcp_itf_pair_get (lipi);
60 0 : LCP_MPLS_SYNC_DBG ("sync_state_cb: mpls enabled %u parent %U", is_enable,
61 : format_lcp_itf_pair, lip);
62 0 : mpls_sw_interface_enable_disable (&mpls_main, lip->lip_host_sw_if_index,
63 : is_enable);
64 0 : return;
65 : }
66 :
67 : // If device is LCP host, toggle MPLS XC feature.
68 0 : lipi = lcp_itf_pair_find_by_host (sw_if_index);
69 0 : if (INDEX_INVALID == lipi)
70 0 : return;
71 0 : lip = lcp_itf_pair_get (lipi);
72 :
73 0 : vnet_feature_enable_disable ("mpls-input", "linux-cp-xc-mpls", sw_if_index,
74 : is_enable, NULL, 0);
75 :
76 0 : 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 0 : if (!lcp_sync ())
81 0 : return;
82 :
83 0 : if (lip->lip_namespace)
84 : {
85 0 : curr_ns_fd = clib_netns_open (NULL /* self */);
86 0 : vif_ns_fd = clib_netns_open (lip->lip_namespace);
87 0 : if (vif_ns_fd != -1)
88 0 : clib_setns (vif_ns_fd);
89 : }
90 :
91 0 : ctl_path = format (NULL, "/proc/sys/net/mpls/conf/%s/input%c",
92 : lip->lip_host_name, NULL);
93 0 : if (NULL == ctl_path)
94 : {
95 0 : LCP_MPLS_SYNC_DBG ("sync_state_cb: failed to format sysctl");
96 0 : goto SYNC_CLEANUP;
97 : }
98 :
99 0 : ctl_fd = open ((char *) ctl_path, O_WRONLY);
100 0 : if (ctl_fd < 0)
101 : {
102 0 : LCP_MPLS_SYNC_DBG ("sync_state_cb: failed to open %s for writing",
103 : ctl_path);
104 0 : goto SYNC_CLEANUP;
105 : }
106 :
107 0 : if (fdformat (ctl_fd, "%u", is_enable) < 1)
108 : {
109 0 : LCP_MPLS_SYNC_DBG ("sync_state_cb: failed to write to %s", ctl_path);
110 0 : goto SYNC_CLEANUP;
111 : }
112 :
113 0 : LCP_MPLS_SYNC_DBG ("sync_state_cb: set mpls input for %s",
114 : lip->lip_host_name);
115 :
116 0 : SYNC_CLEANUP:
117 0 : if (ctl_fd > -1)
118 0 : close (ctl_fd);
119 :
120 0 : if (NULL != ctl_path)
121 0 : vec_free (ctl_path);
122 :
123 0 : if (vif_ns_fd != -1)
124 0 : close (vif_ns_fd);
125 :
126 0 : if (curr_ns_fd != -1)
127 : {
128 0 : clib_setns (curr_ns_fd);
129 0 : close (curr_ns_fd);
130 : }
131 : }
132 :
133 : static clib_error_t *
134 2 : lcp_mpls_sync_init (vlib_main_t *vm)
135 : {
136 2 : lcp_itf_pair_vft_t mpls_sync_itf_pair_vft = {
137 : .pair_add_fn = lcp_mpls_sync_pair_add_cb,
138 : };
139 2 : lcp_itf_pair_register_vft (&mpls_sync_itf_pair_vft);
140 :
141 2 : mpls_interface_state_change_add_callback (lcp_mpls_sync_state_cb, 0);
142 :
143 2 : lcp_mpls_sync_logger = vlib_log_register_class ("linux-cp", "mpls-sync");
144 :
145 2 : return NULL;
146 : }
147 :
148 6 : VLIB_INIT_FUNCTION (lcp_mpls_sync_init) = {
149 : .runs_after = VLIB_INITS ("lcp_interface_init", "mpls_init"),
150 : };
151 :
152 : /*
153 : * fd.io coding-style-patch-verification: ON
154 : *
155 : * Local Variables:
156 : * eval: (c-set-style "gnu")
157 : * End:
158 : */
|