]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
fe18ee2d DS |
2 | /* zebra NS Routines |
3 | * Copyright (C) 2016 Cumulus Networks, Inc. | |
4 | * Donald Sharp | |
b95c1883 | 5 | * Copyright (C) 2017/2018 6WIND |
fe18ee2d DS |
6 | */ |
7 | #include "zebra.h" | |
8 | ||
13460c44 | 9 | #include "lib/ns.h" |
fe18ee2d DS |
10 | #include "lib/vrf.h" |
11 | #include "lib/prefix.h" | |
12 | #include "lib/memory.h" | |
13 | ||
fe18ee2d | 14 | #include "zebra_ns.h" |
7c551956 | 15 | #include "zebra_vrf.h" |
05f7f5db | 16 | #include "rt.h" |
b7cfce93 | 17 | #include "zebra_vxlan.h" |
3347430b | 18 | #include "debug.h" |
e27dec3c | 19 | #include "zebra_netns_notify.h" |
ec31f30d | 20 | #include "zebra_netns_id.h" |
43fe6a2a | 21 | #include "zebra_pbr.h" |
c317d3f2 | 22 | #include "zebra_tc.h" |
47a08aa9 | 23 | #include "rib.h" |
8288a24f | 24 | #include "table_manager.h" |
257b245c | 25 | #include "zebra_errors.h" |
ec31f30d PG |
26 | |
27 | extern struct zebra_privs_t zserv_privs; | |
4a1ab8e4 | 28 | |
224ccf29 | 29 | DEFINE_MTYPE_STATIC(ZEBRA, ZEBRA_NS, "Zebra Name Space"); |
fe18ee2d | 30 | |
337960dd | 31 | static struct zebra_ns *dzns; |
fe18ee2d | 32 | |
62b8bb7a | 33 | static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete); |
736d41ad | 34 | |
d62a17ae | 35 | struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id) |
fe18ee2d | 36 | { |
ff705b15 PG |
37 | if (ns_id == NS_DEFAULT) |
38 | return dzns; | |
39 | struct zebra_ns *info = (struct zebra_ns *)ns_info_lookup(ns_id); | |
40 | ||
41 | return (info == NULL) ? dzns : info; | |
fe18ee2d DS |
42 | } |
43 | ||
3347430b PG |
44 | static struct zebra_ns *zebra_ns_alloc(void) |
45 | { | |
46 | return XCALLOC(MTYPE_ZEBRA_NS, sizeof(struct zebra_ns)); | |
47 | } | |
48 | ||
49 | static int zebra_ns_new(struct ns *ns) | |
50 | { | |
51 | struct zebra_ns *zns; | |
52 | ||
257b245c SW |
53 | if (!ns) |
54 | return -1; | |
55 | ||
3347430b PG |
56 | if (IS_ZEBRA_DEBUG_EVENT) |
57 | zlog_info("ZNS %s with id %u (created)", ns->name, ns->ns_id); | |
58 | ||
59 | zns = zebra_ns_alloc(); | |
60 | ns->info = zns; | |
61 | zns->ns = ns; | |
3f6e9ae5 | 62 | zns->ns_id = ns->ns_id; |
ff705b15 PG |
63 | |
64 | /* Do any needed per-NS data structure allocation. */ | |
65 | zns->if_table = route_table_init(); | |
ff705b15 | 66 | |
3347430b PG |
67 | return 0; |
68 | } | |
69 | ||
70 | static int zebra_ns_delete(struct ns *ns) | |
71 | { | |
996c9314 | 72 | struct zebra_ns *zns = (struct zebra_ns *)ns->info; |
3347430b PG |
73 | |
74 | if (IS_ZEBRA_DEBUG_EVENT) | |
75 | zlog_info("ZNS %s with id %u (deleted)", ns->name, ns->ns_id); | |
76 | if (!zns) | |
77 | return 0; | |
fd4c24f5 | 78 | XFREE(MTYPE_ZEBRA_NS, ns->info); |
3347430b PG |
79 | return 0; |
80 | } | |
81 | ||
82 | static int zebra_ns_enabled(struct ns *ns) | |
83 | { | |
84 | struct zebra_ns *zns = ns->info; | |
85 | ||
86 | if (IS_ZEBRA_DEBUG_EVENT) | |
87 | zlog_info("ZNS %s with id %u (enabled)", ns->name, ns->ns_id); | |
88 | if (!zns) | |
89 | return 0; | |
90 | return zebra_ns_enable(ns->ns_id, (void **)&zns); | |
91 | } | |
92 | ||
ff705b15 | 93 | int zebra_ns_disabled(struct ns *ns) |
3347430b PG |
94 | { |
95 | struct zebra_ns *zns = ns->info; | |
96 | ||
97 | if (IS_ZEBRA_DEBUG_EVENT) | |
98 | zlog_info("ZNS %s with id %u (disabled)", ns->name, ns->ns_id); | |
99 | if (!zns) | |
100 | return 0; | |
62b8bb7a | 101 | return zebra_ns_disable_internal(zns, true); |
3347430b PG |
102 | } |
103 | ||
84915b0a | 104 | /* Do global enable actions - open sockets, read kernel config etc. */ |
d62a17ae | 105 | int zebra_ns_enable(ns_id_t ns_id, void **info) |
fe18ee2d | 106 | { |
d62a17ae | 107 | struct zebra_ns *zns = (struct zebra_ns *)(*info); |
fe18ee2d | 108 | |
ff705b15 PG |
109 | zns->ns_id = ns_id; |
110 | ||
d62a17ae | 111 | kernel_init(zns); |
d166308b | 112 | zebra_dplane_ns_enable(zns, true); |
d62a17ae | 113 | interface_list(zns); |
114 | route_read(zns); | |
a26daa77 SW |
115 | |
116 | vlan_read(zns); | |
ab35be75 | 117 | kernel_read_pbr_rules(zns); |
c317d3f2 | 118 | kernel_read_tc_qdisc(zns); |
fe18ee2d | 119 | |
d62a17ae | 120 | return 0; |
fe18ee2d DS |
121 | } |
122 | ||
62b8bb7a MS |
123 | /* Common handler for ns disable - this can be called during ns config, |
124 | * or during zebra shutdown. | |
125 | */ | |
126 | static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete) | |
fe18ee2d | 127 | { |
c2270bf1 DS |
128 | if (zns->if_table) |
129 | route_table_finish(zns->if_table); | |
130 | zns->if_table = NULL; | |
fe18ee2d | 131 | |
d166308b MS |
132 | zebra_dplane_ns_enable(zns, false /*Disable*/); |
133 | ||
62b8bb7a | 134 | kernel_terminate(zns, complete); |
fe18ee2d | 135 | |
ff705b15 PG |
136 | zns->ns_id = NS_DEFAULT; |
137 | ||
d62a17ae | 138 | return 0; |
fe18ee2d DS |
139 | } |
140 | ||
62b8bb7a MS |
141 | /* During zebra shutdown, do partial cleanup while the async dataplane |
142 | * is still running. | |
143 | */ | |
2961d060 PG |
144 | int zebra_ns_early_shutdown(struct ns *ns, |
145 | void *param_in __attribute__((unused)), | |
146 | void **param_out __attribute__((unused))) | |
62b8bb7a MS |
147 | { |
148 | struct zebra_ns *zns = ns->info; | |
149 | ||
150 | if (zns == NULL) | |
151 | return 0; | |
152 | ||
2961d060 PG |
153 | zebra_ns_disable_internal(zns, false); |
154 | return NS_WALK_CONTINUE; | |
62b8bb7a MS |
155 | } |
156 | ||
157 | /* During zebra shutdown, do final cleanup | |
158 | * after all dataplane work is complete. | |
159 | */ | |
2961d060 PG |
160 | int zebra_ns_final_shutdown(struct ns *ns, |
161 | void *param_in __attribute__((unused)), | |
162 | void **param_out __attribute__((unused))) | |
62b8bb7a MS |
163 | { |
164 | struct zebra_ns *zns = ns->info; | |
165 | ||
166 | if (zns == NULL) | |
167 | return 0; | |
168 | ||
169 | kernel_terminate(zns, true); | |
170 | ||
2961d060 | 171 | return NS_WALK_CONTINUE; |
62b8bb7a | 172 | } |
5335613b | 173 | |
ac2cb9bf | 174 | int zebra_ns_init(void) |
fe18ee2d | 175 | { |
257b245c | 176 | struct ns *default_ns; |
ec31f30d | 177 | ns_id_t ns_id; |
03aff2d8 | 178 | ns_id_t ns_id_external; |
20f4b2b0 | 179 | struct ns *ns; |
ec31f30d | 180 | |
0cf6db21 | 181 | frr_with_privs(&zserv_privs) { |
01b9e3fd DL |
182 | ns_id = zebra_ns_id_get_default(); |
183 | } | |
03aff2d8 PG |
184 | ns_id_external = ns_map_nsid_with_external(ns_id, true); |
185 | ns_init_management(ns_id_external, ns_id); | |
20f4b2b0 PG |
186 | ns = ns_get_default(); |
187 | if (ns) | |
188 | ns->relative_default_ns = ns_id; | |
736d41ad | 189 | |
1eb92f06 | 190 | default_ns = ns_lookup(NS_DEFAULT); |
257b245c SW |
191 | if (!default_ns) { |
192 | flog_err(EC_ZEBRA_NS_NO_DEFAULT, | |
193 | "%s: failed to find default ns", __func__); | |
194 | exit(EXIT_FAILURE); /* This is non-recoverable */ | |
195 | } | |
196 | ||
84915b0a | 197 | /* Do any needed per-NS data structure allocation. */ |
257b245c SW |
198 | zebra_ns_new(default_ns); |
199 | dzns = default_ns->info; | |
84915b0a | 200 | |
201 | /* Register zebra VRF callbacks, create and activate default VRF. */ | |
d62a17ae | 202 | zebra_vrf_init(); |
fe18ee2d | 203 | |
84915b0a | 204 | /* Default NS is activated */ |
03aff2d8 | 205 | zebra_ns_enable(ns_id_external, (void **)&dzns); |
fe18ee2d | 206 | |
3347430b PG |
207 | if (vrf_is_backend_netns()) { |
208 | ns_add_hook(NS_NEW_HOOK, zebra_ns_new); | |
209 | ns_add_hook(NS_ENABLE_HOOK, zebra_ns_enabled); | |
210 | ns_add_hook(NS_DISABLE_HOOK, zebra_ns_disabled); | |
211 | ns_add_hook(NS_DELETE_HOOK, zebra_ns_delete); | |
e27dec3c PG |
212 | zebra_ns_notify_parse(); |
213 | zebra_ns_notify_init(); | |
3347430b | 214 | } |
7f0ea8a4 | 215 | |
d62a17ae | 216 | return 0; |
fe18ee2d | 217 | } |
b95c1883 PG |
218 | |
219 | int zebra_ns_config_write(struct vty *vty, struct ns *ns) | |
220 | { | |
221 | if (ns && ns->name != NULL) | |
222 | vty_out(vty, " netns %s\n", ns->name); | |
223 | return 0; | |
224 | } |