[U-Boot] [PATCH RFC] sandbox: Add tap based networking

Matthias Weisser weisserm at arcor.de
Sat Dec 3 16:06:58 CET 2011


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


More information about the U-Boot mailing list