Browse Source

[netdevice] Add the concept of a network upper-layer driver

Add the concept of a network upper-layer driver, which can create
arbitrary devices on top of network devices.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 14 years ago
parent
commit
ca4df90a63
2 changed files with 114 additions and 35 deletions
  1. 39
    21
      src/include/ipxe/netdevice.h
  2. 75
    14
      src/net/netdevice.c

+ 39
- 21
src/include/ipxe/netdevice.h View File

@@ -344,6 +344,34 @@ struct net_device {
344 344
 /** Declare a network-layer protocol */
345 345
 #define __net_protocol __table_entry ( NET_PROTOCOLS, 01 )
346 346
 
347
+/** A network upper-layer driver */
348
+struct net_driver {
349
+	/** Name */
350
+	const char *name;
351
+	/** Probe device
352
+	 *
353
+	 * @v netdev		Network device
354
+	 * @ret rc		Return status code
355
+	 */
356
+	int ( * probe ) ( struct net_device *netdev );
357
+	/** Notify of device or link state change
358
+	 *
359
+	 * @v netdev		Network device
360
+	 */
361
+	void ( * notify ) ( struct net_device *netdev );
362
+	/** Remove device
363
+	 *
364
+	 * @v netdev		Network device
365
+	 */
366
+	void ( * remove ) ( struct net_device *netdev );
367
+};
368
+
369
+/** Network driver table */
370
+#define NET_DRIVERS __table ( struct net_driver, "net_drivers" )
371
+
372
+/** Declare a network driver */
373
+#define __net_driver __table_entry ( NET_DRIVERS, 01 )
374
+
347 375
 extern struct list_head net_devices;
348 376
 extern struct net_device_operations null_netdev_operations;
349 377
 extern struct settings_operations netdev_settings_operations;
@@ -451,27 +479,6 @@ netdev_settings_init ( struct net_device *netdev ) {
451 479
 	netdev->settings.settings.op = &netdev_settings_operations;
452 480
 }
453 481
 
454
-/**
455
- * Mark network device as having link up
456
- *
457
- * @v netdev		Network device
458
- */
459
-static inline __attribute__ (( always_inline )) void
460
-netdev_link_up ( struct net_device *netdev ) {
461
-	netdev->link_rc = 0;
462
-}
463
-
464
-/**
465
- * Mark network device as having link down due to a specific error
466
- *
467
- * @v netdev		Network device
468
- * @v rc		Link status code
469
- */
470
-static inline __attribute__ (( always_inline )) void
471
-netdev_link_err ( struct net_device *netdev, int rc ) {
472
-	netdev->link_rc = rc;
473
-}
474
-
475 482
 /**
476 483
  * Check link state of network device
477 484
  *
@@ -505,6 +512,7 @@ netdev_irq_enabled ( struct net_device *netdev ) {
505 512
 	return ( netdev->state & NETDEV_IRQ_ENABLED );
506 513
 }
507 514
 
515
+extern void netdev_link_err ( struct net_device *netdev, int rc );
508 516
 extern void netdev_link_down ( struct net_device *netdev );
509 517
 extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
510 518
 extern void netdev_tx_complete_err ( struct net_device *netdev,
@@ -554,4 +562,14 @@ static inline void netdev_tx_complete_next ( struct net_device *netdev ) {
554 562
 	netdev_tx_complete_next_err ( netdev, 0 );
555 563
 }
556 564
 
565
+/**
566
+ * Mark network device as having link up
567
+ *
568
+ * @v netdev		Network device
569
+ */
570
+static inline __attribute__ (( always_inline )) void
571
+netdev_link_up ( struct net_device *netdev ) {
572
+	netdev_link_err ( netdev, 0 );
573
+}
574
+
557 575
 #endif /* _IPXE_NETDEVICE_H */

+ 75
- 14
src/net/netdevice.c View File

@@ -56,6 +56,39 @@ struct errortab netdev_errors[] __errortab = {
56 56
 	__einfo_errortab ( EINFO_EUNKNOWN_LINK_STATUS ),
57 57
 };
58 58
 
59
+/**
60
+ * Notify drivers of network device or link state change
61
+ *
62
+ * @v netdev		Network device
63
+ */
64
+static void netdev_notify ( struct net_device *netdev ) {
65
+	struct net_driver *driver;
66
+
67
+	for_each_table_entry ( driver, NET_DRIVERS )
68
+		driver->notify ( netdev );
69
+}
70
+
71
+/**
72
+ * Mark network device as having a specific link state
73
+ *
74
+ * @v netdev		Network device
75
+ * @v rc		Link status code
76
+ */
77
+void netdev_link_err ( struct net_device *netdev, int rc ) {
78
+
79
+	/* Record link state */
80
+	netdev->link_rc = rc;
81
+	if ( netdev->link_rc == 0 ) {
82
+		DBGC ( netdev, "NETDEV %p link is up\n", netdev );
83
+	} else {
84
+		DBGC ( netdev, "NETDEV %p link is down: %s\n",
85
+		       netdev, strerror ( netdev->link_rc ) );
86
+	}
87
+
88
+	/* Notify drivers of link state change */
89
+	netdev_notify ( netdev );
90
+}
91
+
59 92
 /**
60 93
  * Mark network device as having link down
61 94
  *
@@ -68,7 +101,7 @@ void netdev_link_down ( struct net_device *netdev ) {
68 101
 	 */
69 102
 	if ( ( netdev->link_rc == 0 ) ||
70 103
 	     ( netdev->link_rc == -EUNKNOWN_LINK_STATUS ) ) {
71
-		netdev->link_rc = -ENOTCONN;
104
+		netdev_link_err ( netdev, -ENOTCONN );
72 105
 	}
73 106
 }
74 107
 
@@ -367,6 +400,7 @@ struct net_device * alloc_netdev ( size_t priv_size ) {
367 400
  */
368 401
 int register_netdev ( struct net_device *netdev ) {
369 402
 	static unsigned int ifindex = 0;
403
+	struct net_driver *driver;
370 404
 	int rc;
371 405
 
372 406
 	/* Create device name */
@@ -376,22 +410,38 @@ int register_netdev ( struct net_device *netdev ) {
376 410
 	/* Set initial link-layer address */
377 411
 	netdev->ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
378 412
 
413
+	/* Add to device list */
414
+	netdev_get ( netdev );
415
+	list_add_tail ( &netdev->list, &net_devices );
416
+	DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
417
+	       netdev, netdev->name, netdev->dev->name,
418
+	       netdev_addr ( netdev ) );
419
+
379 420
 	/* Register per-netdev configuration settings */
380 421
 	if ( ( rc = register_settings ( netdev_settings ( netdev ),
381 422
 					NULL ) ) != 0 ) {
382 423
 		DBGC ( netdev, "NETDEV %p could not register settings: %s\n",
383 424
 		       netdev, strerror ( rc ) );
384
-		return rc;
425
+		goto err_register_settings;
385 426
 	}
386 427
 
387
-	/* Add to device list */
388
-	netdev_get ( netdev );
389
-	list_add_tail ( &netdev->list, &net_devices );
390
-	DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
391
-	       netdev, netdev->name, netdev->dev->name,
392
-	       netdev_addr ( netdev ) );
428
+	/* Probe device */
429
+	for_each_table_entry ( driver, NET_DRIVERS ) {
430
+		if ( ( rc = driver->probe ( netdev ) ) != 0 ) {
431
+			DBGC ( netdev, "NETDEV %p could not add %s device: "
432
+			       "%s\n", netdev, driver->name, strerror ( rc ) );
433
+			goto err_probe;
434
+		}
435
+	}
393 436
 
394 437
 	return 0;
438
+
439
+ err_probe:
440
+	for_each_table_entry_continue_reverse ( driver, NET_DRIVERS )
441
+		driver->remove ( netdev );
442
+	unregister_settings ( netdev_settings ( netdev ) );
443
+ err_register_settings:
444
+	return rc;
395 445
 }
396 446
 
397 447
 /**
@@ -419,6 +469,9 @@ int netdev_open ( struct net_device *netdev ) {
419 469
 	/* Add to head of open devices list */
420 470
 	list_add ( &netdev->open_list, &open_net_devices );
421 471
 
472
+	/* Notify drivers of device state change */
473
+	netdev_notify ( netdev );
474
+
422 475
 	return 0;
423 476
 }
424 477
 
@@ -435,18 +488,21 @@ void netdev_close ( struct net_device *netdev ) {
435 488
 
436 489
 	DBGC ( netdev, "NETDEV %p closing\n", netdev );
437 490
 
491
+	/* Remove from open devices list */
492
+	list_del ( &netdev->open_list );
493
+
494
+	/* Mark as closed */
495
+	netdev->state &= ~NETDEV_OPEN;
496
+
497
+	/* Notify drivers of device state change */
498
+	netdev_notify ( netdev );
499
+
438 500
 	/* Close the device */
439 501
 	netdev->op->close ( netdev );
440 502
 
441 503
 	/* Flush TX and RX queues */
442 504
 	netdev_tx_flush ( netdev );
443 505
 	netdev_rx_flush ( netdev );
444
-
445
-	/* Mark as closed */
446
-	netdev->state &= ~NETDEV_OPEN;
447
-
448
-	/* Remove from open devices list */
449
-	list_del ( &netdev->open_list );
450 506
 }
451 507
 
452 508
 /**
@@ -457,10 +513,15 @@ void netdev_close ( struct net_device *netdev ) {
457 513
  * Removes the network device from the list of network devices.
458 514
  */
459 515
 void unregister_netdev ( struct net_device *netdev ) {
516
+	struct net_driver *driver;
460 517
 
461 518
 	/* Ensure device is closed */
462 519
 	netdev_close ( netdev );
463 520
 
521
+	/* Remove device */
522
+	for_each_table_entry_reverse ( driver, NET_DRIVERS )
523
+		driver->remove ( netdev );
524
+
464 525
 	/* Unregister per-netdev configuration settings */
465 526
 	unregister_settings ( netdev_settings ( netdev ) );
466 527
 

Loading…
Cancel
Save