
Am 29.11.2011 19:39, schrieb Mike Frysinger:
+static int tap_set_hwaddr(struct eth_device *dev)
> +{ > + /* Nothing to be done here */ > + return 0; > +}
isn't there an ioctl that lets you control this ?
Sure. But if I read the the docs correct it is an privileged operation and I don't think we wan't to run u-boot as super user all the time. How is the situation handled on real hardware when the MAC is programmed to an EEPROM on the NIC. Can the MAC be read from the NIC and set to u-boot? This would be the best solution as linux should take care about MAC address assignment.
the tap_initialize() func should read the current MAC address assigned to the tap device and write that to dev->enetaddr
Done.
then when tap_set_hwaddr() gets called, if the MAC is different, it will attempt to set the MAC to what the user requested. if they don't have permission, then the code can yell at them. but if they do, this should work imo. this gets us the best of all worlds i think.
I looked into that. It seems that you have to shut down the interface, change the MAC and up the interface again. I tried now to do this using some ioctls but didn't got it working as user or as root. So I give up at this point. Should I submit the V2 patch without setting MAC function anyway or will it not be applied then?
If someone has an idea: Here is the (simplified) code to set the MAC of a tap interface.
void os_tap_set_hw_addr(int fd, unsigned char *hwaddr) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, "tap0", IFNAMSIZ); /* Get the interface flags */ if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { perror("Could not get interface flags"); } /* Shut down the interface */ ifr.ifr_flags &= ~(IFF_UP); if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) { perror("Could not down the interface"); }
/* Set the new hw address */ ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; memcpy(&ifr.ifr_hwaddr.sa_data, hwaddr, ETH_ALEN);
if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) { perror("ioctl(SIOCSIFHWADDR)"); }
/* Get the interface flags */ if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { perror("Could not get interface flags"); } /* Shut down the interface */ ifr.ifr_flags |= IFF_UP; if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) { perror("Could not up the interface"); } }
The SIOC{G,S}IFFLAGS ioctl calls fail with "Invalid argument" and the SIOCSIFHWADDR fails with "Device or resource busy".