VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetAdp/solaris/VBoxNetAdp-solaris.c@ 48030

Last change on this file since 48030 was 41700, checked in by vboxsync, 13 years ago

Solaris: license header update for kernel bits.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 19.5 KB
Line 
1/* $Id: VBoxNetAdp-solaris.c 41700 2012-06-14 10:12:57Z vboxsync $ */
2/** @file
3 * VBoxNetAdapter - Network Adapter Driver (Host), Solaris Specific Code.
4 */
5
6/*
7 * Copyright (C) 2009-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#define LOG_GROUP LOG_GROUP_NET_ADP_DRV
31#ifdef DEBUG_ramshankar
32# define LOG_ENABLED
33# define LOG_INSTANCE RTLogRelDefaultInstance()
34#endif
35#include <VBox/log.h>
36#include <VBox/err.h>
37#include <VBox/version.h>
38#include <iprt/assert.h>
39#include <iprt/semaphore.h>
40#include <iprt/initterm.h>
41#include <iprt/assert.h>
42#include <iprt/mem.h>
43#include <iprt/rand.h>
44
45#include <sys/types.h>
46#include <sys/dlpi.h>
47#include <sys/types.h>
48#include <sys/param.h>
49#include <sys/stat.h>
50#include <sys/stream.h>
51#include <sys/stropts.h>
52#include <sys/strsun.h>
53#include <sys/modctl.h>
54#include <sys/ddi.h>
55#include <sys/sunddi.h>
56#include <sys/sunldi.h>
57#include <sys/gld.h>
58
59#include "../VBoxNetAdpInternal.h"
60
61/*******************************************************************************
62* Defined Constants And Macros *
63*******************************************************************************/
64#define DEVICE_NAME "vboxnet"
65/** The module descriptions as seen in 'modinfo'. */
66#define DEVICE_DESC_DRV "VirtualBox NetAdp"
67#define VBOXNETADP_MTU 1500
68
69
70/*******************************************************************************
71* Internal Functions *
72*******************************************************************************/
73static int VBoxNetAdpSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd);
74static int VBoxNetAdpSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd);
75
76/**
77 * Streams: module info.
78 */
79static struct module_info g_VBoxNetAdpSolarisModInfo =
80{
81 0x0dd, /* module id */
82 DEVICE_NAME,
83 0, /* min. packet size */
84 INFPSZ, /* max. packet size */
85 0, /* hi-water mark */
86 0 /* lo-water mark */
87};
88
89/**
90 * Streams: read queue hooks.
91 */
92static struct qinit g_VBoxNetAdpSolarisReadQ =
93{
94 NULL, /* read */
95 gld_rsrv,
96 gld_open,
97 gld_close,
98 NULL, /* admin (reserved) */
99 &g_VBoxNetAdpSolarisModInfo,
100 NULL /* module stats */
101};
102
103/**
104 * Streams: write queue hooks.
105 */
106static struct qinit g_VBoxNetAdpSolarisWriteQ =
107{
108 gld_wput,
109 gld_wsrv,
110 NULL, /* open */
111 NULL, /* close */
112 NULL, /* admin (reserved) */
113 &g_VBoxNetAdpSolarisModInfo,
114 NULL /* module stats */
115};
116
117/**
118 * Streams: IO stream tab.
119 */
120static struct streamtab g_VBoxNetAdpSolarisStreamTab =
121{
122 &g_VBoxNetAdpSolarisReadQ,
123 &g_VBoxNetAdpSolarisWriteQ,
124 NULL, /* muxread init */
125 NULL /* muxwrite init */
126};
127
128/**
129 * cb_ops: driver char/block entry points
130 */
131static struct cb_ops g_VBoxNetAdpSolarisCbOps =
132{
133 nulldev, /* cb open */
134 nulldev, /* cb close */
135 nodev, /* b strategy */
136 nodev, /* b dump */
137 nodev, /* b print */
138 nodev, /* cb read */
139 nodev, /* cb write */
140 nodev, /* cb ioctl */
141 nodev, /* c devmap */
142 nodev, /* c mmap */
143 nodev, /* c segmap */
144 nochpoll, /* c poll */
145 ddi_prop_op, /* property ops */
146 &g_VBoxNetAdpSolarisStreamTab,
147 D_MP, /* compat. flag */
148 CB_REV /* revision */
149};
150
151/**
152 * dev_ops: driver entry/exit and other ops.
153 */
154static struct dev_ops g_VBoxNetAdpSolarisDevOps =
155{
156 DEVO_REV, /* driver build revision */
157 0, /* ref count */
158 gld_getinfo,
159 nulldev, /* identify */
160 nulldev, /* probe */
161 VBoxNetAdpSolarisAttach,
162 VBoxNetAdpSolarisDetach,
163 nodev, /* reset */
164 &g_VBoxNetAdpSolarisCbOps,
165 (struct bus_ops *)0,
166 nodev /* power */
167};
168
169/**
170 * modldrv: export driver specifics to kernel
171 */
172static struct modldrv g_VBoxNetAdpSolarisDriver =
173{
174 &mod_driverops, /* extern from kernel */
175 DEVICE_DESC_DRV " " VBOX_VERSION_STRING "r" RT_XSTR(VBOX_SVN_REV),
176 &g_VBoxNetAdpSolarisDevOps
177};
178
179/**
180 * modlinkage: export install/remove/info to the kernel
181 */
182static struct modlinkage g_VBoxNetAdpSolarisModLinkage =
183{
184 MODREV_1, /* loadable module system revision */
185 {
186 &g_VBoxNetAdpSolarisDriver, /* adapter streams driver framework */
187 NULL /* terminate array of linkage structures */
188 }
189};
190
191
192/*******************************************************************************
193* Global Variables *
194*******************************************************************************/
195/** The default ethernet broadcast address */
196static uchar_t achBroadcastAddr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
197
198/**
199 * vboxnetadp_state_t: per-instance data
200 */
201typedef struct vboxnetadp_state_t
202{
203 dev_info_t *pDip; /* device info. */
204 RTMAC FactoryMac; /* default 'factory' MAC address */
205 RTMAC CurrentMac; /* current MAC address */
206} vboxnetadp_state_t;
207
208
209/*******************************************************************************
210* Internal Functions *
211*******************************************************************************/
212static int vboxNetAdpSolarisGenerateMac(PRTMAC pMac);
213static int vboxNetAdpSolarisSetMacAddress(gld_mac_info_t *pMacInfo, unsigned char *pszMacAddr);
214static int vboxNetAdpSolarisSend(gld_mac_info_t *pMacInfo, mblk_t *pMsg);
215static int vboxNetAdpSolarisStub(gld_mac_info_t *pMacInfo);
216static int vboxNetAdpSolarisSetPromisc(gld_mac_info_t *pMacInfo, int fPromisc);
217static int vboxNetAdpSolarisSetMulticast(gld_mac_info_t *pMacInfo, unsigned char *pMulticastAddr, int fMulticast);
218static int vboxNetAdpSolarisGetStats(gld_mac_info_t *pMacInfo, struct gld_stats *pStats);
219
220
221/**
222 * Kernel entry points
223 */
224int _init(void)
225{
226 LogFunc((DEVICE_NAME ":_init\n"));
227
228 /*
229 * Prevent module autounloading.
230 */
231 modctl_t *pModCtl = mod_getctl(&g_VBoxNetAdpSolarisModLinkage);
232 if (pModCtl)
233 pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
234 else
235 LogRel((DEVICE_NAME ":failed to disable autounloading!\n"));
236
237 /*
238 * Initialize IPRT.
239 */
240 int rc = RTR0Init(0);
241 if (RT_SUCCESS(rc))
242 {
243 rc = mod_install(&g_VBoxNetAdpSolarisModLinkage);
244 if (!rc)
245 return rc;
246
247 LogRel((DEVICE_NAME ":mod_install failed. rc=%d\n", rc));
248 RTR0Term();
249 }
250 else
251 LogRel((DEVICE_NAME ":failed to initialize IPRT (rc=%d)\n", rc));
252
253 return RTErrConvertToErrno(rc);
254}
255
256
257int _fini(void)
258{
259 LogFunc((DEVICE_NAME ":_fini\n"));
260
261 /*
262 * Undo the work done during start (in reverse order).
263 */
264 RTR0Term();
265
266 return mod_remove(&g_VBoxNetAdpSolarisModLinkage);
267}
268
269
270int _info(struct modinfo *pModInfo)
271{
272 LogFunc((DEVICE_NAME ":_info\n"));
273
274 int rc = mod_info(&g_VBoxNetAdpSolarisModLinkage, pModInfo);
275
276 Log((DEVICE_NAME ":_info returns %d\n", rc));
277 return rc;
278}
279
280
281/**
282 * Attach entry point, to attach a device to the system or resume it.
283 *
284 * @param pDip The module structure instance.
285 * @param enmCmd Operation type (attach/resume).
286 *
287 * @returns corresponding solaris error code.
288 */
289static int VBoxNetAdpSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd)
290{
291 LogFunc((DEVICE_NAME ":VBoxNetAdpSolarisAttach pDip=%p enmCmd=%d\n", pDip, enmCmd));
292
293 int rc = -1;
294 switch (enmCmd)
295 {
296 case DDI_ATTACH:
297 {
298 gld_mac_info_t *pMacInfo = gld_mac_alloc(pDip);
299 if (pMacInfo)
300 {
301 vboxnetadp_state_t *pState = RTMemAllocZ(sizeof(vboxnetadp_state_t));
302 if (pState)
303 {
304 pState->pDip = pDip;
305
306 /*
307 * Setup GLD MAC layer registration info.
308 */
309 pMacInfo->gldm_reset = vboxNetAdpSolarisStub;
310 pMacInfo->gldm_start = vboxNetAdpSolarisStub;
311 pMacInfo->gldm_stop = vboxNetAdpSolarisStub;
312 pMacInfo->gldm_set_mac_addr = vboxNetAdpSolarisSetMacAddress;
313 pMacInfo->gldm_set_multicast = vboxNetAdpSolarisSetMulticast;
314 pMacInfo->gldm_set_promiscuous = vboxNetAdpSolarisSetPromisc;
315 pMacInfo->gldm_send = vboxNetAdpSolarisSend;
316 pMacInfo->gldm_intr = NULL;
317 pMacInfo->gldm_get_stats = vboxNetAdpSolarisGetStats;
318 pMacInfo->gldm_ioctl = NULL;
319 pMacInfo->gldm_ident = DEVICE_NAME;
320 pMacInfo->gldm_type = DL_ETHER;
321 pMacInfo->gldm_minpkt = 0;
322 pMacInfo->gldm_maxpkt = VBOXNETADP_MTU;
323 pMacInfo->gldm_capabilities = GLD_CAP_LINKSTATE;
324 AssertCompile(sizeof(RTMAC) == ETHERADDRL);
325
326 pMacInfo->gldm_addrlen = ETHERADDRL;
327 pMacInfo->gldm_saplen = -2;
328 pMacInfo->gldm_broadcast_addr = achBroadcastAddr;
329 pMacInfo->gldm_ppa = ddi_get_instance(pState->pDip);
330 pMacInfo->gldm_devinfo = pState->pDip;
331 pMacInfo->gldm_private = (caddr_t)pState;
332
333 /*
334 * We use a semi-random MAC addresses similar to a guest NIC's MAC address
335 * as the default factory address of the interface.
336 */
337 rc = vboxNetAdpSolarisGenerateMac(&pState->FactoryMac);
338 if (RT_SUCCESS(rc))
339 {
340 bcopy(&pState->FactoryMac, &pState->CurrentMac, sizeof(RTMAC));
341 pMacInfo->gldm_vendor_addr = (unsigned char *)&pState->FactoryMac;
342
343 /*
344 * Now try registering our GLD with the MAC layer.
345 * Registration can fail on some S10 versions when the MTU size is more than 1500.
346 * When we implement jumbo frames we should probably retry with MTU 1500 for S10.
347 */
348 rc = gld_register(pDip, (char *)ddi_driver_name(pDip), pMacInfo);
349 if (rc == DDI_SUCCESS)
350 {
351 ddi_report_dev(pDip);
352 gld_linkstate(pMacInfo, GLD_LINKSTATE_UP);
353 return DDI_SUCCESS;
354 }
355 else
356 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisAttach failed to register GLD. rc=%d\n", rc));
357 }
358 else
359 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisAttach failed to generate mac address.rc=%d\n"));
360
361 RTMemFree(pState);
362 }
363 else
364 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisAttach failed to alloc state.\n"));
365
366 gld_mac_free(pMacInfo);
367 }
368 else
369 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisAttach failed to alloc mac structure.\n"));
370 return DDI_FAILURE;
371 }
372
373 case DDI_RESUME:
374 {
375 /* Nothing to do here... */
376 return DDI_SUCCESS;
377 }
378
379 /* case DDI_PM_RESUME: */
380 default:
381 return DDI_FAILURE;
382 }
383}
384
385
386/**
387 * Detach entry point, to detach a device to the system or suspend it.
388 *
389 * @param pDip The module structure instance.
390 * @param enmCmd Operation type (detach/suspend).
391 *
392 * @returns corresponding solaris error code.
393 */
394static int VBoxNetAdpSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)
395{
396 LogFunc((DEVICE_NAME ":VBoxNetAdpSolarisDetach pDip=%p enmCmd=%d\n", pDip, enmCmd));
397
398 switch (enmCmd)
399 {
400 case DDI_DETACH:
401 {
402 /*
403 * Unregister and clean up.
404 */
405 gld_mac_info_t *pMacInfo = ddi_get_driver_private(pDip);
406 if (pMacInfo)
407 {
408 vboxnetadp_state_t *pState = (vboxnetadp_state_t *)pMacInfo->gldm_private;
409 if (pState)
410 {
411 gld_linkstate(pMacInfo, GLD_LINKSTATE_DOWN);
412 int rc = gld_unregister(pMacInfo);
413 if (rc == DDI_SUCCESS)
414 {
415 gld_mac_free(pMacInfo);
416 RTMemFree(pState);
417 return DDI_SUCCESS;
418 }
419 else
420 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisDetach failed to unregister GLD from MAC layer.rc=%d\n", rc));
421 }
422 else
423 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisDetach failed to get internal state.\n"));
424 }
425 else
426 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisDetach failed to get driver private GLD data.\n"));
427
428 return DDI_FAILURE;
429 }
430
431 case DDI_RESUME:
432 {
433 /* Nothing to do here... */
434 return DDI_SUCCESS;
435 }
436
437 /* case DDI_SUSPEND: */
438 /* case DDI_HOTPLUG_DETACH: */
439 default:
440 return DDI_FAILURE;
441 }
442}
443
444
445static int vboxNetAdpSolarisGenerateMac(PRTMAC pMac)
446{
447 pMac->au8[0] = 0x08;
448 pMac->au8[1] = 0x00;
449 pMac->au8[2] = 0x27;
450 RTRandBytes(&pMac->au8[3], 3);
451 Log((DEVICE_NAME ":VBoxNetAdpSolarisGenerateMac Generated %.*Rhxs\n", sizeof(RTMAC), &pMac));
452 return VINF_SUCCESS;
453}
454
455
456static int vboxNetAdpSolarisSetMacAddress(gld_mac_info_t *pMacInfo, unsigned char *pszMacAddr)
457{
458 vboxnetadp_state_t *pState = (vboxnetadp_state_t *)pMacInfo->gldm_private;
459 if (pState)
460 {
461 bcopy(pszMacAddr, &pState->CurrentMac, sizeof(RTMAC));
462 Log((DEVICE_NAME ":vboxNetAdpSolarisSetMacAddress updated MAC %.*Rhxs\n", sizeof(RTMAC), &pState->CurrentMac));
463 return GLD_SUCCESS;
464 }
465 else
466 LogRel((DEVICE_NAME ":vboxNetAdpSolarisSetMacAddress failed to get internal state.\n"));
467 return GLD_FAILURE;
468}
469
470
471static int vboxNetAdpSolarisSend(gld_mac_info_t *pMacInfo, mblk_t *pMsg)
472{
473 while (pMsg)
474 {
475 mblk_t *pMsgNext = pMsg->b_cont;
476 pMsg->b_cont = NULL;
477 freemsg(pMsg);
478 pMsg = pMsgNext;
479 }
480 return GLD_SUCCESS;
481}
482
483
484static int vboxNetAdpSolarisStub(gld_mac_info_t *pMacInfo)
485{
486 return GLD_SUCCESS;
487}
488
489
490static int vboxNetAdpSolarisSetMulticast(gld_mac_info_t *pMacInfo, unsigned char *pMulticastAddr, int fMulticast)
491{
492 return GLD_SUCCESS;
493}
494
495
496static int vboxNetAdpSolarisSetPromisc(gld_mac_info_t *pMacInfo, int fPromisc)
497{
498 /* Host requesting promiscuous intnet connection... */
499 return GLD_SUCCESS;
500}
501
502
503static int vboxNetAdpSolarisGetStats(gld_mac_info_t *pMacInfo, struct gld_stats *pStats)
504{
505 /*
506 * For now fake up stats. Stats like duplex and speed are better set as they
507 * are used in utilities like dladm. Link state capabilities are critical
508 * as they are used by ipadm while trying to restore persistent interface configs.
509 */
510 vboxnetadp_state_t *pState = (vboxnetadp_state_t *)pMacInfo->gldm_private;
511 if (pState)
512 {
513 pStats->glds_speed = 1000000000ULL; /* Bits/sec. */
514 pStats->glds_media = GLDM_UNKNOWN; /* Media/Connector Type */
515 pStats->glds_intr = 0; /* Interrupt count */
516 pStats->glds_norcvbuf = 0; /* Recv. discards */
517 pStats->glds_errxmt = 0; /* Xmit errors */
518 pStats->glds_errrcv = 0; /* Recv. errors */
519 pStats->glds_missed = 0; /* Pkt Drops on Recv. */
520 pStats->glds_underflow = 0; /* Buffer underflows */
521 pStats->glds_overflow = 0; /* Buffer overflows */
522
523 /* Ether */
524 pStats->glds_frame = 0; /* Align errors */
525 pStats->glds_crc = 0; /* CRC errors */
526 pStats->glds_duplex = GLD_DUPLEX_FULL; /* Link duplex state */
527 pStats->glds_nocarrier = 0; /* Carrier sense errors */
528 pStats->glds_collisions = 0; /* Xmit Collisions */
529 pStats->glds_excoll = 0; /* Frame discard due to excess collisions */
530 pStats->glds_xmtlatecoll = 0; /* Late collisions */
531 pStats->glds_defer = 0; /* Deferred Xmits */
532 pStats->glds_dot3_first_coll = 0; /* Single collision frames */
533 pStats->glds_dot3_multi_coll = 0; /* Multiple collision frames */
534 pStats->glds_dot3_sqe_error = 0; /* SQE errors */
535 pStats->glds_dot3_mac_xmt_error = 0; /* MAC Xmit errors */
536 pStats->glds_dot3_mac_rcv_error = 0; /* Mac Recv. errors */
537 pStats->glds_dot3_frame_too_long = 0; /* Frame too long errors */
538 pStats->glds_short = 0; /* Runt frames */
539
540 pStats->glds_noxmtbuf = 0; /* Xmit Buf errors */
541 pStats->glds_xmtretry = 0; /* Xmit retries */
542 pStats->glds_multixmt = 0; /* Multicast Xmits */
543 pStats->glds_multircv = 0; /* Multicast Recvs. */
544 pStats->glds_brdcstxmt = 0; /* Broadcast Xmits*/
545 pStats->glds_brdcstrcv = 0; /* Broadcast Recvs. */
546
547 return GLD_SUCCESS;
548 }
549 else
550 LogRel((DEVICE_NAME ":vboxNetAdpSolarisGetStats failed to get internal state.\n"));
551 return GLD_FAILURE;
552}
553
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette