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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <linux-cp/lcp_interface.h>
20 #include <vnet/plugin/plugin.h>
21 #include <vnet/mpls/mpls.h>
22 #include <vppinfra/linux/netns.h>
26 vlib_log_class_t lcp_mpls_sync_logger;
28 #define LCP_MPLS_SYNC_DBG(...) \
29 vlib_log_debug (lcp_mpls_sync_logger, __VA_ARGS__);
32 lcp_mpls_sync_pair_add_cb (lcp_itf_pair_t *lip)
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);
38 mpls_sw_interface_enable_disable (&mpls_main, lip->lip_host_sw_if_index,
43 lcp_mpls_sync_state_cb (struct mpls_main_t *mm, uword opaque, u32 sw_if_index,
53 LCP_MPLS_SYNC_DBG ("sync_state_cb: called for sw_if_index %u", sw_if_index);
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)
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,
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)
71 lip = lcp_itf_pair_get (lipi);
73 vnet_feature_enable_disable ("mpls-input", "linux-cp-xc-mpls", sw_if_index,
76 LCP_MPLS_SYNC_DBG ("sync_state_cb: mpls xc state %u parent %U", is_enable,
77 format_lcp_itf_pair, lip);
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.
85 if (lip->lip_namespace)
87 curr_ns_fd = clib_netns_open (NULL /* self */);
88 vif_ns_fd = clib_netns_open (lip->lip_namespace);
90 clib_setns (vif_ns_fd);
93 ctl_path = format (NULL, "/proc/sys/net/mpls/conf/%s/input%c",
94 lip->lip_host_name, NULL);
97 LCP_MPLS_SYNC_DBG ("sync_state_cb: failed to format sysctl");
101 ctl_fd = open ((char *) ctl_path, O_WRONLY);
104 LCP_MPLS_SYNC_DBG ("sync_state_cb: failed to open %s for writing",
109 if (fdformat (ctl_fd, "%u", is_enable) < 1)
111 LCP_MPLS_SYNC_DBG ("sync_state_cb: failed to write to %s", ctl_path);
115 LCP_MPLS_SYNC_DBG ("sync_state_cb: set mpls input for %s",
122 if (NULL != ctl_path)
128 if (curr_ns_fd != -1)
130 clib_setns (curr_ns_fd);
135 static clib_error_t *
136 lcp_mpls_sync_init (vlib_main_t *vm)
138 lcp_itf_pair_vft_t mpls_sync_itf_pair_vft = {
139 .pair_add_fn = lcp_mpls_sync_pair_add_cb,
141 lcp_itf_pair_register_vft (&mpls_sync_itf_pair_vft);
143 mpls_interface_state_change_add_callback (lcp_mpls_sync_state_cb, 0);
145 lcp_mpls_sync_logger = vlib_log_register_class ("linux-cp", "mpls-sync");
150 VLIB_INIT_FUNCTION (lcp_mpls_sync_init) = {
151 .runs_after = VLIB_INITS ("lcp_interface_init", "mpls_init"),
155 * fd.io coding-style-patch-verification: ON
158 * eval: (c-set-style "gnu")