--- a/master/ethernet.c Sun Jun 01 18:07:47 2014 +1200
+++ b/master/ethernet.c Tue Apr 14 10:12:55 2015 -0400
@@ -79,6 +79,7 @@
int ec_eoedev_stop(struct net_device *);
int ec_eoedev_tx(struct sk_buff *, struct net_device *);
struct net_device_stats *ec_eoedev_stats(struct net_device *);
+static int ec_eoedev_set_mac(struct net_device *netdev, void *p);
/*****************************************************************************/
@@ -90,11 +91,34 @@
.ndo_stop = ec_eoedev_stop,
.ndo_start_xmit = ec_eoedev_tx,
.ndo_get_stats = ec_eoedev_stats,
+ .ndo_set_mac_address = ec_eoedev_set_mac,
};
#endif
/*****************************************************************************/
+/**
+ * ec_eoedev_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int
+ec_eoedev_set_mac(struct net_device *netdev, void *p)
+{
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+
+ return 0;
+}
+
+/*****************************************************************************/
+
/** EoE constructor.
*
* Initializes the EoE handler, creates a net_device and registers it.
@@ -107,9 +131,13 @@
)
{
ec_eoe_t **priv;
- int i, ret = 0;
+ int ret = 0;
char name[EC_DATAGRAM_NAME_SIZE];
+ struct net_device *dev;
+ unsigned char lo_mac[ETH_ALEN] = {0};
+ unsigned int use_master_mac = 0;
+
eoe->slave = slave;
ec_datagram_init(&eoe->datagram);
@@ -165,8 +193,53 @@
eoe->dev->get_stats = ec_eoedev_stats;
#endif
- for (i = 0; i < ETH_ALEN; i++)
- eoe->dev->dev_addr[i] = i | (i << 4);
+ // First check if the MAC address assigned to the master is globally unique
+ if ((slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[0] & 0x02) != 0x02) {
+ // The master MAC is unique and the NIC part can be used for the EoE interface MAC
+ use_master_mac = 1;
+ }
+ else {
+ // The master MAC is not unique, so we check for unique MAC in other interfaces
+ dev = first_net_device(&init_net);
+ while (dev) {
+ // Check if globally unique MAC address
+ if (dev->addr_len == ETH_ALEN) {
+ if (memcmp(dev->dev_addr, lo_mac, ETH_ALEN) != 0) {
+ if ((dev->dev_addr[0] & 0x02) != 0x02) {
+ // The first globally unique MAC address has been identified
+ break;
+ }
+ }
+ }
+ dev = next_net_device(dev);
+ }
+ if (eoe->dev->addr_len == ETH_ALEN) {
+ if (dev) {
+ // A unique MAC were identified in one of the other network interfaces
+ // and the NIC part can be used for the EoE interface MAC.
+ EC_SLAVE_INFO(slave, "%s MAC address derived from NIC part of %s MAC address",
+ eoe->dev->name, dev->name);
+ eoe->dev->dev_addr[1] = dev->dev_addr[3];
+ eoe->dev->dev_addr[2] = dev->dev_addr[4];
+ eoe->dev->dev_addr[3] = dev->dev_addr[5];
+ }
+ else {
+ use_master_mac = 1;
+ }
+ }
+ }
+ if (eoe->dev->addr_len == ETH_ALEN) {
+ if (use_master_mac) {
+ EC_SLAVE_INFO(slave, "%s MAC address derived from NIC part of %s MAC address",
+ eoe->dev->name, slave->master->devices[EC_DEVICE_MAIN].dev->name);
+ eoe->dev->dev_addr[1] = slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[3];
+ eoe->dev->dev_addr[2] = slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[4];
+ eoe->dev->dev_addr[3] = slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[5];
+ }
+ eoe->dev->dev_addr[0] = 0x02;
+ eoe->dev->dev_addr[4] = (uint8_t)(slave->ring_position >> 8);
+ eoe->dev->dev_addr[5] = (uint8_t)(slave->ring_position);
+ }
// initialize private data
priv = netdev_priv(eoe->dev);
@@ -188,8 +261,6 @@
goto out_free;
}
- // make the last address octet unique
- eoe->dev->dev_addr[ETH_ALEN - 1] = (uint8_t) eoe->dev->ifindex;
return 0;
out_free: