# HG changeset patch # User Knud Baastrup # Date 1429020775 14400 # Node ID e25af8bd3957f1aa8b785eebb74958dc6b1a2e02 # Parent ecef88726fc376111a221314769d0a6bc9b7330c Eoe mac address now derived from unique mac. The EoE MAC address is now derived from the NIC part of the first global unique MAC address of the linked list of available network interfaces or otherwise the MAC address used by the EtherCAT master. The EoE MAC address will get the format 02:NIC:NIC:NIC:RP:RP where NIC comes from the unique MAC address (if available) and RP is the ring position of the EoE slave. diff -r ecef88726fc3 -r e25af8bd3957 master/ethernet.c --- 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: