Quellcode durchsuchen

[netdevice] Avoid registering duplicate network devices

Reject network devices which appear to be duplicates of those already
available via a different underlying hardware device.  On a Xen PV-HVM
system, this allows us to filter out the emulated PCI NICs (which
would otherwise appear alongside the netfront NICs).

Note that we cannot use the Xen facility to "unplug" the emulated PCI
NICs, since there is no guarantee that the OS we subsequently load
will have a native netfront driver.

We permit devices with the same MAC address if they are attached to
the same underlying hardware device (e.g. VLAN devices).

Inspired-by: Marin Hannache <git@mareo.fr>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown vor 10 Jahren
Ursprung
Commit
98d09a1e03
2 geänderte Dateien mit 42 neuen und 5 gelöschten Zeilen
  1. 2
    0
      src/include/ipxe/netdevice.h
  2. 40
    5
      src/net/netdevice.c

+ 2
- 0
src/include/ipxe/netdevice.h Datei anzeigen

685
 extern struct net_device * find_netdev_by_index ( unsigned int index );
685
 extern struct net_device * find_netdev_by_index ( unsigned int index );
686
 extern struct net_device * find_netdev_by_location ( unsigned int bus_type,
686
 extern struct net_device * find_netdev_by_location ( unsigned int bus_type,
687
 						     unsigned int location );
687
 						     unsigned int location );
688
+extern struct net_device *
689
+find_netdev_by_ll_addr ( struct ll_protocol *ll_protocol, const void *ll_addr );
688
 extern struct net_device * last_opened_netdev ( void );
690
 extern struct net_device * last_opened_netdev ( void );
689
 extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
691
 extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
690
 		    struct net_protocol *net_protocol, const void *ll_dest,
692
 		    struct net_protocol *net_protocol, const void *ll_dest,

+ 40
- 5
src/net/netdevice.c Datei anzeigen

602
 int register_netdev ( struct net_device *netdev ) {
602
 int register_netdev ( struct net_device *netdev ) {
603
 	struct ll_protocol *ll_protocol = netdev->ll_protocol;
603
 	struct ll_protocol *ll_protocol = netdev->ll_protocol;
604
 	struct net_driver *driver;
604
 	struct net_driver *driver;
605
+	struct net_device *duplicate;
605
 	uint32_t seed;
606
 	uint32_t seed;
606
 	int rc;
607
 	int rc;
607
 
608
 
609
+	/* Set initial link-layer address, if not already set */
610
+	if ( ! netdev_has_ll_addr ( netdev ) ) {
611
+		ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
612
+	}
613
+
614
+	/* Reject network devices that are already available via a
615
+	 * different hardware device.
616
+	 */
617
+	duplicate = find_netdev_by_ll_addr ( ll_protocol, netdev->ll_addr );
618
+	if ( duplicate && ( duplicate->dev != netdev->dev ) ) {
619
+		DBGC ( netdev, "NETDEV rejecting duplicate (phys %s) of %s "
620
+		       "(phys %s)\n", netdev->dev->name, duplicate->name,
621
+		       duplicate->dev->name );
622
+		rc = -EEXIST;
623
+		goto err_duplicate;
624
+	}
625
+
608
 	/* Record device index and create device name */
626
 	/* Record device index and create device name */
609
 	netdev->index = netdev_index++;
627
 	netdev->index = netdev_index++;
610
 	if ( netdev->name[0] == '\0' ) {
628
 	if ( netdev->name[0] == '\0' ) {
612
 			   netdev->index );
630
 			   netdev->index );
613
 	}
631
 	}
614
 
632
 
615
-	/* Set initial link-layer address, if not already set */
616
-	if ( ! netdev_has_ll_addr ( netdev ) ) {
617
-		ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
618
-	}
619
-
620
 	/* Use least significant bits of the link-layer address to
633
 	/* Use least significant bits of the link-layer address to
621
 	 * improve the randomness of the (non-cryptographic) random
634
 	 * improve the randomness of the (non-cryptographic) random
622
 	 * number generator.
635
 	 * number generator.
660
 	clear_settings ( netdev_settings ( netdev ) );
673
 	clear_settings ( netdev_settings ( netdev ) );
661
 	unregister_settings ( netdev_settings ( netdev ) );
674
 	unregister_settings ( netdev_settings ( netdev ) );
662
  err_register_settings:
675
  err_register_settings:
676
+ err_duplicate:
663
 	return rc;
677
 	return rc;
664
 }
678
 }
665
 
679
 
852
 	return NULL;	
866
 	return NULL;	
853
 }
867
 }
854
 
868
 
869
+/**
870
+ * Get network device by link-layer address
871
+ *
872
+ * @v ll_protocol	Link-layer protocol
873
+ * @v ll_addr		Link-layer address
874
+ * @ret netdev		Network device, or NULL
875
+ */
876
+struct net_device * find_netdev_by_ll_addr ( struct ll_protocol *ll_protocol,
877
+					     const void *ll_addr ) {
878
+	struct net_device *netdev;
879
+
880
+	list_for_each_entry ( netdev, &net_devices, list ) {
881
+		if ( ( netdev->ll_protocol == ll_protocol ) &&
882
+		     ( memcmp ( netdev->ll_addr, ll_addr,
883
+				ll_protocol->ll_addr_len ) == 0 ) )
884
+			return netdev;
885
+	}
886
+
887
+	return NULL;
888
+}
889
+
855
 /**
890
 /**
856
  * Get most recently opened network device
891
  * Get most recently opened network device
857
  *
892
  *

Laden…
Abbrechen
Speichern