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".

-- 
Matthias
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to