VirtualBox

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

Last change on this file since 37786 was 37786, checked in by vboxsync, 14 years ago

spaces.

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