VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 7 weeks ago

Copyright year updates by scm.

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