VirtualBox

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

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

HostDrivers/solaris: LogFlow->Log for debug purposes.

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

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