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.
This commit is contained in:
Knud Baastrup 2015-04-14 10:12:55 -04:00
parent 0dbebdbddf
commit c4b7de9406
1 changed files with 76 additions and 5 deletions

View File

@ -79,6 +79,7 @@ int ec_eoedev_open(struct net_device *);
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 @@ static const struct net_device_ops ec_eoedev_ops = {
.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 @@ int ec_eoe_init(
)
{
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 @@ int ec_eoe_init(
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 @@ int ec_eoe_init(
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: