]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
7fc02572 RW |
2 | /* |
3 | * Copyright (C) 2016 by Open Source Routing. | |
7fc02572 RW |
4 | */ |
5 | ||
d3e2c74a | 6 | #include <zebra.h> |
ddfeb486 DL |
7 | |
8 | #ifdef OPEN_BSD | |
9 | ||
d3e2c74a RW |
10 | #include <netmpls/mpls.h> |
11 | #include "zebra/rt.h" | |
12 | #include "zebra/zebra_mpls.h" | |
13 | #include "zebra/debug.h" | |
364fed6b | 14 | #include "zebra/zebra_errors.h" |
b3f2b590 | 15 | #include "zebra/zebra_router.h" |
d3e2c74a RW |
16 | |
17 | #include "privs.h" | |
18 | #include "prefix.h" | |
19 | #include "interface.h" | |
20 | #include "log.h" | |
174482ef | 21 | #include "lib_errors.h" |
d3e2c74a RW |
22 | |
23 | extern struct zebra_privs_t zserv_privs; | |
24 | ||
25 | struct { | |
d7c0a89a | 26 | uint32_t rtseq; |
d62a17ae | 27 | int fd; |
d42127da | 28 | int ioctl_fd; |
d3e2c74a RW |
29 | } kr_state; |
30 | ||
d62a17ae | 31 | static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label, |
f2595bd5 | 32 | const struct zebra_nhlfe *nhlfe) |
d3e2c74a | 33 | { |
d62a17ae | 34 | struct iovec iov[5]; |
35 | struct rt_msghdr hdr; | |
36 | struct sockaddr_mpls sa_label_in, sa_label_out; | |
37 | struct sockaddr_in nexthop; | |
38 | int iovcnt = 0; | |
39 | int ret; | |
40 | ||
41 | if (IS_ZEBRA_DEBUG_KERNEL) | |
42 | zlog_debug("%s: 0x%x, label=%u", __func__, action, in_label); | |
43 | ||
44 | /* initialize header */ | |
45 | memset(&hdr, 0, sizeof(hdr)); | |
46 | hdr.rtm_version = RTM_VERSION; | |
47 | ||
48 | hdr.rtm_type = action; | |
49 | hdr.rtm_flags = RTF_UP; | |
50 | hdr.rtm_fmask = RTF_MPLS; | |
51 | hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ | |
52 | hdr.rtm_msglen = sizeof(hdr); | |
53 | hdr.rtm_hdrlen = sizeof(struct rt_msghdr); | |
54 | hdr.rtm_priority = 0; | |
55 | /* adjust iovec */ | |
56 | iov[iovcnt].iov_base = &hdr; | |
57 | iov[iovcnt++].iov_len = sizeof(hdr); | |
58 | ||
59 | /* in label */ | |
60 | memset(&sa_label_in, 0, sizeof(sa_label_in)); | |
61 | sa_label_in.smpls_len = sizeof(sa_label_in); | |
62 | sa_label_in.smpls_family = AF_MPLS; | |
63 | sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); | |
64 | /* adjust header */ | |
65 | hdr.rtm_flags |= RTF_MPLS | RTF_MPATH; | |
66 | hdr.rtm_addrs |= RTA_DST; | |
67 | hdr.rtm_msglen += sizeof(sa_label_in); | |
68 | /* adjust iovec */ | |
69 | iov[iovcnt].iov_base = &sa_label_in; | |
70 | iov[iovcnt++].iov_len = sizeof(sa_label_in); | |
71 | ||
72 | /* nexthop */ | |
73 | memset(&nexthop, 0, sizeof(nexthop)); | |
74 | nexthop.sin_len = sizeof(nexthop); | |
75 | nexthop.sin_family = AF_INET; | |
76 | nexthop.sin_addr = nhlfe->nexthop->gate.ipv4; | |
77 | /* adjust header */ | |
78 | hdr.rtm_flags |= RTF_GATEWAY; | |
79 | hdr.rtm_addrs |= RTA_GATEWAY; | |
80 | hdr.rtm_msglen += sizeof(nexthop); | |
81 | /* adjust iovec */ | |
82 | iov[iovcnt].iov_base = &nexthop; | |
83 | iov[iovcnt++].iov_len = sizeof(nexthop); | |
84 | ||
85 | /* If action is RTM_DELETE we have to get rid of MPLS infos */ | |
86 | if (action != RTM_DELETE) { | |
87 | memset(&sa_label_out, 0, sizeof(sa_label_out)); | |
88 | sa_label_out.smpls_len = sizeof(sa_label_out); | |
89 | sa_label_out.smpls_family = AF_MPLS; | |
90 | sa_label_out.smpls_label = | |
91 | htonl(nhlfe->nexthop->nh_label->label[0] | |
92 | << MPLS_LABEL_OFFSET); | |
93 | /* adjust header */ | |
94 | hdr.rtm_addrs |= RTA_SRC; | |
95 | hdr.rtm_flags |= RTF_MPLS; | |
96 | hdr.rtm_msglen += sizeof(sa_label_out); | |
97 | /* adjust iovec */ | |
98 | iov[iovcnt].iov_base = &sa_label_out; | |
99 | iov[iovcnt++].iov_len = sizeof(sa_label_out); | |
100 | ||
101 | if (nhlfe->nexthop->nh_label->label[0] == MPLS_LABEL_IMPLNULL) | |
102 | hdr.rtm_mpls = MPLS_OP_POP; | |
103 | else | |
104 | hdr.rtm_mpls = MPLS_OP_SWAP; | |
105 | } | |
106 | ||
0cf6db21 | 107 | frr_with_privs(&zserv_privs) { |
01b9e3fd DL |
108 | ret = writev(kr_state.fd, iov, iovcnt); |
109 | } | |
d62a17ae | 110 | |
111 | if (ret == -1) | |
450971aa | 112 | flog_err_sys(EC_LIB_SOCKET, "%s: %s", __func__, |
09c866e3 | 113 | safe_strerror(errno)); |
d62a17ae | 114 | |
115 | return ret; | |
e07486ce RW |
116 | } |
117 | ||
118 | #if !defined(ROUNDUP) | |
d62a17ae | 119 | #define ROUNDUP(a) \ |
120 | (((a) & (sizeof(long) - 1)) ? (1 + ((a) | (sizeof(long) - 1))) : (a)) | |
e07486ce RW |
121 | #endif |
122 | ||
d62a17ae | 123 | static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label, |
f2595bd5 | 124 | const struct zebra_nhlfe *nhlfe) |
e07486ce | 125 | { |
d62a17ae | 126 | struct iovec iov[5]; |
127 | struct rt_msghdr hdr; | |
128 | struct sockaddr_mpls sa_label_in, sa_label_out; | |
129 | struct pad { | |
130 | struct sockaddr_in6 addr; | |
131 | char pad[sizeof(long)]; /* thank you IPv6 */ | |
132 | } nexthop; | |
133 | int iovcnt = 0; | |
134 | int ret; | |
135 | ||
136 | if (IS_ZEBRA_DEBUG_KERNEL) | |
137 | zlog_debug("%s: 0x%x, label=%u", __func__, action, in_label); | |
138 | ||
139 | /* initialize header */ | |
140 | memset(&hdr, 0, sizeof(hdr)); | |
141 | hdr.rtm_version = RTM_VERSION; | |
142 | ||
143 | hdr.rtm_type = action; | |
144 | hdr.rtm_flags = RTF_UP; | |
145 | hdr.rtm_fmask = RTF_MPLS; | |
146 | hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ | |
147 | hdr.rtm_msglen = sizeof(hdr); | |
148 | hdr.rtm_hdrlen = sizeof(struct rt_msghdr); | |
149 | hdr.rtm_priority = 0; | |
150 | /* adjust iovec */ | |
151 | iov[iovcnt].iov_base = &hdr; | |
152 | iov[iovcnt++].iov_len = sizeof(hdr); | |
153 | ||
154 | /* in label */ | |
155 | memset(&sa_label_in, 0, sizeof(sa_label_in)); | |
156 | sa_label_in.smpls_len = sizeof(sa_label_in); | |
157 | sa_label_in.smpls_family = AF_MPLS; | |
158 | sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); | |
159 | /* adjust header */ | |
160 | hdr.rtm_flags |= RTF_MPLS | RTF_MPATH; | |
161 | hdr.rtm_addrs |= RTA_DST; | |
162 | hdr.rtm_msglen += sizeof(sa_label_in); | |
163 | /* adjust iovec */ | |
164 | iov[iovcnt].iov_base = &sa_label_in; | |
165 | iov[iovcnt++].iov_len = sizeof(sa_label_in); | |
166 | ||
167 | /* nexthop */ | |
168 | memset(&nexthop, 0, sizeof(nexthop)); | |
169 | nexthop.addr.sin6_len = sizeof(struct sockaddr_in6); | |
170 | nexthop.addr.sin6_family = AF_INET6; | |
171 | nexthop.addr.sin6_addr = nhlfe->nexthop->gate.ipv6; | |
172 | if (IN6_IS_ADDR_LINKLOCAL(&nexthop.addr.sin6_addr)) { | |
173 | uint16_t tmp16; | |
174 | struct sockaddr_in6 *sin6 = &nexthop.addr; | |
175 | ||
176 | nexthop.addr.sin6_scope_id = nhlfe->nexthop->ifindex; | |
177 | ||
178 | memcpy(&tmp16, &sin6->sin6_addr.s6_addr[2], sizeof(tmp16)); | |
179 | tmp16 = htons(sin6->sin6_scope_id); | |
180 | memcpy(&sin6->sin6_addr.s6_addr[2], &tmp16, sizeof(tmp16)); | |
181 | sin6->sin6_scope_id = 0; | |
182 | } | |
183 | ||
184 | /* adjust header */ | |
185 | hdr.rtm_flags |= RTF_GATEWAY; | |
186 | hdr.rtm_addrs |= RTA_GATEWAY; | |
187 | hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6)); | |
188 | /* adjust iovec */ | |
189 | iov[iovcnt].iov_base = &nexthop; | |
190 | iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6)); | |
191 | ||
192 | /* If action is RTM_DELETE we have to get rid of MPLS infos */ | |
193 | if (action != RTM_DELETE) { | |
194 | memset(&sa_label_out, 0, sizeof(sa_label_out)); | |
195 | sa_label_out.smpls_len = sizeof(sa_label_out); | |
196 | sa_label_out.smpls_family = AF_MPLS; | |
197 | sa_label_out.smpls_label = | |
198 | htonl(nhlfe->nexthop->nh_label->label[0] | |
199 | << MPLS_LABEL_OFFSET); | |
200 | /* adjust header */ | |
201 | hdr.rtm_addrs |= RTA_SRC; | |
202 | hdr.rtm_flags |= RTF_MPLS; | |
203 | hdr.rtm_msglen += sizeof(sa_label_out); | |
204 | /* adjust iovec */ | |
205 | iov[iovcnt].iov_base = &sa_label_out; | |
206 | iov[iovcnt++].iov_len = sizeof(sa_label_out); | |
207 | ||
208 | if (nhlfe->nexthop->nh_label->label[0] == MPLS_LABEL_IMPLNULL) | |
209 | hdr.rtm_mpls = MPLS_OP_POP; | |
210 | else | |
211 | hdr.rtm_mpls = MPLS_OP_SWAP; | |
212 | } | |
213 | ||
0cf6db21 | 214 | frr_with_privs(&zserv_privs) { |
01b9e3fd DL |
215 | ret = writev(kr_state.fd, iov, iovcnt); |
216 | } | |
d62a17ae | 217 | |
218 | if (ret == -1) | |
450971aa | 219 | flog_err_sys(EC_LIB_SOCKET, "%s: %s", __func__, |
09c866e3 | 220 | safe_strerror(errno)); |
d62a17ae | 221 | |
222 | return ret; | |
d3e2c74a RW |
223 | } |
224 | ||
fc608372 | 225 | static int kernel_lsp_cmd(struct zebra_dplane_ctx *ctx) |
d3e2c74a | 226 | { |
ee70f629 | 227 | const struct nhlfe_list_head *head; |
f2595bd5 | 228 | const struct zebra_nhlfe *nhlfe; |
ee70f629 | 229 | const struct nexthop *nexthop = NULL; |
d62a17ae | 230 | unsigned int nexthop_num = 0; |
fc608372 MS |
231 | int action; |
232 | ||
233 | switch (dplane_ctx_get_op(ctx)) { | |
234 | case DPLANE_OP_LSP_DELETE: | |
235 | action = RTM_DELETE; | |
236 | break; | |
237 | case DPLANE_OP_LSP_INSTALL: | |
238 | action = RTM_ADD; | |
239 | break; | |
240 | case DPLANE_OP_LSP_UPDATE: | |
241 | action = RTM_CHANGE; | |
242 | break; | |
a98701f0 DS |
243 | case DPLANE_OP_NONE: |
244 | case DPLANE_OP_ROUTE_INSTALL: | |
245 | case DPLANE_OP_ROUTE_UPDATE: | |
246 | case DPLANE_OP_ROUTE_DELETE: | |
247 | case DPLANE_OP_ROUTE_NOTIFY: | |
248 | case DPLANE_OP_NH_INSTALL: | |
249 | case DPLANE_OP_NH_UPDATE: | |
250 | case DPLANE_OP_NH_DELETE: | |
251 | case DPLANE_OP_LSP_NOTIFY: | |
252 | case DPLANE_OP_PW_INSTALL: | |
253 | case DPLANE_OP_PW_UNINSTALL: | |
254 | case DPLANE_OP_SYS_ROUTE_ADD: | |
255 | case DPLANE_OP_SYS_ROUTE_DELETE: | |
256 | case DPLANE_OP_ADDR_INSTALL: | |
257 | case DPLANE_OP_ADDR_UNINSTALL: | |
258 | case DPLANE_OP_MAC_INSTALL: | |
259 | case DPLANE_OP_MAC_DELETE: | |
260 | case DPLANE_OP_NEIGH_INSTALL: | |
261 | case DPLANE_OP_NEIGH_UPDATE: | |
262 | case DPLANE_OP_NEIGH_DELETE: | |
263 | case DPLANE_OP_VTEP_ADD: | |
264 | case DPLANE_OP_VTEP_DELETE: | |
265 | case DPLANE_OP_RULE_ADD: | |
266 | case DPLANE_OP_RULE_DELETE: | |
267 | case DPLANE_OP_RULE_UPDATE: | |
268 | case DPLANE_OP_NEIGH_DISCOVER: | |
269 | case DPLANE_OP_BR_PORT_UPDATE: | |
270 | case DPLANE_OP_IPTABLE_ADD: | |
271 | case DPLANE_OP_IPTABLE_DELETE: | |
272 | case DPLANE_OP_IPSET_ADD: | |
273 | case DPLANE_OP_IPSET_DELETE: | |
274 | case DPLANE_OP_IPSET_ENTRY_ADD: | |
275 | case DPLANE_OP_IPSET_ENTRY_DELETE: | |
276 | case DPLANE_OP_NEIGH_IP_INSTALL: | |
277 | case DPLANE_OP_NEIGH_IP_DELETE: | |
278 | case DPLANE_OP_NEIGH_TABLE_UPDATE: | |
279 | case DPLANE_OP_GRE_SET: | |
280 | case DPLANE_OP_INTF_ADDR_ADD: | |
281 | case DPLANE_OP_INTF_ADDR_DEL: | |
282 | case DPLANE_OP_INTF_NETCONFIG: | |
283 | case DPLANE_OP_INTF_INSTALL: | |
284 | case DPLANE_OP_INTF_UPDATE: | |
285 | case DPLANE_OP_INTF_DELETE: | |
286 | case DPLANE_OP_TC_QDISC_INSTALL: | |
287 | case DPLANE_OP_TC_QDISC_UNINSTALL: | |
288 | case DPLANE_OP_TC_CLASS_ADD: | |
289 | case DPLANE_OP_TC_CLASS_DELETE: | |
290 | case DPLANE_OP_TC_CLASS_UPDATE: | |
291 | case DPLANE_OP_TC_FILTER_ADD: | |
292 | case DPLANE_OP_TC_FILTER_DELETE: | |
293 | case DPLANE_OP_TC_FILTER_UPDATE: | |
fc608372 MS |
294 | return -1; |
295 | } | |
d62a17ae | 296 | |
ee70f629 MS |
297 | head = dplane_ctx_get_nhlfe_list(ctx); |
298 | frr_each(nhlfe_list_const, head, nhlfe) { | |
d62a17ae | 299 | nexthop = nhlfe->nexthop; |
300 | if (!nexthop) | |
301 | continue; | |
302 | ||
b3f2b590 | 303 | if (nexthop_num >= zrouter.multipath_num) |
d62a17ae | 304 | break; |
305 | ||
306 | if (((action == RTM_ADD || action == RTM_CHANGE) | |
307 | && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) | |
308 | && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))) | |
309 | || (action == RTM_DELETE | |
310 | && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) | |
311 | && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)))) { | |
5e8c8947 | 312 | if (nhlfe->nexthop->nh_label->num_labels > 1) { |
e914ccbe | 313 | flog_warn(EC_ZEBRA_MAX_LABELS_PUSH, |
3efd0893 | 314 | "%s: can't push %u labels at once (maximum is 1)", |
9df414fe QY |
315 | __func__, |
316 | nhlfe->nexthop->nh_label->num_labels); | |
5e8c8947 RW |
317 | continue; |
318 | } | |
319 | ||
d62a17ae | 320 | nexthop_num++; |
321 | ||
322 | switch (NHLFE_FAMILY(nhlfe)) { | |
323 | case AF_INET: | |
fc608372 MS |
324 | kernel_send_rtmsg_v4( |
325 | action, | |
326 | dplane_ctx_get_in_label(ctx), | |
327 | nhlfe); | |
d62a17ae | 328 | break; |
329 | case AF_INET6: | |
fc608372 MS |
330 | kernel_send_rtmsg_v6( |
331 | action, | |
332 | dplane_ctx_get_in_label(ctx), | |
333 | nhlfe); | |
d62a17ae | 334 | break; |
335 | default: | |
336 | break; | |
337 | } | |
d62a17ae | 338 | } |
339 | } | |
340 | ||
95f7965d | 341 | return 0; |
d3e2c74a RW |
342 | } |
343 | ||
fc608372 | 344 | enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx) |
d3e2c74a | 345 | { |
d62a17ae | 346 | int ret; |
c4c8dec0 | 347 | |
fc608372 | 348 | ret = kernel_lsp_cmd(ctx); |
c4c8dec0 | 349 | |
fc608372 MS |
350 | return (ret == 0 ? |
351 | ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE); | |
16c628de MS |
352 | } |
353 | ||
97d8d05a | 354 | static enum zebra_dplane_result kmpw_install(struct zebra_dplane_ctx *ctx) |
d42127da RW |
355 | { |
356 | struct ifreq ifr; | |
357 | struct ifmpwreq imr; | |
358 | struct sockaddr_storage ss; | |
359 | struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss; | |
360 | struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss; | |
97d8d05a | 361 | const union g_addr *gaddr; |
d42127da RW |
362 | |
363 | memset(&imr, 0, sizeof(imr)); | |
97d8d05a | 364 | switch (dplane_ctx_get_pw_type(ctx)) { |
d42127da RW |
365 | case PW_TYPE_ETHERNET: |
366 | imr.imr_type = IMR_TYPE_ETHERNET; | |
367 | break; | |
368 | case PW_TYPE_ETHERNET_TAGGED: | |
369 | imr.imr_type = IMR_TYPE_ETHERNET_TAGGED; | |
370 | break; | |
371 | default: | |
9df414fe | 372 | zlog_debug("%s: unhandled pseudowire type (%#X)", __func__, |
97d8d05a MS |
373 | dplane_ctx_get_pw_type(ctx)); |
374 | return ZEBRA_DPLANE_REQUEST_FAILURE; | |
d42127da RW |
375 | } |
376 | ||
97d8d05a | 377 | if (dplane_ctx_get_pw_flags(ctx) & F_PSEUDOWIRE_CWORD) |
d42127da RW |
378 | imr.imr_flags |= IMR_FLAG_CONTROLWORD; |
379 | ||
380 | /* pseudowire nexthop */ | |
381 | memset(&ss, 0, sizeof(ss)); | |
16d69787 | 382 | gaddr = dplane_ctx_get_pw_dest(ctx); |
97d8d05a | 383 | switch (dplane_ctx_get_pw_af(ctx)) { |
d42127da RW |
384 | case AF_INET: |
385 | sa_in->sin_family = AF_INET; | |
386 | sa_in->sin_len = sizeof(struct sockaddr_in); | |
97d8d05a | 387 | sa_in->sin_addr = gaddr->ipv4; |
d42127da RW |
388 | break; |
389 | case AF_INET6: | |
390 | sa_in6->sin6_family = AF_INET6; | |
391 | sa_in6->sin6_len = sizeof(struct sockaddr_in6); | |
97d8d05a | 392 | sa_in6->sin6_addr = gaddr->ipv6; |
d42127da RW |
393 | break; |
394 | default: | |
9df414fe | 395 | zlog_debug("%s: unhandled pseudowire address-family (%u)", |
97d8d05a MS |
396 | __func__, dplane_ctx_get_pw_af(ctx)); |
397 | return ZEBRA_DPLANE_REQUEST_FAILURE; | |
d42127da RW |
398 | } |
399 | memcpy(&imr.imr_nexthop, (struct sockaddr *)&ss, | |
400 | sizeof(imr.imr_nexthop)); | |
401 | ||
402 | /* pseudowire local/remote labels */ | |
97d8d05a MS |
403 | imr.imr_lshim.shim_label = dplane_ctx_get_pw_local_label(ctx); |
404 | imr.imr_rshim.shim_label = dplane_ctx_get_pw_remote_label(ctx); | |
d42127da RW |
405 | |
406 | /* ioctl */ | |
407 | memset(&ifr, 0, sizeof(ifr)); | |
7c7ef4a8 | 408 | strlcpy(ifr.ifr_name, dplane_ctx_get_ifname(ctx), |
97d8d05a | 409 | sizeof(ifr.ifr_name)); |
d42127da RW |
410 | ifr.ifr_data = (caddr_t)&imr; |
411 | if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) { | |
450971aa | 412 | flog_err_sys(EC_LIB_SYSTEM_CALL, "ioctl SIOCSETMPWCFG: %s", |
09c866e3 | 413 | safe_strerror(errno)); |
97d8d05a | 414 | return ZEBRA_DPLANE_REQUEST_FAILURE; |
d42127da RW |
415 | } |
416 | ||
97d8d05a | 417 | return ZEBRA_DPLANE_REQUEST_SUCCESS; |
d42127da RW |
418 | } |
419 | ||
97d8d05a | 420 | static enum zebra_dplane_result kmpw_uninstall(struct zebra_dplane_ctx *ctx) |
d42127da RW |
421 | { |
422 | struct ifreq ifr; | |
423 | struct ifmpwreq imr; | |
424 | ||
425 | memset(&ifr, 0, sizeof(ifr)); | |
426 | memset(&imr, 0, sizeof(imr)); | |
7c7ef4a8 | 427 | strlcpy(ifr.ifr_name, dplane_ctx_get_ifname(ctx), |
97d8d05a | 428 | sizeof(ifr.ifr_name)); |
d42127da RW |
429 | ifr.ifr_data = (caddr_t)&imr; |
430 | if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) { | |
450971aa | 431 | flog_err_sys(EC_LIB_SYSTEM_CALL, "ioctl SIOCSETMPWCFG: %s", |
09c866e3 | 432 | safe_strerror(errno)); |
97d8d05a | 433 | return ZEBRA_DPLANE_REQUEST_FAILURE; |
d42127da RW |
434 | } |
435 | ||
97d8d05a MS |
436 | return ZEBRA_DPLANE_REQUEST_SUCCESS; |
437 | } | |
438 | ||
439 | /* | |
440 | * Pseudowire update api for openbsd. | |
441 | */ | |
442 | enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx) | |
443 | { | |
444 | enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; | |
445 | ||
446 | switch (dplane_ctx_get_op(ctx)) { | |
447 | case DPLANE_OP_PW_INSTALL: | |
448 | result = kmpw_install(ctx); | |
449 | break; | |
450 | case DPLANE_OP_PW_UNINSTALL: | |
451 | result = kmpw_uninstall(ctx); | |
452 | break; | |
a98701f0 DS |
453 | case DPLANE_OP_NONE: |
454 | case DPLANE_OP_ROUTE_INSTALL: | |
455 | case DPLANE_OP_ROUTE_UPDATE: | |
456 | case DPLANE_OP_ROUTE_DELETE: | |
457 | case DPLANE_OP_ROUTE_NOTIFY: | |
458 | case DPLANE_OP_NH_INSTALL: | |
459 | case DPLANE_OP_NH_UPDATE: | |
460 | case DPLANE_OP_NH_DELETE: | |
461 | case DPLANE_OP_LSP_INSTALL: | |
462 | case DPLANE_OP_LSP_UPDATE: | |
463 | case DPLANE_OP_LSP_DELETE: | |
464 | case DPLANE_OP_LSP_NOTIFY: | |
465 | case DPLANE_OP_SYS_ROUTE_ADD: | |
466 | case DPLANE_OP_SYS_ROUTE_DELETE: | |
467 | case DPLANE_OP_ADDR_INSTALL: | |
468 | case DPLANE_OP_ADDR_UNINSTALL: | |
469 | case DPLANE_OP_MAC_INSTALL: | |
470 | case DPLANE_OP_MAC_DELETE: | |
471 | case DPLANE_OP_NEIGH_INSTALL: | |
472 | case DPLANE_OP_NEIGH_UPDATE: | |
473 | case DPLANE_OP_NEIGH_DELETE: | |
474 | case DPLANE_OP_VTEP_ADD: | |
475 | case DPLANE_OP_VTEP_DELETE: | |
476 | case DPLANE_OP_RULE_ADD: | |
477 | case DPLANE_OP_RULE_DELETE: | |
478 | case DPLANE_OP_RULE_UPDATE: | |
479 | case DPLANE_OP_NEIGH_DISCOVER: | |
480 | case DPLANE_OP_BR_PORT_UPDATE: | |
481 | case DPLANE_OP_IPTABLE_ADD: | |
482 | case DPLANE_OP_IPTABLE_DELETE: | |
483 | case DPLANE_OP_IPSET_ADD: | |
484 | case DPLANE_OP_IPSET_DELETE: | |
485 | case DPLANE_OP_IPSET_ENTRY_ADD: | |
486 | case DPLANE_OP_IPSET_ENTRY_DELETE: | |
487 | case DPLANE_OP_NEIGH_IP_INSTALL: | |
488 | case DPLANE_OP_NEIGH_IP_DELETE: | |
489 | case DPLANE_OP_NEIGH_TABLE_UPDATE: | |
490 | case DPLANE_OP_GRE_SET: | |
491 | case DPLANE_OP_INTF_ADDR_ADD: | |
492 | case DPLANE_OP_INTF_ADDR_DEL: | |
493 | case DPLANE_OP_INTF_NETCONFIG: | |
494 | case DPLANE_OP_INTF_INSTALL: | |
495 | case DPLANE_OP_INTF_UPDATE: | |
496 | case DPLANE_OP_INTF_DELETE: | |
497 | case DPLANE_OP_TC_QDISC_INSTALL: | |
498 | case DPLANE_OP_TC_QDISC_UNINSTALL: | |
499 | case DPLANE_OP_TC_CLASS_ADD: | |
500 | case DPLANE_OP_TC_CLASS_DELETE: | |
501 | case DPLANE_OP_TC_CLASS_UPDATE: | |
502 | case DPLANE_OP_TC_FILTER_ADD: | |
503 | case DPLANE_OP_TC_FILTER_DELETE: | |
504 | case DPLANE_OP_TC_FILTER_UPDATE: | |
97d8d05a | 505 | break; |
5b94ec50 | 506 | } |
97d8d05a MS |
507 | |
508 | return result; | |
d42127da RW |
509 | } |
510 | ||
d3e2c74a | 511 | #define MAX_RTSOCK_BUF 128 * 1024 |
d62a17ae | 512 | int mpls_kernel_init(void) |
d3e2c74a | 513 | { |
d62a17ae | 514 | int rcvbuf, default_rcvbuf; |
515 | socklen_t optlen; | |
516 | ||
517 | if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) { | |
450971aa | 518 | flog_err_sys(EC_LIB_SOCKET, "%s: socket", __func__); |
d62a17ae | 519 | return -1; |
520 | } | |
521 | ||
d42127da RW |
522 | if ((kr_state.ioctl_fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0)) |
523 | == -1) { | |
450971aa | 524 | flog_err_sys(EC_LIB_SOCKET, "%s: ioctl socket", __func__); |
d42127da RW |
525 | return -1; |
526 | } | |
527 | ||
d62a17ae | 528 | /* grow receive buffer, don't wanna miss messages */ |
529 | optlen = sizeof(default_rcvbuf); | |
530 | if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, &default_rcvbuf, | |
531 | &optlen) | |
532 | == -1) | |
450971aa | 533 | flog_err_sys(EC_LIB_SOCKET, |
9df414fe | 534 | "kr_init getsockopt SOL_SOCKET SO_RCVBUF"); |
d62a17ae | 535 | else |
536 | for (rcvbuf = MAX_RTSOCK_BUF; | |
537 | rcvbuf > default_rcvbuf | |
538 | && setsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, | |
539 | sizeof(rcvbuf)) | |
540 | == -1 | |
541 | && errno == ENOBUFS; | |
542 | rcvbuf /= 2) | |
543 | ; /* nothing */ | |
544 | ||
545 | kr_state.rtseq = 1; | |
546 | ||
6fb35808 MS |
547 | /* Strict pseudowire reachability checking required for obsd */ |
548 | mpls_pw_reach_strict = true; | |
549 | ||
d62a17ae | 550 | return 0; |
d3e2c74a | 551 | } |
ddfeb486 DL |
552 | |
553 | #endif /* OPEN_BSD */ |