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