VirtualBox

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

Last change on this file since 79846 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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