Print this page
patch tsoome-feedback
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/rcm_daemon/common/vlan_rcm.c
+++ new/usr/src/cmd/rcm_daemon/common/vlan_rcm.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) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 /*
26 26 * This RCM module adds support to the RCM framework for VLAN links
27 27 */
28 28
29 29 #include <stdio.h>
30 30 #include <stdlib.h>
31 31 #include <string.h>
32 32 #include <errno.h>
33 33 #include <sys/types.h>
34 34 #include <synch.h>
35 35 #include <assert.h>
36 36 #include <strings.h>
37 37 #include "rcm_module.h"
38 38 #include <libintl.h>
39 39 #include <libdllink.h>
40 40 #include <libdlvlan.h>
41 41 #include <libdlpi.h>
42 42
43 43 /*
44 44 * Definitions
45 45 */
46 46 #ifndef lint
47 47 #define _(x) gettext(x)
48 48 #else
49 49 #define _(x) x
50 50 #endif
51 51
52 52 /* Some generic well-knowns and defaults used in this module */
53 53 #define RCM_LINK_PREFIX "SUNW_datalink" /* RCM datalink name prefix */
54 54 #define RCM_LINK_RESOURCE_MAX (13 + LINKID_STR_WIDTH)
55 55
56 56 /* VLAN link flags */
57 57 typedef enum {
58 58 VLAN_OFFLINED = 0x1,
59 59 VLAN_CONSUMER_OFFLINED = 0x2,
60 60 VLAN_STALE = 0x4
61 61 } vlan_flag_t;
62 62
63 63 /* link representation */
64 64 typedef struct dl_vlan {
65 65 struct dl_vlan *dv_next; /* next VLAN on the same link */
66 66 struct dl_vlan *dv_prev; /* prev VLAN on the same link */
67 67 datalink_id_t dv_vlanid;
68 68 vlan_flag_t dv_flags; /* VLAN link flags */
69 69 } dl_vlan_t;
70 70
71 71 /* VLAN Cache state flags */
72 72 typedef enum {
73 73 CACHE_NODE_STALE = 0x1, /* stale cached data */
74 74 CACHE_NODE_NEW = 0x2, /* new cached nodes */
75 75 CACHE_NODE_OFFLINED = 0x4 /* nodes offlined */
76 76 } cache_node_state_t;
77 77
78 78 /* Network Cache lookup options */
79 79 #define CACHE_NO_REFRESH 0x1 /* cache refresh not needed */
80 80 #define CACHE_REFRESH 0x2 /* refresh cache */
81 81
82 82 /* Cache element */
83 83 typedef struct link_cache {
84 84 struct link_cache *vc_next; /* next cached resource */
85 85 struct link_cache *vc_prev; /* prev cached resource */
86 86 char *vc_resource; /* resource name */
87 87 datalink_id_t vc_linkid; /* linkid */
88 88 dl_vlan_t *vc_vlan; /* VLAN list on this link */
89 89 cache_node_state_t vc_state; /* cache state flags */
90 90 } link_cache_t;
91 91
92 92 /*
93 93 * Global cache for network VLANs
94 94 */
95 95 static link_cache_t cache_head;
96 96 static link_cache_t cache_tail;
97 97 static mutex_t cache_lock;
98 98 static int events_registered = 0;
99 99
100 100 static dladm_handle_t dld_handle = NULL;
101 101
102 102 /*
103 103 * RCM module interface prototypes
104 104 */
105 105 static int vlan_register(rcm_handle_t *);
106 106 static int vlan_unregister(rcm_handle_t *);
107 107 static int vlan_get_info(rcm_handle_t *, char *, id_t, uint_t,
108 108 char **, char **, nvlist_t *, rcm_info_t **);
109 109 static int vlan_suspend(rcm_handle_t *, char *, id_t,
110 110 timespec_t *, uint_t, char **, rcm_info_t **);
111 111 static int vlan_resume(rcm_handle_t *, char *, id_t, uint_t,
112 112 char **, rcm_info_t **);
113 113 static int vlan_offline(rcm_handle_t *, char *, id_t, uint_t,
114 114 char **, rcm_info_t **);
115 115 static int vlan_undo_offline(rcm_handle_t *, char *, id_t, uint_t,
116 116 char **, rcm_info_t **);
117 117 static int vlan_remove(rcm_handle_t *, char *, id_t, uint_t,
118 118 char **, rcm_info_t **);
119 119 static int vlan_notify_event(rcm_handle_t *, char *, id_t, uint_t,
120 120 char **, nvlist_t *, rcm_info_t **);
121 121 static int vlan_configure(rcm_handle_t *, datalink_id_t);
122 122
123 123 /* Module private routines */
124 124 static void cache_free();
125 125 static int cache_update(rcm_handle_t *);
126 126 static void cache_remove(link_cache_t *);
127 127 static void node_free(link_cache_t *);
128 128 static void cache_insert(link_cache_t *);
129 129 static link_cache_t *cache_lookup(rcm_handle_t *, char *, char);
130 130 static int vlan_consumer_offline(rcm_handle_t *, link_cache_t *,
131 131 char **, uint_t, rcm_info_t **);
132 132 static void vlan_consumer_online(rcm_handle_t *, link_cache_t *,
133 133 char **, uint_t, rcm_info_t **);
134 134 static int vlan_offline_vlan(link_cache_t *, uint32_t,
135 135 cache_node_state_t);
136 136 static void vlan_online_vlan(link_cache_t *);
137 137 static char *vlan_usage(link_cache_t *);
138 138 static void vlan_log_err(datalink_id_t, char **, char *);
139 139 static int vlan_consumer_notify(rcm_handle_t *, datalink_id_t,
140 140 char **, uint_t, rcm_info_t **);
141 141
142 142 /* Module-Private data */
143 143 static struct rcm_mod_ops vlan_ops =
144 144 {
145 145 RCM_MOD_OPS_VERSION,
146 146 vlan_register,
147 147 vlan_unregister,
148 148 vlan_get_info,
149 149 vlan_suspend,
150 150 vlan_resume,
151 151 vlan_offline,
152 152 vlan_undo_offline,
153 153 vlan_remove,
154 154 NULL,
155 155 NULL,
156 156 vlan_notify_event
157 157 };
158 158
159 159 /*
160 160 * rcm_mod_init() - Update registrations, and return the ops structure.
161 161 */
162 162 struct rcm_mod_ops *
163 163 rcm_mod_init(void)
164 164 {
165 165 dladm_status_t status;
166 166 char errmsg[DLADM_STRSIZE];
167 167
168 168 rcm_log_message(RCM_TRACE1, "VLAN: mod_init\n");
169 169
170 170 cache_head.vc_next = &cache_tail;
171 171 cache_head.vc_prev = NULL;
172 172 cache_tail.vc_prev = &cache_head;
173 173 cache_tail.vc_next = NULL;
174 174 (void) mutex_init(&cache_lock, 0, NULL);
175 175
176 176 if ((status = dladm_open(&dld_handle)) != DLADM_STATUS_OK) {
177 177 rcm_log_message(RCM_WARNING,
178 178 "VLAN: mod_init failed: cannot open datalink handle: %s\n",
179 179 dladm_status2str(status, errmsg));
180 180 return (NULL);
181 181 }
182 182
183 183 /* Return the ops vectors */
184 184 return (&vlan_ops);
185 185 }
186 186
187 187 /*
188 188 * rcm_mod_info() - Return a string describing this module.
189 189 */
190 190 const char *
191 191 rcm_mod_info(void)
192 192 {
193 193 rcm_log_message(RCM_TRACE1, "VLAN: mod_info\n");
194 194
195 195 return ("VLAN module version 1.2");
196 196 }
197 197
198 198 /*
199 199 * rcm_mod_fini() - Destroy the network VLAN cache.
200 200 */
201 201 int
202 202 rcm_mod_fini(void)
203 203 {
204 204 rcm_log_message(RCM_TRACE1, "VLAN: mod_fini\n");
205 205
206 206 /*
207 207 * Note that vlan_unregister() does not seem to be called anywhere,
208 208 * therefore we free the cache nodes here. In theory we should call
209 209 * rcm_register_interest() for each node before we free it, the
210 210 * framework does not provide the rcm_handle to allow us to do so.
211 211 */
212 212 cache_free();
213 213 (void) mutex_destroy(&cache_lock);
214 214
215 215 dladm_close(dld_handle);
216 216 return (RCM_SUCCESS);
217 217 }
218 218
219 219 /*
220 220 * vlan_register() - Make sure the cache is properly sync'ed, and its
221 221 * registrations are in order.
222 222 */
223 223 static int
224 224 vlan_register(rcm_handle_t *hd)
225 225 {
226 226 rcm_log_message(RCM_TRACE1, "VLAN: register\n");
227 227
228 228 if (cache_update(hd) < 0)
229 229 return (RCM_FAILURE);
230 230
231 231 /*
232 232 * Need to register interest in all new resources
233 233 * getting attached, so we get attach event notifications
234 234 */
235 235 if (!events_registered) {
236 236 if (rcm_register_event(hd, RCM_RESOURCE_LINK_NEW, 0, NULL)
237 237 != RCM_SUCCESS) {
238 238 rcm_log_message(RCM_ERROR,
239 239 _("VLAN: failed to register %s\n"),
240 240 RCM_RESOURCE_LINK_NEW);
241 241 return (RCM_FAILURE);
242 242 } else {
243 243 rcm_log_message(RCM_DEBUG, "VLAN: registered %s\n",
244 244 RCM_RESOURCE_LINK_NEW);
245 245 events_registered++;
246 246 }
247 247 }
248 248
249 249 return (RCM_SUCCESS);
250 250 }
251 251
252 252 /*
253 253 * vlan_unregister() - Walk the cache, unregistering all the networks.
254 254 */
255 255 static int
256 256 vlan_unregister(rcm_handle_t *hd)
257 257 {
258 258 link_cache_t *node;
259 259
260 260 rcm_log_message(RCM_TRACE1, "VLAN: unregister\n");
261 261
262 262 /* Walk the cache, unregistering everything */
263 263 (void) mutex_lock(&cache_lock);
264 264 node = cache_head.vc_next;
265 265 while (node != &cache_tail) {
266 266 if (rcm_unregister_interest(hd, node->vc_resource, 0)
267 267 != RCM_SUCCESS) {
268 268 rcm_log_message(RCM_ERROR,
269 269 _("VLAN: failed to unregister %s\n"),
270 270 node->vc_resource);
271 271 (void) mutex_unlock(&cache_lock);
272 272 return (RCM_FAILURE);
273 273 }
274 274 cache_remove(node);
275 275 node_free(node);
276 276 node = cache_head.vc_next;
277 277 }
278 278 (void) mutex_unlock(&cache_lock);
279 279
280 280 /*
281 281 * Unregister interest in all new resources
282 282 */
283 283 if (events_registered) {
284 284 if (rcm_unregister_event(hd, RCM_RESOURCE_LINK_NEW, 0)
285 285 != RCM_SUCCESS) {
286 286 rcm_log_message(RCM_ERROR,
287 287 _("VLAN: failed to unregister %s\n"),
288 288 RCM_RESOURCE_LINK_NEW);
289 289 return (RCM_FAILURE);
290 290 } else {
291 291 rcm_log_message(RCM_DEBUG, "VLAN: unregistered %s\n",
292 292 RCM_RESOURCE_LINK_NEW);
293 293 events_registered--;
294 294 }
295 295 }
296 296
297 297 return (RCM_SUCCESS);
298 298 }
299 299
300 300 /*
301 301 * vlan_offline() - Offline VLANs on a specific node.
302 302 */
303 303 static int
304 304 vlan_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
305 305 char **errorp, rcm_info_t **info)
306 306 {
307 307 link_cache_t *node;
308 308
309 309 rcm_log_message(RCM_TRACE1, "VLAN: offline(%s)\n", rsrc);
310 310
311 311 /* Lock the cache and lookup the resource */
312 312 (void) mutex_lock(&cache_lock);
313 313 node = cache_lookup(hd, rsrc, CACHE_REFRESH);
314 314 if (node == NULL) {
315 315 /* should not happen because the resource is registered. */
316 316 vlan_log_err(DATALINK_INVALID_LINKID, errorp,
317 317 "unrecognized resource");
318 318 (void) mutex_unlock(&cache_lock);
319 319 return (RCM_SUCCESS);
320 320 }
321 321
322 322 /*
323 323 * Inform consumers (IP interfaces) of associated VLANs to be offlined
324 324 */
325 325 if (vlan_consumer_offline(hd, node, errorp, flags, info) ==
326 326 RCM_SUCCESS) {
327 327 rcm_log_message(RCM_DEBUG,
328 328 "VLAN: consumers agreed on offline\n");
329 329 } else {
330 330 vlan_log_err(node->vc_linkid, errorp,
331 331 "consumers failed to offline");
332 332 (void) mutex_unlock(&cache_lock);
333 333 return (RCM_FAILURE);
334 334 }
335 335
336 336 /* Check if it's a query */
337 337 if (flags & RCM_QUERY) {
338 338 rcm_log_message(RCM_TRACE1,
339 339 "VLAN: offline query succeeded(%s)\n", rsrc);
340 340 (void) mutex_unlock(&cache_lock);
341 341 return (RCM_SUCCESS);
342 342 }
343 343
344 344 if (vlan_offline_vlan(node, VLAN_OFFLINED, CACHE_NODE_OFFLINED) !=
345 345 RCM_SUCCESS) {
346 346 vlan_online_vlan(node);
347 347 vlan_log_err(node->vc_linkid, errorp, "offline failed");
348 348 (void) mutex_unlock(&cache_lock);
349 349 return (RCM_FAILURE);
350 350 }
351 351
352 352 rcm_log_message(RCM_TRACE1, "VLAN: Offline succeeded(%s)\n", rsrc);
353 353 (void) mutex_unlock(&cache_lock);
354 354 return (RCM_SUCCESS);
355 355 }
356 356
357 357 /*
358 358 * vlan_undo_offline() - Undo offline of a previously offlined node.
359 359 */
360 360 /*ARGSUSED*/
361 361 static int
362 362 vlan_undo_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
363 363 char **errorp, rcm_info_t **info)
364 364 {
365 365 link_cache_t *node;
366 366
367 367 rcm_log_message(RCM_TRACE1, "VLAN: online(%s)\n", rsrc);
368 368
369 369 (void) mutex_lock(&cache_lock);
370 370 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
371 371 if (node == NULL) {
372 372 vlan_log_err(DATALINK_INVALID_LINKID, errorp, "no such link");
373 373 (void) mutex_unlock(&cache_lock);
374 374 errno = ENOENT;
375 375 return (RCM_FAILURE);
376 376 }
377 377
378 378 /* Check if no attempt should be made to online the link here */
379 379 if (!(node->vc_state & CACHE_NODE_OFFLINED)) {
380 380 vlan_log_err(node->vc_linkid, errorp, "link not offlined");
381 381 (void) mutex_unlock(&cache_lock);
382 382 errno = ENOTSUP;
383 383 return (RCM_SUCCESS);
384 384 }
385 385
386 386 vlan_online_vlan(node);
387 387
388 388 /*
389 389 * Inform IP interfaces on associated VLANs to be onlined
390 390 */
391 391 vlan_consumer_online(hd, node, errorp, flags, info);
392 392
393 393 node->vc_state &= ~CACHE_NODE_OFFLINED;
394 394 rcm_log_message(RCM_TRACE1, "VLAN: online succeeded(%s)\n", rsrc);
395 395 (void) mutex_unlock(&cache_lock);
396 396 return (RCM_SUCCESS);
397 397 }
398 398
399 399 static void
400 400 vlan_online_vlan(link_cache_t *node)
401 401 {
402 402 dl_vlan_t *vlan;
403 403 dladm_status_t status;
404 404 char errmsg[DLADM_STRSIZE];
405 405
406 406 /*
407 407 * Try to bring on all offlined VLANs
408 408 */
409 409 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
410 410 if (!(vlan->dv_flags & VLAN_OFFLINED))
411 411 continue;
412 412
413 413 if ((status = dladm_vlan_up(dld_handle, vlan->dv_vlanid)) !=
414 414 DLADM_STATUS_OK) {
415 415 /*
416 416 * Print a warning message and continue to online
417 417 * other VLANs.
418 418 */
419 419 rcm_log_message(RCM_WARNING,
420 420 _("VLAN: VLAN online failed (%u): %s\n"),
421 421 vlan->dv_vlanid, dladm_status2str(status, errmsg));
422 422 } else {
423 423 vlan->dv_flags &= ~VLAN_OFFLINED;
424 424 }
425 425 }
426 426 }
427 427
428 428 static int
429 429 vlan_offline_vlan(link_cache_t *node, uint32_t flags, cache_node_state_t state)
430 430 {
431 431 dl_vlan_t *vlan;
432 432 dladm_status_t status;
433 433 char errmsg[DLADM_STRSIZE];
434 434
435 435 rcm_log_message(RCM_TRACE2, "VLAN: vlan_offline_vlan (%s %u %u)\n",
436 436 node->vc_resource, flags, state);
437 437
438 438 /*
439 439 * Try to delete all explicit created VLAN
440 440 */
441 441 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
442 442 if ((status = dladm_vlan_delete(dld_handle, vlan->dv_vlanid,
443 443 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
444 444 rcm_log_message(RCM_WARNING,
445 445 _("VLAN: VLAN offline failed (%u): %s\n"),
446 446 vlan->dv_vlanid, dladm_status2str(status, errmsg));
447 447 return (RCM_FAILURE);
448 448 } else {
449 449 rcm_log_message(RCM_TRACE1,
450 450 "VLAN: VLAN offline succeeded(%u)\n",
451 451 vlan->dv_vlanid);
452 452 vlan->dv_flags |= flags;
453 453 }
454 454 }
455 455
456 456 node->vc_state |= state;
457 457 return (RCM_SUCCESS);
458 458 }
459 459
460 460 /*
461 461 * vlan_get_info() - Gather usage information for this resource.
462 462 */
463 463 /*ARGSUSED*/
464 464 int
465 465 vlan_get_info(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
466 466 char **usagep, char **errorp, nvlist_t *props, rcm_info_t **info)
467 467 {
468 468 link_cache_t *node;
469 469
470 470 rcm_log_message(RCM_TRACE1, "VLAN: get_info(%s)\n", rsrc);
471 471
472 472 (void) mutex_lock(&cache_lock);
473 473 node = cache_lookup(hd, rsrc, CACHE_REFRESH);
474 474 if (node == NULL) {
475 475 rcm_log_message(RCM_INFO,
476 476 _("VLAN: get_info(%s) unrecognized resource\n"), rsrc);
477 477 (void) mutex_unlock(&cache_lock);
478 478 errno = ENOENT;
479 479 return (RCM_FAILURE);
480 480 }
481 481
482 482 *usagep = vlan_usage(node);
483 483 (void) mutex_unlock(&cache_lock);
484 484 if (*usagep == NULL) {
485 485 /* most likely malloc failure */
486 486 rcm_log_message(RCM_ERROR,
487 487 _("VLAN: get_info(%s) malloc failure\n"), rsrc);
488 488 (void) mutex_unlock(&cache_lock);
489 489 errno = ENOMEM;
490 490 return (RCM_FAILURE);
491 491 }
492 492
493 493 /* Set client/role properties */
494 494 (void) nvlist_add_string(props, RCM_CLIENT_NAME, "VLAN");
495 495
496 496 rcm_log_message(RCM_TRACE1, "VLAN: get_info(%s) info = %s\n",
497 497 rsrc, *usagep);
498 498 return (RCM_SUCCESS);
499 499 }
500 500
501 501 /*
502 502 * vlan_suspend() - Nothing to do, always okay
503 503 */
504 504 /*ARGSUSED*/
505 505 static int
506 506 vlan_suspend(rcm_handle_t *hd, char *rsrc, id_t id, timespec_t *interval,
507 507 uint_t flags, char **errorp, rcm_info_t **info)
508 508 {
509 509 rcm_log_message(RCM_TRACE1, "VLAN: suspend(%s)\n", rsrc);
510 510 return (RCM_SUCCESS);
511 511 }
512 512
513 513 /*
514 514 * vlan_resume() - Nothing to do, always okay
515 515 */
516 516 /*ARGSUSED*/
517 517 static int
518 518 vlan_resume(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
519 519 char **errorp, rcm_info_t **info)
520 520 {
521 521 rcm_log_message(RCM_TRACE1, "VLAN: resume(%s)\n", rsrc);
522 522 return (RCM_SUCCESS);
523 523 }
524 524
525 525 /*
526 526 * vlan_consumer_remove()
527 527 *
528 528 * Notify VLAN consumers to remove cache.
529 529 */
530 530 static int
531 531 vlan_consumer_remove(rcm_handle_t *hd, link_cache_t *node, uint_t flags,
532 532 rcm_info_t **info)
533 533 {
534 534 dl_vlan_t *vlan = NULL;
535 535 char rsrc[RCM_LINK_RESOURCE_MAX];
536 536 int ret = RCM_SUCCESS;
537 537
538 538 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_remove (%s)\n",
539 539 node->vc_resource);
540 540
541 541 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
542 542
543 543 /*
544 544 * This will only be called when the offline operation
545 545 * succeeds, so the VLAN consumers must have been offlined
546 546 * at this point.
547 547 */
548 548 assert(vlan->dv_flags & VLAN_CONSUMER_OFFLINED);
549 549
550 550 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
551 551 RCM_LINK_PREFIX, vlan->dv_vlanid);
552 552
553 553 ret = rcm_notify_remove(hd, rsrc, flags, info);
554 554 if (ret != RCM_SUCCESS) {
555 555 rcm_log_message(RCM_WARNING,
556 556 _("VLAN: notify remove failed (%s)\n"), rsrc);
557 557 break;
558 558 }
559 559 }
560 560
561 561 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_remove done\n");
562 562 return (ret);
563 563 }
564 564
565 565 /*
566 566 * vlan_remove() - remove a resource from cache
567 567 */
568 568 /*ARGSUSED*/
569 569 static int
570 570 vlan_remove(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
571 571 char **errorp, rcm_info_t **info)
572 572 {
573 573 link_cache_t *node;
574 574 int rv;
575 575
576 576 rcm_log_message(RCM_TRACE1, "VLAN: remove(%s)\n", rsrc);
577 577
578 578 (void) mutex_lock(&cache_lock);
579 579 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
580 580 if (node == NULL) {
581 581 rcm_log_message(RCM_INFO,
582 582 _("VLAN: remove(%s) unrecognized resource\n"), rsrc);
583 583 (void) mutex_unlock(&cache_lock);
584 584 errno = ENOENT;
585 585 return (RCM_FAILURE);
586 586 }
587 587
588 588 /* remove the cached entry for the resource */
589 589 cache_remove(node);
590 590 (void) mutex_unlock(&cache_lock);
591 591
592 592 rv = vlan_consumer_remove(hd, node, flags, info);
593 593 node_free(node);
594 594 return (rv);
595 595 }
596 596
597 597 /*
598 598 * vlan_notify_event - Project private implementation to receive new resource
599 599 * events. It intercepts all new resource events. If the
600 600 * new resource is a network resource, pass up a notify
601 601 * for it too. The new resource need not be cached, since
602 602 * it is done at register again.
603 603 */
604 604 /*ARGSUSED*/
605 605 static int
606 606 vlan_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
607 607 char **errorp, nvlist_t *nvl, rcm_info_t **info)
608 608 {
609 609 nvpair_t *nvp = NULL;
610 610 datalink_id_t linkid;
611 611 uint64_t id64;
612 612 int rv = RCM_SUCCESS;
613 613
614 614 rcm_log_message(RCM_TRACE1, "VLAN: notify_event(%s)\n", rsrc);
615 615
616 616 if (strcmp(rsrc, RCM_RESOURCE_LINK_NEW) != 0) {
617 617 vlan_log_err(DATALINK_INVALID_LINKID, errorp,
618 618 "unrecognized event");
619 619 errno = EINVAL;
620 620 return (RCM_FAILURE);
621 621 }
622 622
623 623 /* Update cache to reflect latest VLANs */
624 624 if (cache_update(hd) < 0) {
625 625 vlan_log_err(DATALINK_INVALID_LINKID, errorp,
626 626 "private Cache update failed");
627 627 return (RCM_FAILURE);
628 628 }
629 629
630 630 /*
631 631 * Try best to recover all configuration.
632 632 */
633 633 rcm_log_message(RCM_DEBUG, "VLAN: process_nvlist\n");
634 634 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
635 635 if (strcmp(nvpair_name(nvp), RCM_NV_LINKID) != 0)
636 636 continue;
637 637
638 638 if (nvpair_value_uint64(nvp, &id64) != 0) {
639 639 vlan_log_err(DATALINK_INVALID_LINKID, errorp,
640 640 "cannot get linkid");
641 641 rv = RCM_FAILURE;
642 642 continue;
643 643 }
644 644
645 645 linkid = (datalink_id_t)id64;
646 646 if (vlan_configure(hd, linkid) != 0) {
647 647 vlan_log_err(linkid, errorp, "configuring failed");
648 648 rv = RCM_FAILURE;
649 649 continue;
650 650 }
651 651
652 652 /* Notify all VLAN consumers */
653 653 if (vlan_consumer_notify(hd, linkid, errorp, flags,
654 654 info) != 0) {
655 655 vlan_log_err(linkid, errorp, "consumer notify failed");
656 656 rv = RCM_FAILURE;
657 657 }
658 658 }
659 659
660 660 rcm_log_message(RCM_TRACE1,
661 661 "VLAN: notify_event: link configuration complete\n");
662 662 return (rv);
663 663 }
664 664
665 665 /*
666 666 * vlan_usage - Determine the usage of a link.
667 667 * The returned buffer is owned by caller, and the caller
668 668 * must free it up when done.
669 669 */
670 670 static char *
671 671 vlan_usage(link_cache_t *node)
672 672 {
673 673 dl_vlan_t *vlan;
674 674 int nvlan;
675 675 char *buf;
676 676 const char *fmt;
677 677 char *sep;
678 678 char errmsg[DLADM_STRSIZE];
679 679 char name[MAXLINKNAMELEN];
680 680 dladm_status_t status;
681 681 size_t bufsz;
682 682
683 683 rcm_log_message(RCM_TRACE2, "VLAN: usage(%s)\n", node->vc_resource);
684 684
685 685 assert(MUTEX_HELD(&cache_lock));
686 686 if ((status = dladm_datalink_id2info(dld_handle, node->vc_linkid, NULL,
687 687 NULL, NULL, name, sizeof (name))) != DLADM_STATUS_OK) {
688 688 rcm_log_message(RCM_ERROR,
689 689 _("VLAN: usage(%s) get link name failure(%s)\n"),
690 690 node->vc_resource, dladm_status2str(status, errmsg));
691 691 return (NULL);
692 692 }
693 693
694 694 if (node->vc_state & CACHE_NODE_OFFLINED)
695 695 fmt = _("%1$s offlined");
696 696 else
697 697 fmt = _("%1$s VLANs: ");
698 698
699 699 /* TRANSLATION_NOTE: separator used between VLAN linkids */
700 700 sep = _(", ");
701 701
702 702 nvlan = 0;
703 703 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next)
704 704 nvlan++;
705 705
706 706 /* space for VLANs and separators, plus message */
707 707 bufsz = nvlan * (MAXLINKNAMELEN + strlen(sep)) +
708 708 strlen(fmt) + MAXLINKNAMELEN + 1;
709 709 if ((buf = malloc(bufsz)) == NULL) {
710 710 rcm_log_message(RCM_ERROR,
711 711 _("VLAN: usage(%s) malloc failure(%s)\n"),
712 712 node->vc_resource, strerror(errno));
713 713 return (NULL);
714 714 }
715 715 (void) snprintf(buf, bufsz, fmt, name);
716 716
717 717 if (node->vc_state & CACHE_NODE_OFFLINED) {
718 718 /* Nothing else to do */
719 719 rcm_log_message(RCM_TRACE2, "VLAN: usage (%s) info = %s\n",
720 720 node->vc_resource, buf);
721 721 return (buf);
722 722 }
723 723
724 724 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
725 725 rcm_log_message(RCM_DEBUG, "VLAN:= %u\n", vlan->dv_vlanid);
726 726
727 727 if ((status = dladm_datalink_id2info(dld_handle,
728 728 vlan->dv_vlanid, NULL, NULL, NULL, name,
729 729 sizeof (name))) != DLADM_STATUS_OK) {
730 730 rcm_log_message(RCM_ERROR,
731 731 _("VLAN: usage(%s) get vlan %u name failure(%s)\n"),
732 732 node->vc_resource, vlan->dv_vlanid,
733 733 dladm_status2str(status, errmsg));
734 734 free(buf);
735 735 return (NULL);
736 736 }
737 737
738 738 (void) strlcat(buf, name, bufsz);
739 739 if (vlan->dv_next != NULL)
740 740 (void) strlcat(buf, sep, bufsz);
741 741 }
742 742
743 743 rcm_log_message(RCM_TRACE2, "VLAN: usage (%s) info = %s\n",
744 744 node->vc_resource, buf);
745 745
746 746 return (buf);
747 747 }
748 748
749 749 /*
750 750 * Cache management routines, all cache management functions should be
751 751 * be called with cache_lock held.
752 752 */
753 753
754 754 /*
755 755 * cache_lookup() - Get a cache node for a resource.
756 756 * Call with cache lock held.
757 757 *
758 758 * This ensures that the cache is consistent with the system state and
759 759 * returns a pointer to the cache element corresponding to the resource.
760 760 */
761 761 static link_cache_t *
762 762 cache_lookup(rcm_handle_t *hd, char *rsrc, char options)
763 763 {
764 764 link_cache_t *node;
765 765
766 766 rcm_log_message(RCM_TRACE2, "VLAN: cache lookup(%s)\n", rsrc);
767 767
768 768 assert(MUTEX_HELD(&cache_lock));
769 769 if (options & CACHE_REFRESH) {
770 770 /* drop lock since update locks cache again */
771 771 (void) mutex_unlock(&cache_lock);
772 772 (void) cache_update(hd);
773 773 (void) mutex_lock(&cache_lock);
774 774 }
775 775
776 776 node = cache_head.vc_next;
777 777 for (; node != &cache_tail; node = node->vc_next) {
778 778 if (strcmp(rsrc, node->vc_resource) == 0) {
779 779 rcm_log_message(RCM_TRACE2,
780 780 "VLAN: cache lookup succeeded(%s)\n", rsrc);
781 781 return (node);
782 782 }
783 783 }
784 784 return (NULL);
785 785 }
786 786
787 787 /*
788 788 * node_free - Free a node from the cache
789 789 */
790 790 static void
791 791 node_free(link_cache_t *node)
792 792 {
793 793 dl_vlan_t *vlan, *next;
794 794
795 795 if (node != NULL) {
796 796 free(node->vc_resource);
797 797
798 798 /* free the VLAN list */
799 799 for (vlan = node->vc_vlan; vlan != NULL; vlan = next) {
800 800 next = vlan->dv_next;
801 801 free(vlan);
802 802 }
803 803 free(node);
804 804 }
805 805 }
806 806
807 807 /*
808 808 * cache_insert - Insert a resource node in cache
809 809 */
810 810 static void
811 811 cache_insert(link_cache_t *node)
812 812 {
813 813 assert(MUTEX_HELD(&cache_lock));
814 814
815 815 /* insert at the head for best performance */
816 816 node->vc_next = cache_head.vc_next;
817 817 node->vc_prev = &cache_head;
818 818
819 819 node->vc_next->vc_prev = node;
820 820 node->vc_prev->vc_next = node;
821 821 }
822 822
823 823 /*
824 824 * cache_remove() - Remove a resource node from cache.
825 825 */
826 826 static void
827 827 cache_remove(link_cache_t *node)
828 828 {
829 829 assert(MUTEX_HELD(&cache_lock));
830 830 node->vc_next->vc_prev = node->vc_prev;
831 831 node->vc_prev->vc_next = node->vc_next;
832 832 node->vc_next = NULL;
833 833 node->vc_prev = NULL;
834 834 }
835 835
836 836 typedef struct vlan_update_arg_s {
837 837 rcm_handle_t *hd;
838 838 int retval;
839 839 } vlan_update_arg_t;
840 840
841 841 /*
842 842 * vlan_update() - Update physical interface properties
843 843 */
844 844 static int
845 845 vlan_update(dladm_handle_t handle, datalink_id_t vlanid, void *arg)
846 846 {
847 847 vlan_update_arg_t *vlan_update_argp = arg;
848 848 rcm_handle_t *hd = vlan_update_argp->hd;
849 849 link_cache_t *node;
850 850 dl_vlan_t *vlan;
851 851 char *rsrc;
852 852 dladm_vlan_attr_t vlan_attr;
853 853 dladm_status_t status;
854 854 char errmsg[DLADM_STRSIZE];
855 855 boolean_t newnode = B_FALSE;
856 856 int ret = -1;
857 857
858 858 rcm_log_message(RCM_TRACE2, "VLAN: vlan_update(%u)\n", vlanid);
859 859
860 860 assert(MUTEX_HELD(&cache_lock));
861 861 status = dladm_vlan_info(handle, vlanid, &vlan_attr, DLADM_OPT_ACTIVE);
862 862 if (status != DLADM_STATUS_OK) {
863 863 rcm_log_message(RCM_TRACE1,
864 864 "VLAN: vlan_update() cannot get vlan information for "
865 865 "%u(%s)\n", vlanid, dladm_status2str(status, errmsg));
866 866 return (DLADM_WALK_CONTINUE);
867 867 }
868 868
869 869 rsrc = malloc(RCM_LINK_RESOURCE_MAX);
870 870 if (rsrc == NULL) {
871 871 rcm_log_message(RCM_ERROR, _("VLAN: malloc error(%s): %u\n"),
872 872 strerror(errno), vlanid);
873 873 goto done;
874 874 }
875 875
876 876 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
877 877 RCM_LINK_PREFIX, vlan_attr.dv_linkid);
878 878
879 879 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH);
880 880 if (node != NULL) {
881 881 rcm_log_message(RCM_DEBUG,
882 882 "VLAN: %s already registered (vlanid:%d)\n",
883 883 rsrc, vlan_attr.dv_vid);
884 884 free(rsrc);
885 885 } else {
886 886 rcm_log_message(RCM_DEBUG,
887 887 "VLAN: %s is a new resource (vlanid:%d)\n",
888 888 rsrc, vlan_attr.dv_vid);
889 889 if ((node = calloc(1, sizeof (link_cache_t))) == NULL) {
890 890 free(rsrc);
891 891 rcm_log_message(RCM_ERROR, _("VLAN: calloc: %s\n"),
892 892 strerror(errno));
893 893 goto done;
894 894 }
895 895
896 896 node->vc_resource = rsrc;
897 897 node->vc_vlan = NULL;
898 898 node->vc_linkid = vlan_attr.dv_linkid;
899 899 node->vc_state |= CACHE_NODE_NEW;
900 900 newnode = B_TRUE;
901 901 }
902 902
903 903 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
904 904 if (vlan->dv_vlanid == vlanid) {
905 905 vlan->dv_flags &= ~VLAN_STALE;
906 906 break;
907 907 }
908 908 }
909 909
910 910 if (vlan == NULL) {
911 911 if ((vlan = calloc(1, sizeof (dl_vlan_t))) == NULL) {
912 912 rcm_log_message(RCM_ERROR, _("VLAN: malloc: %s\n"),
913 913 strerror(errno));
914 914 if (newnode) {
915 915 free(rsrc);
916 916 free(node);
917 917 }
918 918 goto done;
919 919 }
920 920 vlan->dv_vlanid = vlanid;
921 921 vlan->dv_next = node->vc_vlan;
922 922 vlan->dv_prev = NULL;
923 923 if (node->vc_vlan != NULL)
924 924 node->vc_vlan->dv_prev = vlan;
925 925 node->vc_vlan = vlan;
926 926 }
927 927
928 928 node->vc_state &= ~CACHE_NODE_STALE;
929 929
930 930 if (newnode)
931 931 cache_insert(node);
932 932
933 933 rcm_log_message(RCM_TRACE3, "VLAN: vlan_update: succeeded(%u)\n",
934 934 vlanid);
935 935 ret = 0;
936 936 done:
937 937 vlan_update_argp->retval = ret;
938 938 return (ret == 0 ? DLADM_WALK_CONTINUE : DLADM_WALK_TERMINATE);
939 939 }
940 940
941 941 /*
942 942 * vlan_update_all() - Determine all VLAN links in the system
943 943 */
944 944 static int
945 945 vlan_update_all(rcm_handle_t *hd)
946 946 {
947 947 vlan_update_arg_t arg = {NULL, 0};
948 948
949 949 rcm_log_message(RCM_TRACE2, "VLAN: vlan_update_all\n");
950 950
951 951 assert(MUTEX_HELD(&cache_lock));
952 952 arg.hd = hd;
953 953 (void) dladm_walk_datalink_id(vlan_update, dld_handle, &arg,
954 954 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
955 955 return (arg.retval);
956 956 }
957 957
958 958 /*
959 959 * cache_update() - Update cache with latest interface info
960 960 */
961 961 static int
962 962 cache_update(rcm_handle_t *hd)
963 963 {
964 964 link_cache_t *node, *nnode;
965 965 dl_vlan_t *vlan;
966 966 int rv;
967 967
968 968 rcm_log_message(RCM_TRACE2, "VLAN: cache_update\n");
969 969
970 970 (void) mutex_lock(&cache_lock);
971 971
972 972 /* first we walk the entire cache, marking each entry stale */
973 973 node = cache_head.vc_next;
974 974 for (; node != &cache_tail; node = node->vc_next) {
975 975 node->vc_state |= CACHE_NODE_STALE;
976 976 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next)
977 977 vlan->dv_flags |= VLAN_STALE;
978 978 }
979 979
980 980 rv = vlan_update_all(hd);
981 981
982 982 /*
983 983 * Continue to delete all stale nodes from the cache even
984 984 * vlan_update_all() failed. Unregister link that are not offlined
985 985 * and still in cache
986 986 */
987 987 for (node = cache_head.vc_next; node != &cache_tail; node = nnode) {
988 988 dl_vlan_t *vlan, *next;
989 989
990 990 for (vlan = node->vc_vlan; vlan != NULL; vlan = next) {
991 991 next = vlan->dv_next;
992 992
993 993 /* clear stale VLANs */
994 994 if (vlan->dv_flags & VLAN_STALE) {
995 995 if (vlan->dv_prev != NULL)
996 996 vlan->dv_prev->dv_next = next;
997 997 else
998 998 node->vc_vlan = next;
999 999
1000 1000 if (next != NULL)
1001 1001 next->dv_prev = vlan->dv_prev;
1002 1002 free(vlan);
1003 1003 }
1004 1004 }
1005 1005
1006 1006 nnode = node->vc_next;
1007 1007 if (node->vc_state & CACHE_NODE_STALE) {
1008 1008 (void) rcm_unregister_interest(hd, node->vc_resource,
1009 1009 0);
1010 1010 rcm_log_message(RCM_DEBUG, "VLAN: unregistered %s\n",
1011 1011 node->vc_resource);
1012 1012 assert(node->vc_vlan == NULL);
1013 1013 cache_remove(node);
1014 1014 node_free(node);
1015 1015 continue;
1016 1016 }
1017 1017
1018 1018 if (!(node->vc_state & CACHE_NODE_NEW))
1019 1019 continue;
1020 1020
1021 1021 if (rcm_register_interest(hd, node->vc_resource, 0, NULL) !=
1022 1022 RCM_SUCCESS) {
1023 1023 rcm_log_message(RCM_ERROR,
1024 1024 _("VLAN: failed to register %s\n"),
1025 1025 node->vc_resource);
1026 1026 rv = -1;
1027 1027 } else {
1028 1028 rcm_log_message(RCM_DEBUG, "VLAN: registered %s\n",
1029 1029 node->vc_resource);
1030 1030 node->vc_state &= ~CACHE_NODE_NEW;
1031 1031 }
1032 1032 }
1033 1033
1034 1034 (void) mutex_unlock(&cache_lock);
1035 1035 return (rv);
1036 1036 }
1037 1037
1038 1038 /*
1039 1039 * cache_free() - Empty the cache
1040 1040 */
1041 1041 static void
1042 1042 cache_free()
1043 1043 {
1044 1044 link_cache_t *node;
1045 1045
1046 1046 rcm_log_message(RCM_TRACE2, "VLAN: cache_free\n");
1047 1047
1048 1048 (void) mutex_lock(&cache_lock);
1049 1049 node = cache_head.vc_next;
1050 1050 while (node != &cache_tail) {
1051 1051 cache_remove(node);
1052 1052 node_free(node);
1053 1053 node = cache_head.vc_next;
1054 1054 }
1055 1055 (void) mutex_unlock(&cache_lock);
1056 1056 }
1057 1057
1058 1058 /*
1059 1059 * vlan_log_err() - RCM error log wrapper
1060 1060 */
1061 1061 static void
1062 1062 vlan_log_err(datalink_id_t linkid, char **errorp, char *errmsg)
1063 1063 {
1064 1064 char link[MAXLINKNAMELEN];
1065 1065 char errstr[DLADM_STRSIZE];
1066 1066 dladm_status_t status;
1067 1067 int len;
1068 1068 const char *errfmt;
1069 1069 char *error;
1070 1070
1071 1071 link[0] = '\0';
1072 1072 if (linkid != DATALINK_INVALID_LINKID) {
1073 1073 char rsrc[RCM_LINK_RESOURCE_MAX];
1074 1074
1075 1075 (void) snprintf(rsrc, sizeof (rsrc), "%s/%u",
1076 1076 RCM_LINK_PREFIX, linkid);
1077 1077
1078 1078 rcm_log_message(RCM_ERROR, _("VLAN: %s(%s)\n"), errmsg, rsrc);
1079 1079 if ((status = dladm_datalink_id2info(dld_handle, linkid, NULL,
1080 1080 NULL, NULL, link, sizeof (link))) != DLADM_STATUS_OK) {
1081 1081 rcm_log_message(RCM_WARNING,
1082 1082 _("VLAN: cannot get link name for (%s) %s\n"),
1083 1083 rsrc, dladm_status2str(status, errstr));
1084 1084 }
1085 1085 } else {
1086 1086 rcm_log_message(RCM_ERROR, _("VLAN: %s\n"), errmsg);
1087 1087 }
1088 1088
1089 1089 errfmt = strlen(link) > 0 ? _("VLAN: %s(%s)") : _("VLAN: %s");
1090 1090 len = strlen(errfmt) + strlen(errmsg) + MAXLINKNAMELEN + 1;
1091 1091 if ((error = malloc(len)) != NULL) {
1092 1092 if (strlen(link) > 0)
1093 1093 (void) snprintf(error, len, errfmt, errmsg, link);
1094 1094 else
1095 1095 (void) snprintf(error, len, errfmt, errmsg);
1096 1096 }
1097 1097
1098 1098 if (errorp != NULL)
1099 1099 *errorp = error;
1100 1100 }
1101 1101
1102 1102 /*
1103 1103 * vlan_consumer_online()
1104 1104 *
1105 1105 * Notify online to VLAN consumers.
1106 1106 */
1107 1107 /* ARGSUSED */
1108 1108 static void
1109 1109 vlan_consumer_online(rcm_handle_t *hd, link_cache_t *node, char **errorp,
1110 1110 uint_t flags, rcm_info_t **info)
1111 1111 {
1112 1112 dl_vlan_t *vlan;
1113 1113 char rsrc[RCM_LINK_RESOURCE_MAX];
1114 1114
1115 1115 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_online (%s)\n",
1116 1116 node->vc_resource);
1117 1117
1118 1118 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
1119 1119 if (!(vlan->dv_flags & VLAN_CONSUMER_OFFLINED))
1120 1120 continue;
1121 1121
1122 1122 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
1123 1123 RCM_LINK_PREFIX, vlan->dv_vlanid);
1124 1124
1125 1125 if (rcm_notify_online(hd, rsrc, flags, info) == RCM_SUCCESS)
1126 1126 vlan->dv_flags &= ~VLAN_CONSUMER_OFFLINED;
1127 1127 }
1128 1128
1129 1129 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_online done\n");
1130 1130 }
1131 1131
1132 1132 /*
1133 1133 * vlan_consumer_offline()
1134 1134 *
1135 1135 * Offline VLAN consumers.
1136 1136 */
1137 1137 static int
1138 1138 vlan_consumer_offline(rcm_handle_t *hd, link_cache_t *node, char **errorp,
1139 1139 uint_t flags, rcm_info_t **info)
1140 1140 {
1141 1141 dl_vlan_t *vlan;
1142 1142 char rsrc[RCM_LINK_RESOURCE_MAX];
1143 1143 int ret = RCM_SUCCESS;
1144 1144
1145 1145 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_offline (%s)\n",
1146 1146 node->vc_resource);
1147 1147
1148 1148 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
1149 1149 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u",
1150 1150 RCM_LINK_PREFIX, vlan->dv_vlanid);
1151 1151
1152 1152 ret = rcm_request_offline(hd, rsrc, flags, info);
1153 1153 if (ret != RCM_SUCCESS)
1154 1154 break;
1155 1155
1156 1156 vlan->dv_flags |= VLAN_CONSUMER_OFFLINED;
1157 1157 }
1158 1158
1159 1159 if (vlan != NULL)
1160 1160 vlan_consumer_online(hd, node, errorp, flags, info);
1161 1161
1162 1162 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_offline done\n");
1163 1163 return (ret);
1164 1164 }
1165 1165
1166 1166 /*
1167 1167 * Send RCM_RESOURCE_LINK_NEW events to other modules about new VLANs.
1168 1168 * Return 0 on success, -1 on failure.
1169 1169 */
1170 1170 static int
1171 1171 vlan_notify_new_vlan(rcm_handle_t *hd, char *rsrc)
1172 1172 {
1173 1173 link_cache_t *node;
1174 1174 dl_vlan_t *vlan;
1175 1175 nvlist_t *nvl = NULL;
1176 1176 uint64_t id;
1177 1177 int ret = -1;
1178 1178
1179 1179 rcm_log_message(RCM_TRACE2, "VLAN: vlan_notify_new_vlan (%s)\n", rsrc);
1180 1180
1181 1181 (void) mutex_lock(&cache_lock);
1182 1182 if ((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) == NULL) {
1183 1183 (void) mutex_unlock(&cache_lock);
1184 1184 return (0);
1185 1185 }
1186 1186
1187 1187 if (nvlist_alloc(&nvl, 0, 0) != 0) {
1188 1188 (void) mutex_unlock(&cache_lock);
1189 1189 rcm_log_message(RCM_WARNING,
1190 1190 _("VLAN: failed to allocate nvlist\n"));
1191 1191 goto done;
1192 1192 }
1193 1193
1194 1194 for (vlan = node->vc_vlan; vlan != NULL; vlan = vlan->dv_next) {
1195 1195 rcm_log_message(RCM_TRACE2,
1196 1196 "VLAN: vlan_notify_new_vlan add (%u)\n",
1197 1197 vlan->dv_vlanid);
1198 1198
1199 1199 id = vlan->dv_vlanid;
1200 1200 if (nvlist_add_uint64(nvl, RCM_NV_LINKID, id) != 0) {
1201 1201 rcm_log_message(RCM_ERROR,
1202 1202 _("VLAN: failed to construct nvlist\n"));
1203 1203 (void) mutex_unlock(&cache_lock);
1204 1204 goto done;
1205 1205 }
1206 1206 }
1207 1207 (void) mutex_unlock(&cache_lock);
1208 1208
↓ open down ↓ |
1208 lines elided |
↑ open up ↑ |
1209 1209 if (rcm_notify_event(hd, RCM_RESOURCE_LINK_NEW, 0, nvl, NULL) !=
1210 1210 RCM_SUCCESS) {
1211 1211 rcm_log_message(RCM_ERROR,
1212 1212 _("VLAN: failed to notify %s event for %s\n"),
1213 1213 RCM_RESOURCE_LINK_NEW, node->vc_resource);
1214 1214 goto done;
1215 1215 }
1216 1216
1217 1217 ret = 0;
1218 1218 done:
1219 - if (nvl != NULL)
1220 - nvlist_free(nvl);
1219 + nvlist_free(nvl);
1221 1220 return (ret);
1222 1221 }
1223 1222
1224 1223 /*
1225 1224 * vlan_consumer_notify() - Notify consumers of VLANs coming back online.
1226 1225 */
1227 1226 static int
1228 1227 vlan_consumer_notify(rcm_handle_t *hd, datalink_id_t linkid, char **errorp,
1229 1228 uint_t flags, rcm_info_t **info)
1230 1229 {
1231 1230 char rsrc[RCM_LINK_RESOURCE_MAX];
1232 1231 link_cache_t *node;
1233 1232
1234 1233 /* Check for the interface in the cache */
1235 1234 (void) snprintf(rsrc, RCM_LINK_RESOURCE_MAX, "%s/%u", RCM_LINK_PREFIX,
1236 1235 linkid);
1237 1236
1238 1237 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_notify(%s)\n", rsrc);
1239 1238
1240 1239 /*
1241 1240 * Inform IP consumers of the new link.
1242 1241 */
1243 1242 if (vlan_notify_new_vlan(hd, rsrc) != 0) {
1244 1243 (void) mutex_lock(&cache_lock);
1245 1244 if ((node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH)) != NULL) {
1246 1245 (void) vlan_offline_vlan(node, VLAN_STALE,
1247 1246 CACHE_NODE_STALE);
1248 1247 }
1249 1248 (void) mutex_unlock(&cache_lock);
1250 1249 rcm_log_message(RCM_TRACE2,
1251 1250 "VLAN: vlan_notify_new_vlan failed(%s)\n", rsrc);
1252 1251 return (-1);
1253 1252 }
1254 1253
1255 1254 rcm_log_message(RCM_TRACE2, "VLAN: vlan_consumer_notify succeeded\n");
1256 1255 return (0);
1257 1256 }
1258 1257
1259 1258 typedef struct vlan_up_arg_s {
1260 1259 datalink_id_t linkid;
1261 1260 int retval;
1262 1261 } vlan_up_arg_t;
1263 1262
1264 1263 static int
1265 1264 vlan_up(dladm_handle_t handle, datalink_id_t vlanid, void *arg)
1266 1265 {
1267 1266 vlan_up_arg_t *vlan_up_argp = arg;
1268 1267 dladm_status_t status;
1269 1268 dladm_vlan_attr_t vlan_attr;
1270 1269 char errmsg[DLADM_STRSIZE];
1271 1270
1272 1271 status = dladm_vlan_info(handle, vlanid, &vlan_attr, DLADM_OPT_PERSIST);
1273 1272 if (status != DLADM_STATUS_OK) {
1274 1273 rcm_log_message(RCM_TRACE1,
1275 1274 "VLAN: vlan_up(): cannot get information for VLAN %u "
1276 1275 "(%s)\n", vlanid, dladm_status2str(status, errmsg));
1277 1276 return (DLADM_WALK_CONTINUE);
1278 1277 }
1279 1278
1280 1279 if (vlan_attr.dv_linkid != vlan_up_argp->linkid)
1281 1280 return (DLADM_WALK_CONTINUE);
1282 1281
1283 1282 rcm_log_message(RCM_TRACE3, "VLAN: vlan_up(%u)\n", vlanid);
1284 1283 if ((status = dladm_vlan_up(handle, vlanid)) == DLADM_STATUS_OK)
1285 1284 return (DLADM_WALK_CONTINUE);
1286 1285
1287 1286 /*
1288 1287 * Prompt the warning message and continue to UP other VLANs.
1289 1288 */
1290 1289 rcm_log_message(RCM_WARNING,
1291 1290 _("VLAN: VLAN up failed (%u): %s\n"),
1292 1291 vlanid, dladm_status2str(status, errmsg));
1293 1292
1294 1293 vlan_up_argp->retval = -1;
1295 1294 return (DLADM_WALK_CONTINUE);
1296 1295 }
1297 1296
1298 1297 /*
1299 1298 * vlan_configure() - Configure VLANs over a physical link after it attaches
1300 1299 */
1301 1300 static int
1302 1301 vlan_configure(rcm_handle_t *hd, datalink_id_t linkid)
1303 1302 {
1304 1303 char rsrc[RCM_LINK_RESOURCE_MAX];
1305 1304 link_cache_t *node;
1306 1305 vlan_up_arg_t arg = {DATALINK_INVALID_LINKID, 0};
1307 1306
1308 1307 /* Check for the VLANs in the cache */
1309 1308 (void) snprintf(rsrc, sizeof (rsrc), "%s/%u", RCM_LINK_PREFIX, linkid);
1310 1309
1311 1310 rcm_log_message(RCM_TRACE2, "VLAN: vlan_configure(%s)\n", rsrc);
1312 1311
1313 1312 /* Check if the link is new or was previously offlined */
1314 1313 (void) mutex_lock(&cache_lock);
1315 1314 if (((node = cache_lookup(hd, rsrc, CACHE_REFRESH)) != NULL) &&
1316 1315 (!(node->vc_state & CACHE_NODE_OFFLINED))) {
1317 1316 rcm_log_message(RCM_TRACE2,
1318 1317 "VLAN: Skipping configured interface(%s)\n", rsrc);
1319 1318 (void) mutex_unlock(&cache_lock);
1320 1319 return (0);
1321 1320 }
1322 1321 (void) mutex_unlock(&cache_lock);
1323 1322
1324 1323 arg.linkid = linkid;
1325 1324 (void) dladm_walk_datalink_id(vlan_up, dld_handle, &arg,
1326 1325 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
1327 1326
1328 1327 if (arg.retval == 0) {
1329 1328 rcm_log_message(RCM_TRACE2,
1330 1329 "VLAN: vlan_configure succeeded(%s)\n", rsrc);
1331 1330 }
1332 1331 return (arg.retval);
1333 1332 }
↓ open down ↓ |
103 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX