Print this page
OS-249
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/libdladm/common/libdllink.c
+++ new/usr/src/lib/libdladm/common/libdllink.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 + * Copyright (c) 2011, Joyent Inc. All rights reserved.
23 24 */
24 25
25 26 #include <sys/types.h>
26 27 #include <unistd.h>
27 28 #include <errno.h>
28 29 #include <fcntl.h>
29 30 #include <assert.h>
30 31 #include <ctype.h>
31 32 #include <strings.h>
32 33 #include <sys/stat.h>
33 34 #include <sys/dld.h>
34 35 #include <sys/vlan.h>
35 36 #include <zone.h>
36 37 #include <librcm.h>
37 38 #include <libdlpi.h>
38 39 #include <libdevinfo.h>
39 40 #include <libdlaggr.h>
40 41 #include <libdlvlan.h>
41 42 #include <libdlvnic.h>
42 43 #include <libdlib.h>
43 44 #include <libdllink.h>
44 45 #include <libdlmgmt.h>
45 46 #include <libdladm_impl.h>
46 47 #include <libinetutil.h>
47 48
48 49 /*
49 50 * Return the attributes of the specified datalink from the DLD driver.
50 51 */
51 52 static dladm_status_t
52 53 i_dladm_info(dladm_handle_t handle, const datalink_id_t linkid,
53 54 dladm_attr_t *dap)
54 55 {
55 56 dld_ioc_attr_t dia;
56 57
57 58 dia.dia_linkid = linkid;
58 59
59 60 if (ioctl(dladm_dld_fd(handle), DLDIOC_ATTR, &dia) < 0)
60 61 return (dladm_errno2status(errno));
61 62
62 63 dap->da_max_sdu = dia.dia_max_sdu;
63 64
64 65 return (DLADM_STATUS_OK);
65 66 }
66 67
67 68 static dladm_status_t
68 69 dladm_usagelog(dladm_handle_t handle, dladm_logtype_t type,
69 70 dld_ioc_usagelog_t *log_info)
70 71 {
71 72 if (type == DLADM_LOGTYPE_FLOW)
72 73 log_info->ul_type = MAC_LOGTYPE_FLOW;
73 74 else
74 75 log_info->ul_type = MAC_LOGTYPE_LINK;
75 76
76 77 if (ioctl(dladm_dld_fd(handle), DLDIOC_USAGELOG, log_info) < 0)
77 78 return (DLADM_STATUS_IOERR);
78 79
79 80 return (DLADM_STATUS_OK);
80 81 }
81 82
82 83 dladm_status_t
83 84 dladm_start_usagelog(dladm_handle_t handle, dladm_logtype_t type,
84 85 uint_t interval)
85 86 {
86 87 dld_ioc_usagelog_t log_info;
87 88
88 89 log_info.ul_onoff = B_TRUE;
89 90 log_info.ul_interval = interval;
90 91
91 92 return (dladm_usagelog(handle, type, &log_info));
92 93 }
93 94
94 95 dladm_status_t
95 96 dladm_stop_usagelog(dladm_handle_t handle, dladm_logtype_t type)
96 97 {
97 98 dld_ioc_usagelog_t log_info;
98 99
99 100 log_info.ul_onoff = B_FALSE;
100 101 log_info.ul_interval = 0;
101 102
102 103 return (dladm_usagelog(handle, type, &log_info));
103 104 }
104 105
105 106 struct i_dladm_walk_arg {
106 107 dladm_walkcb_t *fn;
107 108 void *arg;
108 109 };
109 110
110 111 static int
111 112 i_dladm_walk(dladm_handle_t handle, datalink_id_t linkid, void *arg)
112 113 {
113 114 struct i_dladm_walk_arg *walk_arg = arg;
114 115 char link[MAXLINKNAMELEN];
115 116
116 117 if (dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL, link,
117 118 sizeof (link)) == DLADM_STATUS_OK) {
118 119 return (walk_arg->fn(link, walk_arg->arg));
119 120 }
120 121
121 122 return (DLADM_WALK_CONTINUE);
122 123 }
123 124
124 125 /*
125 126 * Walk all datalinks.
126 127 */
127 128 dladm_status_t
128 129 dladm_walk(dladm_walkcb_t *fn, dladm_handle_t handle, void *arg,
129 130 datalink_class_t class, datalink_media_t dmedia, uint32_t flags)
130 131 {
131 132 struct i_dladm_walk_arg walk_arg;
132 133
133 134 walk_arg.fn = fn;
134 135 walk_arg.arg = arg;
135 136 return (dladm_walk_datalink_id(i_dladm_walk, handle, &walk_arg,
136 137 class, dmedia, flags));
137 138 }
138 139
139 140 #define MAXGRPPERLINK 64
140 141
141 142 int
142 143 dladm_walk_hwgrp(dladm_handle_t handle, datalink_id_t linkid, void *arg,
143 144 boolean_t (*fn)(void *, dladm_hwgrp_attr_t *))
144 145 {
145 146 int bufsize, ret;
146 147 int nhwgrp = MAXGRPPERLINK;
147 148 dld_ioc_hwgrpget_t *iomp = NULL;
148 149
149 150 bufsize = sizeof (dld_ioc_hwgrpget_t) +
150 151 nhwgrp * sizeof (dld_hwgrpinfo_t);
151 152
152 153 if ((iomp = (dld_ioc_hwgrpget_t *)calloc(1, bufsize)) == NULL)
153 154 return (-1);
154 155
155 156 iomp->dih_size = nhwgrp * sizeof (dld_hwgrpinfo_t);
156 157 iomp->dih_linkid = linkid;
157 158
158 159 ret = ioctl(dladm_dld_fd(handle), DLDIOC_GETHWGRP, iomp);
159 160 if (ret == 0) {
160 161 int i;
161 162 int j;
162 163 dld_hwgrpinfo_t *dhip;
163 164 dladm_hwgrp_attr_t attr;
164 165
165 166 dhip = (dld_hwgrpinfo_t *)(iomp + 1);
166 167 for (i = 0; i < iomp->dih_n_groups; i++) {
167 168 bzero(&attr, sizeof (attr));
168 169
169 170 (void) strlcpy(attr.hg_link_name,
170 171 dhip->dhi_link_name, sizeof (attr.hg_link_name));
171 172 attr.hg_grp_num = dhip->dhi_grp_num;
172 173 attr.hg_grp_type = dhip->dhi_grp_type;
173 174 attr.hg_n_rings = dhip->dhi_n_rings;
174 175 for (j = 0; j < dhip->dhi_n_rings; j++)
175 176 attr.hg_rings[j] = dhip->dhi_rings[j];
176 177 dladm_sort_index_list(attr.hg_rings, attr.hg_n_rings);
177 178 attr.hg_n_clnts = dhip->dhi_n_clnts;
178 179 (void) strlcpy(attr.hg_client_names,
179 180 dhip->dhi_clnts, sizeof (attr.hg_client_names));
180 181
181 182 if (!(*fn)(arg, &attr))
182 183 break;
183 184 dhip++;
184 185 }
185 186 }
186 187 free(iomp);
187 188 return (ret);
188 189 }
189 190
190 191 /*
191 192 * Invoke the specified callback for each MAC address entry defined on
192 193 * the specified device.
193 194 */
194 195 int
195 196 dladm_walk_macaddr(dladm_handle_t handle, datalink_id_t linkid, void *arg,
196 197 boolean_t (*fn)(void *, dladm_macaddr_attr_t *))
197 198 {
198 199 int bufsize, ret;
199 200 int nmacaddr = 1024;
200 201 dld_ioc_macaddrget_t *iomp = NULL;
201 202
202 203 bufsize = sizeof (dld_ioc_macaddrget_t) +
203 204 nmacaddr * sizeof (dld_macaddrinfo_t);
204 205
205 206 if ((iomp = (dld_ioc_macaddrget_t *)calloc(1, bufsize)) == NULL)
206 207 return (-1);
207 208
208 209 iomp->dig_size = nmacaddr * sizeof (dld_macaddrinfo_t);
209 210 iomp->dig_linkid = linkid;
210 211
211 212 ret = ioctl(dladm_dld_fd(handle), DLDIOC_MACADDRGET, iomp);
212 213 if (ret == 0) {
213 214 int i;
214 215 dld_macaddrinfo_t *dmip;
215 216 dladm_macaddr_attr_t attr;
216 217
217 218 dmip = (dld_macaddrinfo_t *)(iomp + 1);
218 219 for (i = 0; i < iomp->dig_count; i++) {
219 220 bzero(&attr, sizeof (attr));
220 221
221 222 attr.ma_slot = dmip->dmi_slot;
222 223 attr.ma_flags = 0;
223 224 if (dmip->dmi_flags & DLDIOCMACADDR_USED)
224 225 attr.ma_flags |= DLADM_MACADDR_USED;
225 226 bcopy(dmip->dmi_addr, attr.ma_addr,
226 227 dmip->dmi_addrlen);
227 228 attr.ma_addrlen = dmip->dmi_addrlen;
228 229 (void) strlcpy(attr.ma_client_name,
229 230 dmip->dmi_client_name, MAXNAMELEN);
230 231 attr.ma_client_linkid = dmip->dma_client_linkid;
231 232
232 233 if (!(*fn)(arg, &attr))
233 234 break;
234 235 dmip++;
235 236 }
236 237 }
237 238 free(iomp);
238 239 return (ret);
239 240 }
240 241
241 242 /*
242 243 * These routines are used by administration tools such as dladm(1M) to
243 244 * iterate through the list of MAC interfaces
244 245 */
245 246
246 247 typedef struct dladm_mac_dev {
247 248 char dm_name[MAXNAMELEN];
248 249 struct dladm_mac_dev *dm_next;
249 250 } dladm_mac_dev_t;
250 251
251 252 typedef struct macadm_walk {
252 253 dladm_mac_dev_t *dmd_dev_list;
253 254 } dladm_mac_walk_t;
254 255
255 256 /*
256 257 * Local callback invoked for each DDI_NT_NET node.
257 258 */
258 259 /* ARGSUSED */
259 260 static int
260 261 i_dladm_mac_walk(di_node_t node, di_minor_t minor, void *arg)
261 262 {
262 263 dladm_mac_walk_t *dmwp = arg;
263 264 dladm_mac_dev_t *dmdp = dmwp->dmd_dev_list;
264 265 dladm_mac_dev_t **last_dmdp = &dmwp->dmd_dev_list;
265 266 char mac[MAXNAMELEN];
266 267
267 268 (void) snprintf(mac, MAXNAMELEN, "%s%d",
268 269 di_driver_name(node), di_instance(node));
269 270
270 271 /*
271 272 * Skip aggregations.
272 273 */
273 274 if (strcmp("aggr", di_driver_name(node)) == 0)
274 275 return (DI_WALK_CONTINUE);
275 276
276 277 /*
277 278 * Skip softmacs.
278 279 */
279 280 if (strcmp("softmac", di_driver_name(node)) == 0)
280 281 return (DI_WALK_CONTINUE);
281 282
282 283 while (dmdp) {
283 284 /*
284 285 * Skip duplicates.
285 286 */
286 287 if (strcmp(dmdp->dm_name, mac) == 0)
287 288 return (DI_WALK_CONTINUE);
288 289
289 290 last_dmdp = &dmdp->dm_next;
290 291 dmdp = dmdp->dm_next;
291 292 }
292 293
293 294 if ((dmdp = malloc(sizeof (*dmdp))) == NULL)
294 295 return (DI_WALK_CONTINUE);
295 296
296 297 (void) strlcpy(dmdp->dm_name, mac, MAXNAMELEN);
297 298 dmdp->dm_next = NULL;
298 299 *last_dmdp = dmdp;
299 300
300 301 return (DI_WALK_CONTINUE);
301 302 }
302 303
303 304 /*
304 305 * Invoke the specified callback for each DDI_NT_NET node.
305 306 */
306 307 dladm_status_t
307 308 dladm_mac_walk(int (*fn)(const char *, void *arg), void *arg)
308 309 {
309 310 di_node_t root;
310 311 dladm_mac_walk_t dmw;
311 312 dladm_mac_dev_t *dmdp, *next;
312 313 boolean_t done = B_FALSE;
313 314
314 315 if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL)
315 316 return (dladm_errno2status(errno));
316 317
317 318 dmw.dmd_dev_list = NULL;
318 319
319 320 (void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, &dmw,
320 321 i_dladm_mac_walk);
321 322
322 323 di_fini(root);
323 324
324 325 dmdp = dmw.dmd_dev_list;
325 326 for (dmdp = dmw.dmd_dev_list; dmdp != NULL; dmdp = next) {
326 327 next = dmdp->dm_next;
327 328 if (!done &&
328 329 ((*fn)(dmdp->dm_name, arg) == DLADM_WALK_TERMINATE)) {
329 330 done = B_TRUE;
330 331 }
331 332 free(dmdp);
332 333 }
333 334
334 335 return (DLADM_STATUS_OK);
335 336 }
336 337
337 338 /*
338 339 * Get the current attributes of the specified datalink.
339 340 */
340 341 dladm_status_t
341 342 dladm_info(dladm_handle_t handle, datalink_id_t linkid, dladm_attr_t *dap)
342 343 {
343 344 return (i_dladm_info(handle, linkid, dap));
344 345 }
345 346
346 347 const char *
347 348 dladm_linkstate2str(link_state_t state, char *buf)
348 349 {
349 350 const char *s;
350 351
351 352 switch (state) {
352 353 case LINK_STATE_UP:
353 354 s = "up";
354 355 break;
355 356 case LINK_STATE_DOWN:
356 357 s = "down";
357 358 break;
358 359 default:
359 360 s = "unknown";
360 361 break;
361 362 }
362 363 (void) snprintf(buf, DLADM_STRSIZE, "%s", s);
363 364 return (buf);
364 365 }
365 366
366 367 const char *
367 368 dladm_linkduplex2str(link_duplex_t duplex, char *buf)
368 369 {
369 370 const char *s;
370 371
371 372 switch (duplex) {
372 373 case LINK_DUPLEX_FULL:
373 374 s = "full";
374 375 break;
375 376 case LINK_DUPLEX_HALF:
376 377 s = "half";
377 378 break;
378 379 default:
|
↓ open down ↓ |
346 lines elided |
↑ open up ↑ |
379 380 s = "unknown";
380 381 break;
381 382 }
382 383 (void) snprintf(buf, DLADM_STRSIZE, "%s", s);
383 384 return (buf);
384 385 }
385 386
386 387 /*
387 388 * Case 1: rename an existing link1 to a link2 that does not exist.
388 389 * Result: <linkid1, link2>
390 + * The zonename parameter is used to allow us to create a VNIC in the global
391 + * zone which is assigned to a non-global zone. Since there is a race condition
392 + * in the create process if two VNICs have the same name, we need to rename it
393 + * after it has been assigned to the zone.
389 394 */
390 395 static dladm_status_t
391 396 i_dladm_rename_link_c1(dladm_handle_t handle, datalink_id_t linkid1,
392 - const char *link1, const char *link2, uint32_t flags)
397 + const char *link1, const char *link2, uint32_t flags, const char *zonename)
393 398 {
394 399 dld_ioc_rename_t dir;
395 400 dladm_status_t status = DLADM_STATUS_OK;
396 401
397 402 /*
398 403 * Link is currently available. Check to see whether anything is
399 404 * holding this link to prevent a rename operation.
400 405 */
401 406 if (flags & DLADM_OPT_ACTIVE) {
402 407 dir.dir_linkid1 = linkid1;
403 408 dir.dir_linkid2 = DATALINK_INVALID_LINKID;
404 409 (void) strlcpy(dir.dir_link, link2, MAXLINKNAMELEN);
410 + if (zonename != NULL)
411 + dir.dir_zoneinit = B_TRUE;
412 + else
413 + dir.dir_zoneinit = B_FALSE;
405 414
406 415 if (ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir) < 0) {
407 416 status = dladm_errno2status(errno);
408 417 return (status);
409 418 }
410 419 }
411 420
412 421 status = dladm_remap_datalink_id(handle, linkid1, link2);
413 422 if (status != DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) {
414 423 (void) strlcpy(dir.dir_link, link1, MAXLINKNAMELEN);
424 + dir.dir_zoneinit = B_FALSE;
415 425 (void) ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir);
416 426 }
417 427 return (status);
418 428 }
419 429
420 430 typedef struct link_hold_arg_s {
421 431 datalink_id_t linkid;
422 432 datalink_id_t holder;
423 433 uint32_t flags;
424 434 } link_hold_arg_t;
425 435
426 436 static int
427 437 i_dladm_aggr_link_hold(dladm_handle_t handle, datalink_id_t aggrid, void *arg)
428 438 {
429 439 link_hold_arg_t *hold_arg = arg;
430 440 dladm_aggr_grp_attr_t ginfo;
431 441 dladm_status_t status;
432 442 int i;
433 443
434 444 status = dladm_aggr_info(handle, aggrid, &ginfo, hold_arg->flags);
435 445 if (status != DLADM_STATUS_OK)
436 446 return (DLADM_WALK_CONTINUE);
437 447
438 448 for (i = 0; i < ginfo.lg_nports; i++) {
439 449 if (ginfo.lg_ports[i].lp_linkid == hold_arg->linkid) {
440 450 hold_arg->holder = aggrid;
441 451 return (DLADM_WALK_TERMINATE);
442 452 }
443 453 }
444 454 return (DLADM_WALK_CONTINUE);
445 455 }
446 456
447 457 static int
448 458 i_dladm_vlan_link_hold(dladm_handle_t handle, datalink_id_t vlanid, void *arg)
449 459 {
450 460 link_hold_arg_t *hold_arg = arg;
451 461 dladm_vlan_attr_t vinfo;
452 462 dladm_status_t status;
453 463
454 464 status = dladm_vlan_info(handle, vlanid, &vinfo, hold_arg->flags);
455 465 if (status != DLADM_STATUS_OK)
456 466 return (DLADM_WALK_CONTINUE);
457 467
458 468 if (vinfo.dv_linkid == hold_arg->linkid) {
459 469 hold_arg->holder = vlanid;
460 470 return (DLADM_WALK_TERMINATE);
461 471 }
462 472 return (DLADM_WALK_CONTINUE);
463 473 }
464 474
465 475 /*
466 476 * Case 2: rename an available physical link link1 to a REMOVED physical link
467 477 * link2. As a result, link1 directly inherits all datalinks configured
468 478 * over link2 (linkid2).
469 479 * Result: <linkid2, link2, link1_phymaj, link1_phyinst, link1_devname,
470 480 * link2_other_attr>
471 481 */
472 482 static dladm_status_t
473 483 i_dladm_rename_link_c2(dladm_handle_t handle, datalink_id_t linkid1,
474 484 datalink_id_t linkid2)
475 485 {
476 486 rcm_handle_t *rcm_hdl = NULL;
477 487 nvlist_t *nvl = NULL;
478 488 link_hold_arg_t arg;
479 489 dld_ioc_rename_t dir;
480 490 dladm_conf_t conf1, conf2;
481 491 char devname[MAXLINKNAMELEN];
482 492 uint64_t phymaj, phyinst;
483 493 dladm_status_t status = DLADM_STATUS_OK;
484 494
485 495 /*
486 496 * First check if linkid1 is associated with any persistent
487 497 * aggregations or VLANs. If yes, return BUSY.
488 498 */
489 499 arg.linkid = linkid1;
490 500 arg.holder = DATALINK_INVALID_LINKID;
491 501 arg.flags = DLADM_OPT_PERSIST;
492 502 (void) dladm_walk_datalink_id(i_dladm_aggr_link_hold, handle, &arg,
493 503 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
494 504 if (arg.holder != DATALINK_INVALID_LINKID)
495 505 return (DLADM_STATUS_LINKBUSY);
496 506
497 507 arg.flags = DLADM_OPT_PERSIST;
498 508 (void) dladm_walk_datalink_id(i_dladm_vlan_link_hold, handle, &arg,
499 509 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
500 510 if (arg.holder != DATALINK_INVALID_LINKID)
|
↓ open down ↓ |
76 lines elided |
↑ open up ↑ |
501 511 return (DLADM_STATUS_LINKBUSY);
502 512
503 513 /*
504 514 * Send DLDIOC_RENAME to request to rename link1's linkid to
505 515 * be linkid2. This will check whether link1 is used by any
506 516 * aggregations or VLANs, or is held by any application. If yes,
507 517 * return failure.
508 518 */
509 519 dir.dir_linkid1 = linkid1;
510 520 dir.dir_linkid2 = linkid2;
521 + dir.dir_zoneinit = B_FALSE;
511 522 if (ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir) < 0)
512 523 status = dladm_errno2status(errno);
513 524
514 525 if (status != DLADM_STATUS_OK) {
515 526 return (status);
516 527 }
517 528
518 529 /*
519 530 * Now change the phymaj, phyinst and devname associated with linkid1
520 531 * to be associated with linkid2. Before doing that, the old active
521 532 * linkprop of linkid1 should be deleted.
522 533 */
523 534 (void) dladm_set_linkprop(handle, linkid1, NULL, NULL, 0,
524 535 DLADM_OPT_ACTIVE);
525 536
526 537 if (((status = dladm_getsnap_conf(handle, linkid1, &conf1)) !=
527 538 DLADM_STATUS_OK) ||
528 539 ((status = dladm_get_conf_field(handle, conf1, FDEVNAME, devname,
529 540 MAXLINKNAMELEN)) != DLADM_STATUS_OK) ||
530 541 ((status = dladm_get_conf_field(handle, conf1, FPHYMAJ, &phymaj,
531 542 sizeof (uint64_t))) != DLADM_STATUS_OK) ||
532 543 ((status = dladm_get_conf_field(handle, conf1, FPHYINST, &phyinst,
533 544 sizeof (uint64_t))) != DLADM_STATUS_OK) ||
534 545 ((status = dladm_open_conf(handle, linkid2, &conf2)) !=
535 546 DLADM_STATUS_OK)) {
536 547 dir.dir_linkid1 = linkid2;
537 548 dir.dir_linkid2 = linkid1;
538 549 (void) dladm_init_linkprop(handle, linkid1, B_FALSE);
539 550 (void) ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir);
540 551 return (status);
541 552 }
542 553
543 554 dladm_destroy_conf(handle, conf1);
544 555 (void) dladm_set_conf_field(handle, conf2, FDEVNAME, DLADM_TYPE_STR,
545 556 devname);
546 557 (void) dladm_set_conf_field(handle, conf2, FPHYMAJ, DLADM_TYPE_UINT64,
547 558 &phymaj);
548 559 (void) dladm_set_conf_field(handle, conf2, FPHYINST,
549 560 DLADM_TYPE_UINT64, &phyinst);
550 561 (void) dladm_write_conf(handle, conf2);
551 562 dladm_destroy_conf(handle, conf2);
552 563
553 564 /*
554 565 * Delete link1 and mark link2 up.
555 566 */
556 567 (void) dladm_remove_conf(handle, linkid1);
557 568 (void) dladm_destroy_datalink_id(handle, linkid1, DLADM_OPT_ACTIVE |
558 569 DLADM_OPT_PERSIST);
559 570 (void) dladm_up_datalink_id(handle, linkid2);
560 571
561 572 /*
562 573 * Now generate the RCM_RESOURCE_LINK_NEW sysevent which can be
563 574 * consumed by the RCM framework to restore all the datalink and
564 575 * IP configuration.
565 576 */
566 577 status = DLADM_STATUS_FAILED;
567 578 if ((nvlist_alloc(&nvl, 0, 0) != 0) ||
568 579 (nvlist_add_uint64(nvl, RCM_NV_LINKID, linkid2) != 0)) {
569 580 goto done;
570 581 }
571 582
572 583 if (rcm_alloc_handle(NULL, 0, NULL, &rcm_hdl) != RCM_SUCCESS)
573 584 goto done;
574 585
575 586 if (rcm_notify_event(rcm_hdl, RCM_RESOURCE_LINK_NEW, 0, nvl, NULL) ==
576 587 RCM_SUCCESS) {
577 588 status = DLADM_STATUS_OK;
578 589 }
579 590
580 591 done:
581 592 if (rcm_hdl != NULL)
582 593 (void) rcm_free_handle(rcm_hdl);
583 594 if (nvl != NULL)
584 595 nvlist_free(nvl);
585 596 return (status);
586 597 }
587 598
588 599 /*
589 600 * case 3: rename a non-existent link to a REMOVED physical link.
590 601 * Set the removed physical link's device name to link1, so that
591 602 * when link1 attaches, it inherits all the link configuration of
592 603 * the removed physical link.
593 604 */
594 605 static dladm_status_t
595 606 i_dladm_rename_link_c3(dladm_handle_t handle, const char *link1,
596 607 datalink_id_t linkid2)
597 608 {
598 609 dladm_conf_t conf;
599 610 dladm_status_t status;
600 611
601 612 if (!dladm_valid_linkname(link1))
602 613 return (DLADM_STATUS_LINKINVAL);
603 614
604 615 status = dladm_open_conf(handle, linkid2, &conf);
605 616 if (status != DLADM_STATUS_OK)
606 617 goto done;
607 618
608 619 if ((status = dladm_set_conf_field(handle, conf, FDEVNAME,
609 620 DLADM_TYPE_STR, link1)) == DLADM_STATUS_OK) {
|
↓ open down ↓ |
89 lines elided |
↑ open up ↑ |
610 621 status = dladm_write_conf(handle, conf);
611 622 }
612 623
613 624 dladm_destroy_conf(handle, conf);
614 625
615 626 done:
616 627 return (status);
617 628 }
618 629
619 630 dladm_status_t
620 -dladm_rename_link(dladm_handle_t handle, const char *link1, const char *link2)
631 +dladm_rename_link(dladm_handle_t handle, const char *zonename,
632 + const char *link1, const char *link2)
621 633 {
622 634 datalink_id_t linkid1 = DATALINK_INVALID_LINKID;
623 635 datalink_id_t linkid2 = DATALINK_INVALID_LINKID;
624 636 uint32_t flags1, flags2;
625 637 datalink_class_t class1, class2;
626 638 uint32_t media1, media2;
627 639 boolean_t remphy2 = B_FALSE;
628 640 dladm_status_t status;
629 641
630 - (void) dladm_name2info(handle, link1, &linkid1, &flags1, &class1,
631 - &media1);
632 - if ((dladm_name2info(handle, link2, &linkid2, &flags2, &class2,
633 - &media2) == DLADM_STATUS_OK) && (class2 == DATALINK_CLASS_PHYS) &&
634 - (flags2 == DLADM_OPT_PERSIST)) {
642 + (void) dladm_zname2info(handle, zonename, link1, &linkid1, &flags1,
643 + &class1, &media1);
644 + if ((dladm_zname2info(handle, zonename, link2, &linkid2, &flags2,
645 + &class2, &media2) == DLADM_STATUS_OK) &&
646 + (class2 == DATALINK_CLASS_PHYS) && (flags2 == DLADM_OPT_PERSIST)) {
635 647 /*
636 648 * see whether link2 is a removed physical link.
637 649 */
638 650 remphy2 = B_TRUE;
639 651 }
640 652
641 653 if (linkid1 != DATALINK_INVALID_LINKID) {
642 654 if (linkid2 == DATALINK_INVALID_LINKID) {
643 655 /*
644 656 * case 1: rename an existing link to a link that
645 657 * does not exist.
646 658 */
647 659 status = i_dladm_rename_link_c1(handle, linkid1, link1,
648 - link2, flags1);
660 + link2, flags1, zonename);
649 661 } else if (remphy2) {
650 662 /*
651 663 * case 2: rename an available link to a REMOVED
652 664 * physical link. Return failure if link1 is not
653 665 * an active physical link.
654 666 */
655 667 if ((class1 != class2) || (media1 != media2) ||
656 668 !(flags1 & DLADM_OPT_ACTIVE)) {
657 669 status = DLADM_STATUS_BADARG;
658 670 } else {
659 671 status = i_dladm_rename_link_c2(handle, linkid1,
660 672 linkid2);
661 673 }
662 674 } else {
663 675 status = DLADM_STATUS_EXIST;
664 676 }
665 677 } else if (remphy2) {
666 678 status = i_dladm_rename_link_c3(handle, link1, linkid2);
667 679 } else {
668 680 status = DLADM_STATUS_NOTFOUND;
669 681 }
670 682 return (status);
671 683 }
672 684
673 685 typedef struct consumer_del_phys_arg_s {
674 686 datalink_id_t linkid;
675 687 } consumer_del_phys_arg_t;
676 688
677 689 static int
678 690 i_dladm_vlan_link_del(dladm_handle_t handle, datalink_id_t vlanid, void *arg)
679 691 {
680 692 consumer_del_phys_arg_t *del_arg = arg;
681 693 dladm_vlan_attr_t vinfo;
682 694 dladm_status_t status;
683 695
684 696 status = dladm_vlan_info(handle, vlanid, &vinfo, DLADM_OPT_PERSIST);
685 697 if (status != DLADM_STATUS_OK)
686 698 return (DLADM_WALK_CONTINUE);
687 699
688 700 if (vinfo.dv_linkid == del_arg->linkid)
689 701 (void) dladm_vlan_delete(handle, vlanid, DLADM_OPT_PERSIST);
690 702 return (DLADM_WALK_CONTINUE);
691 703 }
692 704
693 705 static int
694 706 i_dladm_part_link_del(dladm_handle_t handle, datalink_id_t partid, void *arg)
695 707 {
696 708 consumer_del_phys_arg_t *del_arg = arg;
697 709 dladm_part_attr_t pinfo;
698 710 dladm_status_t status;
699 711
700 712 status = dladm_part_info(handle, partid, &pinfo, DLADM_OPT_PERSIST);
701 713 if (status != DLADM_STATUS_OK)
702 714 return (DLADM_WALK_CONTINUE);
703 715
704 716 if (pinfo.dia_physlinkid == del_arg->linkid)
705 717 (void) dladm_part_delete(handle, partid, DLADM_OPT_PERSIST);
706 718 return (DLADM_WALK_CONTINUE);
707 719 }
708 720
709 721 static int
710 722 i_dladm_aggr_link_del(dladm_handle_t handle, datalink_id_t aggrid, void *arg)
711 723 {
712 724 consumer_del_phys_arg_t *del_arg = arg;
713 725 dladm_aggr_grp_attr_t ginfo;
714 726 dladm_status_t status;
715 727 dladm_aggr_port_attr_db_t port[1];
716 728 int i;
717 729
718 730 status = dladm_aggr_info(handle, aggrid, &ginfo, DLADM_OPT_PERSIST);
719 731 if (status != DLADM_STATUS_OK)
720 732 return (DLADM_WALK_CONTINUE);
721 733
722 734 for (i = 0; i < ginfo.lg_nports; i++)
723 735 if (ginfo.lg_ports[i].lp_linkid == del_arg->linkid)
724 736 break;
725 737
726 738 if (i != ginfo.lg_nports) {
727 739 if (ginfo.lg_nports == 1 && i == 0) {
728 740 consumer_del_phys_arg_t aggr_del_arg;
729 741
730 742 /*
731 743 * First delete all the VLANs on this aggregation, then
732 744 * delete the aggregation itself.
733 745 */
734 746 aggr_del_arg.linkid = aggrid;
735 747 (void) dladm_walk_datalink_id(i_dladm_vlan_link_del,
736 748 handle, &aggr_del_arg, DATALINK_CLASS_VLAN,
737 749 DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
738 750 (void) dladm_aggr_delete(handle, aggrid,
739 751 DLADM_OPT_PERSIST);
740 752 } else {
741 753 port[0].lp_linkid = del_arg->linkid;
742 754 (void) dladm_aggr_remove(handle, aggrid, 1, port,
743 755 DLADM_OPT_PERSIST);
744 756 }
745 757 }
746 758 return (DLADM_WALK_CONTINUE);
747 759 }
748 760
749 761 typedef struct del_phys_arg_s {
750 762 dladm_status_t rval;
751 763 } del_phys_arg_t;
752 764
753 765 static int
754 766 i_dladm_phys_delete(dladm_handle_t handle, datalink_id_t linkid, void *arg)
755 767 {
756 768 uint32_t flags;
757 769 datalink_class_t class;
758 770 uint32_t media;
759 771 dladm_status_t status = DLADM_STATUS_OK;
760 772 del_phys_arg_t *del_phys_arg = arg;
761 773 consumer_del_phys_arg_t del_arg;
762 774
763 775 if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class,
764 776 &media, NULL, 0)) != DLADM_STATUS_OK) {
765 777 goto done;
766 778 }
767 779
768 780 /*
769 781 * see whether this link is a removed physical link.
770 782 */
771 783 if ((class != DATALINK_CLASS_PHYS) || !(flags & DLADM_OPT_PERSIST) ||
772 784 (flags & DLADM_OPT_ACTIVE)) {
773 785 status = DLADM_STATUS_BADARG;
774 786 goto done;
775 787 }
776 788
777 789 if (media == DL_ETHER) {
778 790 del_arg.linkid = linkid;
779 791 (void) dladm_walk_datalink_id(i_dladm_aggr_link_del, handle,
780 792 &del_arg, DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE,
781 793 DLADM_OPT_PERSIST);
782 794 (void) dladm_walk_datalink_id(i_dladm_vlan_link_del, handle,
783 795 &del_arg, DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE,
784 796 DLADM_OPT_PERSIST);
785 797 } else if (media == DL_IB) {
786 798 del_arg.linkid = linkid;
787 799 (void) dladm_walk_datalink_id(i_dladm_part_link_del, handle,
788 800 &del_arg, DATALINK_CLASS_PART, DL_IB, DLADM_OPT_PERSIST);
789 801 }
790 802
791 803 (void) dladm_remove_conf(handle, linkid);
792 804 (void) dladm_destroy_datalink_id(handle, linkid, DLADM_OPT_PERSIST);
793 805 done:
794 806 del_phys_arg->rval = status;
795 807 return (DLADM_WALK_CONTINUE);
796 808 }
797 809
798 810 dladm_status_t
799 811 dladm_phys_delete(dladm_handle_t handle, datalink_id_t linkid)
800 812 {
801 813 del_phys_arg_t arg = {DLADM_STATUS_OK};
802 814
803 815 if (linkid == DATALINK_ALL_LINKID) {
804 816 (void) dladm_walk_datalink_id(i_dladm_phys_delete, handle, &arg,
805 817 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE,
806 818 DLADM_OPT_PERSIST);
807 819 return (DLADM_STATUS_OK);
808 820 } else {
809 821 (void) i_dladm_phys_delete(handle, linkid, &arg);
810 822 return (arg.rval);
811 823 }
812 824 }
813 825
814 826 dladm_status_t
815 827 dladm_phys_info(dladm_handle_t handle, datalink_id_t linkid,
816 828 dladm_phys_attr_t *dpap, uint32_t flags)
817 829 {
818 830 dladm_status_t status;
819 831
820 832 assert(flags == DLADM_OPT_ACTIVE || flags == DLADM_OPT_PERSIST);
821 833
822 834 switch (flags) {
823 835 case DLADM_OPT_PERSIST: {
824 836 dladm_conf_t conf;
825 837
826 838 status = dladm_getsnap_conf(handle, linkid, &conf);
827 839 if (status != DLADM_STATUS_OK)
828 840 return (status);
829 841
830 842 status = dladm_get_conf_field(handle, conf, FDEVNAME,
831 843 dpap->dp_dev, MAXLINKNAMELEN);
832 844 dladm_destroy_conf(handle, conf);
833 845 return (status);
834 846 }
835 847 case DLADM_OPT_ACTIVE: {
836 848 dld_ioc_phys_attr_t dip;
837 849
838 850 dip.dip_linkid = linkid;
839 851 if (ioctl(dladm_dld_fd(handle), DLDIOC_PHYS_ATTR, &dip) < 0) {
840 852 status = dladm_errno2status(errno);
841 853 return (status);
842 854 }
843 855 dpap->dp_novanity = dip.dip_novanity;
844 856 (void) strlcpy(dpap->dp_dev, dip.dip_dev, MAXLINKNAMELEN);
845 857 return (DLADM_STATUS_OK);
846 858 }
847 859 default:
848 860 return (DLADM_STATUS_BADARG);
849 861 }
850 862 }
851 863
852 864 typedef struct i_walk_dev_state_s {
853 865 const char *devname;
854 866 datalink_id_t linkid;
855 867 boolean_t found;
856 868 } i_walk_dev_state_t;
857 869
858 870 int
859 871 i_dladm_walk_dev2linkid(dladm_handle_t handle, datalink_id_t linkid, void *arg)
860 872 {
861 873 dladm_phys_attr_t dpa;
862 874 dladm_status_t status;
863 875 i_walk_dev_state_t *statep = arg;
864 876
865 877 status = dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_PERSIST);
866 878 if ((status == DLADM_STATUS_OK) &&
867 879 (strcmp(statep->devname, dpa.dp_dev) == 0)) {
868 880 statep->found = B_TRUE;
869 881 statep->linkid = linkid;
870 882 return (DLADM_WALK_TERMINATE);
871 883 }
872 884 return (DLADM_WALK_CONTINUE);
873 885 }
874 886
875 887 /*
876 888 * Get the linkid from the physical device name.
877 889 */
878 890 dladm_status_t
879 891 dladm_dev2linkid(dladm_handle_t handle, const char *devname,
880 892 datalink_id_t *linkidp)
881 893 {
882 894 i_walk_dev_state_t state;
883 895
884 896 state.found = B_FALSE;
885 897 state.devname = devname;
886 898
887 899 (void) dladm_walk_datalink_id(i_dladm_walk_dev2linkid, handle, &state,
888 900 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
889 901 if (state.found == B_TRUE) {
890 902 *linkidp = state.linkid;
891 903 return (DLADM_STATUS_OK);
892 904 } else {
893 905 return (dladm_errno2status(ENOENT));
894 906 }
895 907 }
896 908
897 909 static int
898 910 parse_devname(const char *devname, char *driver, uint_t *ppa, size_t maxlen)
899 911 {
900 912 char *cp, *tp;
901 913 int len;
902 914
903 915 /*
904 916 * device name length must not be 0, and it must end with digit.
905 917 */
906 918 if (((len = strlen(devname)) == 0) || !isdigit(devname[len - 1]))
907 919 return (EINVAL);
908 920
909 921 (void) strlcpy(driver, devname, maxlen);
910 922 cp = (char *)&driver[len - 1];
911 923
912 924 for (tp = cp; isdigit(*tp); tp--) {
913 925 if (tp <= driver)
914 926 return (EINVAL);
915 927 }
916 928
917 929 *ppa = atoi(tp + 1);
918 930 *(tp + 1) = '\0';
919 931 return (0);
920 932 }
921 933
922 934 dladm_status_t
923 935 dladm_linkid2legacyname(dladm_handle_t handle, datalink_id_t linkid, char *dev,
924 936 size_t len)
925 937 {
926 938 char devname[MAXLINKNAMELEN];
927 939 uint16_t vid = VLAN_ID_NONE;
928 940 datalink_class_t class;
929 941 dladm_status_t status;
930 942
931 943 status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
932 944 NULL, 0);
933 945 if (status != DLADM_STATUS_OK)
934 946 goto done;
935 947
936 948 /*
937 949 * If this is a VLAN, we must first determine the class and linkid of
938 950 * the link the VLAN has been created over.
939 951 */
940 952 if (class == DATALINK_CLASS_VLAN) {
941 953 dladm_vlan_attr_t dva;
942 954
943 955 status = dladm_vlan_info(handle, linkid, &dva,
944 956 DLADM_OPT_ACTIVE);
945 957 if (status != DLADM_STATUS_OK)
946 958 goto done;
947 959 linkid = dva.dv_linkid;
948 960 vid = dva.dv_vid;
949 961
950 962 if ((status = dladm_datalink_id2info(handle, linkid, NULL,
951 963 &class, NULL, NULL, 0)) != DLADM_STATUS_OK) {
952 964 goto done;
953 965 }
954 966 }
955 967
956 968 switch (class) {
957 969 case DATALINK_CLASS_AGGR: {
958 970 dladm_aggr_grp_attr_t dga;
959 971
960 972 status = dladm_aggr_info(handle, linkid, &dga,
961 973 DLADM_OPT_ACTIVE);
962 974 if (status != DLADM_STATUS_OK)
963 975 goto done;
964 976
965 977 if (dga.lg_key == 0) {
966 978 /*
967 979 * If the key was not specified when the aggregation
968 980 * is created, we cannot guess its /dev node name.
969 981 */
970 982 status = DLADM_STATUS_BADARG;
971 983 goto done;
972 984 }
973 985 (void) snprintf(devname, MAXLINKNAMELEN, "aggr%d", dga.lg_key);
974 986 break;
975 987 }
976 988 case DATALINK_CLASS_PHYS: {
977 989 dladm_phys_attr_t dpa;
978 990
979 991 status = dladm_phys_info(handle, linkid, &dpa,
980 992 DLADM_OPT_PERSIST);
981 993 if (status != DLADM_STATUS_OK)
982 994 goto done;
983 995
984 996 (void) strlcpy(devname, dpa.dp_dev, MAXLINKNAMELEN);
985 997 break;
986 998 }
987 999 default:
988 1000 status = DLADM_STATUS_BADARG;
989 1001 goto done;
990 1002 }
991 1003
992 1004 if (vid != VLAN_ID_NONE) {
993 1005 char drv[MAXNAMELEN];
994 1006 uint_t ppa;
995 1007
996 1008 if (parse_devname(devname, drv, &ppa, MAXNAMELEN) != 0) {
997 1009 status = DLADM_STATUS_BADARG;
998 1010 goto done;
999 1011 }
1000 1012 if (snprintf(dev, len, "%s%d", drv, vid * 1000 + ppa) >= len)
1001 1013 status = DLADM_STATUS_TOOSMALL;
1002 1014 } else {
1003 1015 if (strlcpy(dev, devname, len) >= len)
1004 1016 status = DLADM_STATUS_TOOSMALL;
1005 1017 }
1006 1018
1007 1019 done:
1008 1020 return (status);
1009 1021 }
1010 1022
1011 1023 dladm_status_t
1012 1024 dladm_parselink(const char *dev, char *provider, uint_t *ppa)
1013 1025 {
1014 1026 ifspec_t ifsp;
1015 1027
1016 1028 if (dev == NULL || !ifparse_ifspec(dev, &ifsp))
1017 1029 return (DLADM_STATUS_LINKINVAL);
1018 1030
1019 1031 if (provider != NULL)
1020 1032 (void) strlcpy(provider, ifsp.ifsp_devnm, DLPI_LINKNAME_MAX);
1021 1033
1022 1034 if (ppa != NULL)
1023 1035 *ppa = ifsp.ifsp_ppa;
1024 1036
1025 1037 return (DLADM_STATUS_OK);
1026 1038 }
|
↓ open down ↓ |
368 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX