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