2006-02-20 01:01:24

by Martin Michlmayr

[permalink] [raw]
Subject: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

From: John Bowler <[email protected]>

Some Ethernet hardware implementations have no built-in storage for
allocated MAC values - an example is the Intel IXP420 chip which has
support for Ethernet but no defined way of storing allocated MAC values.
With such hardware different board level implementations store the
allocated MAC (or MACs) in different ways. Rather than put board level
code into a specific Ethernet driver this driver provides a generally
accessible repository for the MACs which can be written by board level
code and read by the driver.

The implementation also allows user level programs to access the MAC
information in /proc/net/maclist. This is useful as it allows user space
code to use the MAC if it is not used by a built-in driver.

This driver has been used for several months on various IXP420 based
platforms within the NSLU2-Linux project, including the Linksys NSLU2.
A sample implementation of the use of maclist is sent as patch 2. This
one is for the Linksys NSLU2, but several more patches for other IXP420
based platforms are available.

Signed-off-by: John Bowler <[email protected]>
Signed-off-by: Martin Michlmayr <[email protected]>
Signed-off-by: Alessandro Zummo <[email protected]>
Signed-off-by: Rod Whitby <[email protected]>

---

drivers/net/Kconfig | 15 ++
drivers/net/Makefile | 1
drivers/net/maclist.c | 314 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/net/maclist.h | 23 +++
4 files changed, 353 insertions(+)

--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-nslu2/include/net/maclist.h 2006-02-06 22:35:23.000000000 +0100
@@ -0,0 +1,23 @@
+#ifndef _MACLIST_H
+#define _MACLIST_H 1
+/*
+ * Interfaces to the MAC repository
+ */
+/*
+ * Add a single entry, returns 0 on success else an error
+ * code. Must *not* be called from an interrupt handler.
+ */
+extern int maclist_add(const u8 id_to_add[6]);
+
+/*
+ * Return the current entry count (valid in any context).
+ */
+extern int maclist_count(void);
+
+/*
+ * Return the ID from the n'th entry (valid in any context),
+ * returns 0 on success, -EINVAL if 'n' is out of range.
+ */
+extern int maclist_read(u8 (*buffer_for_id)[6], int index_of_id_to_return);
+
+#endif /*_MACLIST_H*/
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-nslu2/drivers/net/maclist.c 2006-02-06 22:35:23.000000000 +0100
@@ -0,0 +1,314 @@
+/*
+ * drivers/net/maclist.c
+ *
+ * a simple driver to remember ethernet MAC values
+ *
+ * Some Ethernet hardware implementations have no built-in
+ * storage for allocated MAC values - an example is the Intel
+ * IXP420 chip which has support for Ethernet but no defined
+ * way of storing allocated MAC values. With such hardware
+ * different board level implementations store the allocated
+ * MAC (or MACs) in different ways. Rather than put board
+ * level code into a specific Ethernet driver this driver
+ * provides a generally accessible repository for the MACs
+ * which can be written by board level code and read by the
+ * driver.
+ *
+ * The implementation also allows user level programs to
+ * access the MAC information in /proc/net/maclist. This is
+ * useful as it allows user space code to use the MAC if it
+ * is not used by a built-in driver.
+ *
+ * Copyright (C) 2005 John Bowler
+ * Author: John Bowler <[email protected]>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * External interfaces:
+ * Interfaces to linux kernel (and modules)
+ * maclist_add: add a single MAC
+ * maclist_count: total number of MACs stored
+ * maclist_read: read a MAC 0..(maclist_count-1)
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/etherdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/errno.h>
+
+#include <net/maclist.h>
+
+#define MACLIST_NAME "maclist"
+
+MODULE_AUTHOR("John Bowler <[email protected]>");
+MODULE_DESCRIPTION("MAC list repository");
+MODULE_LICENSE("GPL");
+
+typedef struct maclist_entry {
+ struct maclist_entry *next; /* Linked list, first first */
+ u8 id[6]; /* 6 byte Ethernet MAC */
+} maclist_entry_t;
+
+/* Access to this list is possible at any time - entries in
+ * the list are never destroyed. Modification of the list is
+ * safe only from the init code (i.e. modification must be
+ * single threaded), but read from an interrupt at the same
+ * time is possible and safe.
+ */
+static maclist_entry_t *maclist_list = 0;
+
+/*
+ * External interfaces.
+ *
+ * Add a single entry, returns 0 on success else an error
+ * code. Must be single threaded.
+ */
+int maclist_add(const u8 new_id[6]) {
+ maclist_entry_t *new_entry, **tail;
+
+ if (new_id == 0 || !is_valid_ether_addr(new_id)) {
+ printk(KERN_ERR MACLIST_NAME ": invalid ethernet address\n");
+ return -EINVAL;
+ }
+ new_entry = kmalloc(sizeof *new_entry, GFP_KERNEL);
+ if (new_entry == 0)
+ return -ENOMEM;
+ new_entry->next = 0;
+ memcpy(new_entry->id, new_id, sizeof new_entry->id);
+
+ tail = &maclist_list;
+ while (*tail != 0)
+ tail = &(*tail)->next;
+ *tail = new_entry;
+ return 0;
+}
+EXPORT_SYMBOL(maclist_add);
+
+/*
+ * Return the current entry count (valid in any context).
+ */
+int maclist_count(void) {
+ maclist_entry_t *tail = maclist_list;
+ int count = 0;
+
+ while (tail != 0) {
+ tail = tail->next;
+ ++count;
+ }
+
+ return count;
+}
+EXPORT_SYMBOL(maclist_count);
+
+/*
+ * Return the ID from the n'th entry (valid in any context),
+ * returns 0 on success, -EINVAL if 'n' is out of range.
+ */
+int maclist_read(u8 (*id)[6], int n) {
+ maclist_entry_t *entry = maclist_list;
+
+ while (n > 0 && entry != 0) {
+ --n;
+ entry = entry->next;
+ }
+
+ if (n == 0 && entry != 0) {
+ memcpy(id, entry->id, sizeof *id);
+ return 0;
+ }
+
+ printk(KERN_ERR MACLIST_NAME ": id does not exist\n");
+ return -EINVAL;
+}
+EXPORT_SYMBOL(maclist_read);
+
+/*
+ * Parameter parsing. The option string is a list of MAC
+ * addresses, comma separated. (The parsing really should
+ * be somewhere central...)
+ */
+static int __init maclist_setup(char *param) {
+ int bytes = 0, seen_a_digit = 0;
+ u8 id[6];
+
+ memset(id, 0, sizeof id);
+
+ if (param) do {
+ int digit = -1;
+ switch (*param) {
+ case '0': digit = 0; break;
+ case '1': digit = 1; break;
+ case '2': digit = 2; break;
+ case '3': digit = 3; break;
+ case '4': digit = 4; break;
+ case '5': digit = 5; break;
+ case '6': digit = 6; break;
+ case '7': digit = 7; break;
+ case '8': digit = 8; break;
+ case '9': digit = 9; break;
+ case 'a': case 'A': digit = 10; break;
+ case 'b': case 'B': digit = 11; break;
+ case 'c': case 'C': digit = 12; break;
+ case 'd': case 'D': digit = 13; break;
+ case 'e': case 'E': digit = 14; break;
+ case 'f': case 'F': digit = 15; break;
+ case ':':
+ if (seen_a_digit)
+ bytes = (bytes+1) & ~1;
+ else
+ bytes += 2; /* i.e. ff::ff is ff:00:ff */
+ seen_a_digit = 0;
+ break;
+ case 0:
+ if (bytes == 0) /* nothing new seen so far */
+ return 0;
+ /*fall through*/
+ case ',': case ';':
+ if (bytes > 0)
+ bytes = 12; /* i.e. all trailing bytes 0 */
+ break;
+ default:
+ printk(KERN_ERR MACLIST_NAME ": invalid character <%c[%d]>\n",
+ *param, *param);
+ return -EINVAL;
+ }
+
+ if (digit >= 0) {
+ id[bytes>>1] = (id[bytes>>1] << 4) + digit; break;
+ ++bytes;
+ seen_a_digit = 1;
+ }
+
+ if (bytes >= 12) {
+ int rc = maclist_add(id);
+ if (rc)
+ return rc;
+ bytes = 0;
+ seen_a_digit = 0;
+ memset(id, 0, sizeof id);
+ if (*param == 0)
+ return 0;
+ }
+ ++param;
+ } while (1);
+
+ return 0;
+}
+
+/*
+ * procfs support, if compiled in.
+ */
+#ifdef CONFIG_PROC_FS
+/*
+ * Character device read
+ */
+static int maclist_getchar(off_t n) {
+ static char xdigit[16] = "0123456789abcdef";
+ maclist_entry_t *head = maclist_list;
+ int b;
+
+ do {
+ if (head == 0)
+ return -1;
+ if (n < 18)
+ break;
+ head = head->next;
+ n -= 18;
+ } while (1);
+
+ if (n == 17)
+ return '\n';
+
+ b = n/3;
+ switch (n - b*3) {
+ case 0: return xdigit[head->id[b] >> 4];
+ case 1: return xdigit[head->id[b] & 0xf];
+ default: return ':';
+ }
+}
+
+/*
+ * The extensively undocumented proc_read_t callback is implemented here.
+ * Go look in fs/proc/generic.c:
+ *
+ * Prototype:
+ * int f(char *buffer, char **start, off_t offset,
+ * int count, int *peof, void *dat)
+ *
+ * Assume that the buffer is "count" bytes in size.
+ *
+ * 2) Set *start = an address within the buffer.
+ * Put the data of the requested offset at *start.
+ * Return the number of bytes of data placed there.
+ * If this number is greater than zero and you
+ * didn't signal eof and the reader is prepared to
+ * take more data you will be called again with the
+ * requested offset advanced by the number of bytes
+ * absorbed.
+ */
+static int maclist_proc_read(char *buffer, char **start, off_t offset,
+ int count, int *peof, void *dat) {
+ int total;
+
+ *start = buffer;
+ total = 0;
+
+ while (total < count) {
+ int ch = maclist_getchar(offset++);
+ if (ch == -1) {
+ *peof = 1;
+ break;
+ }
+ *buffer++ = ch;
+ ++total;
+ }
+
+ return total;
+}
+#endif
+
+/*
+ * Finally, the init/exit functions.
+ */
+static void __exit maclist_exit(void)
+{
+ maclist_entry_t *list;
+
+ remove_proc_entry(MACLIST_NAME, proc_net);
+
+ list = maclist_list;
+ maclist_list = 0;
+
+ while (list != 0) {
+ maclist_entry_t *head = list;
+ list = head->next;
+ kfree(head);
+ }
+}
+
+#ifdef MODULE
+static char ids[256];
+module_param_string(ids, ids, sizeof ids, 0);
+MODULE_PARM_DESC(ids, "comma separated list of MAC ids\n");
+#else
+__setup("maclist_ids=", maclist_setup);
+#endif
+
+static int __init maclist_init(void)
+{
+# ifdef MODULE
+ if (ids[0])
+ maclist_setup(ids);
+# endif
+
+ /* Ignore failure, the module will still work. */
+ (void)create_proc_read_entry(MACLIST_NAME, S_IRUGO, proc_net, maclist_proc_read, NULL);
+
+ return 0;
+}
+
+module_init(maclist_init);
+module_exit(maclist_exit);
--- linux-nslu2.orig/drivers/net/Makefile 2006-02-06 22:35:18.000000000 +0100
+++ linux-nslu2/drivers/net/Makefile 2006-02-06 22:35:23.000000000 +0100
@@ -74,6 +74,7 @@ obj-$(CONFIG_RIONET) += rionet.o
# end link order section
#

+obj-$(CONFIG_MACLIST) += maclist.o
obj-$(CONFIG_MII) += mii.o
obj-$(CONFIG_PHYLIB) += phy/

--- linux-nslu2.orig/drivers/net/Kconfig 2006-02-06 22:35:18.000000000 +0100
+++ linux-nslu2/drivers/net/Kconfig 2006-02-06 22:35:23.000000000 +0100
@@ -180,6 +180,21 @@ config NET_ETHERNET
kernel: saying N will just cause the configurator to skip all
the questions about Ethernet network cards. If unsure, say N.

+config MACLIST
+ tristate "Ethernet MAC repository"
+ depends on NET_ETHERNET
+ help
+ Some ethernet controllers have no built-in way of obtaining an
+ appropriate Ethernet MAC address. Such controllers have to be
+ initialised in a board-specific way, depending on how the allocated
+ MAC is stored. The MAC repository provides a set of APIs and a
+ proc entry (/proc/net/maclist) to store MAC values from the board
+ so that such drivers can obtain a MAC address without board-specific
+ code. You do not need to enable this device - it will be selected
+ automatically by any device which requires it. It is only useful
+ to enable it manually when building a device driver independently
+ of the kernel build.
+
config MII
tristate "Generic Media Independent Interface device support"
depends on NET_ETHERNET

--
Martin Michlmayr
http://www.cyrius.com/


2006-02-20 01:47:39

by Adrian Bunk

[permalink] [raw]
Subject: Re: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

On Mon, Feb 20, 2006 at 01:01:13AM +0000, Martin Michlmayr wrote:

> From: John Bowler <[email protected]>
>
> Some Ethernet hardware implementations have no built-in storage for
> allocated MAC values - an example is the Intel IXP420 chip which has
> support for Ethernet but no defined way of storing allocated MAC values.
> With such hardware different board level implementations store the
> allocated MAC (or MACs) in different ways. Rather than put board level
> code into a specific Ethernet driver this driver provides a generally
> accessible repository for the MACs which can be written by board level
> code and read by the driver.
>
> The implementation also allows user level programs to access the MAC
> information in /proc/net/maclist. This is useful as it allows user space
> code to use the MAC if it is not used by a built-in driver.
>
> This driver has been used for several months on various IXP420 based
> platforms within the NSLU2-Linux project, including the Linksys NSLU2.
> A sample implementation of the use of maclist is sent as patch 2. This
> one is for the Linksys NSLU2, but several more patches for other IXP420
> based platforms are available.
>...

Silly question:

Why can't this be implemented in user space using the SIOCSIFHWADDR
ioctl?

> Martin Michlmayr

cu
Adrian

--

"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed

2006-02-20 02:02:10

by Alessandro Zummo

[permalink] [raw]
Subject: Re: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

On Mon, 20 Feb 2006 02:47:35 +0100
Adrian Bunk <[email protected]> wrote:

> > Some Ethernet hardware implementations have no built-in storage for
> > allocated MAC values - an example is the Intel IXP420 chip which has
> > support for Ethernet but no defined way of storing allocated MAC values.
> > With such hardware different board level implementations store the
> > allocated MAC (or MACs) in different ways. Rather than put board level
> > c
> Silly question:
>
> Why can't this be implemented in user space using the SIOCSIFHWADDR
> ioctl?

Because sometimes you need to have networking available
well before userspace.

(netconsole, root over nfs, ...)

--

Best regards,

Alessandro Zummo,
Tower Technologies - Turin, Italy

http://www.towertech.it

2006-02-20 02:39:04

by Adrian Bunk

[permalink] [raw]
Subject: Re: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

On Mon, Feb 20, 2006 at 03:01:46AM +0100, Alessandro Zummo wrote:
> On Mon, 20 Feb 2006 02:47:35 +0100
> Adrian Bunk <[email protected]> wrote:
>
> > > Some Ethernet hardware implementations have no built-in storage for
> > > allocated MAC values - an example is the Intel IXP420 chip which has
> > > support for Ethernet but no defined way of storing allocated MAC values.
> > > With such hardware different board level implementations store the
> > > allocated MAC (or MACs) in different ways. Rather than put board level
> > > c
> > Silly question:
> >
> > Why can't this be implemented in user space using the SIOCSIFHWADDR
> > ioctl?
>
> Because sometimes you need to have networking available
> well before userspace.
>
> (netconsole, root over nfs, ...)

Why can't setting MAC addresses be done from initramfs?

> Best regards,
> Alessandro Zummo,

cu
Adrian

--

"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed

2006-02-20 12:16:55

by David Vrabel

[permalink] [raw]
Subject: Re: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

Alessandro Zummo wrote:
> On Mon, 20 Feb 2006 02:47:35 +0100
> Adrian Bunk <[email protected]> wrote:
>
>
>>>Some Ethernet hardware implementations have no built-in storage for
>>>allocated MAC values - an example is the Intel IXP420 chip which has
>>>support for Ethernet but no defined way of storing allocated MAC values.
>>>With such hardware different board level implementations store the
>>>allocated MAC (or MACs) in different ways. Rather than put board level
>>>code

For those not familar with the IXP4xx, the Ethernet drivers are
proprietary and given that there are no other proposed users of this
maclist code there's no need for it in the kernel at this time.

>>Silly question:
>>
>>Why can't this be implemented in user space using the SIOCSIFHWADDR
>>ioctl?

I'm with Adrian on this -- it's a job for userspace. The storage of the
MAC address isn't something that's necessarily board specific anyway but
could depend on which bootloader is used and/or the bootloader version.

> Because sometimes you need to have networking available
> well before userspace.

In the specific case of the IXP4xx, you presumably have some userspace
available because you've just loaded the NPE firmware from it, yes?

David Vrabel

2006-02-20 12:57:45

by Alessandro Zummo

[permalink] [raw]
Subject: Re: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

On Mon, 20 Feb 2006 12:16:43 +0000
David Vrabel <[email protected]> wrote:

> >>>Some Ethernet hardware implementations have no built-in storage for
> >>>allocated MAC values - an example is the Intel IXP420 chip which has
> >>>support for Ethernet but no defined way of storing allocated MAC values.
> >>>With such hardware different board level implementations store the
> >>>allocated MAC (or MACs) in different ways. Rather than put board level
> >>>code

> For those not familar with the IXP4xx, the Ethernet drivers are
> proprietary and given that there are no other proposed users of this
> maclist code there's no need for it in the kernel at this time.

> >>Why can't this be implemented in user space using the SIOCSIFHWADDR
> >>ioctl?

> I'm with Adrian on this -- it's a job for userspace. The storage of the
> MAC address isn't something that's necessarily board specific anyway but
> could depend on which bootloader is used and/or the bootloader version.

> > Because sometimes you need to have networking available
> > well before userspace.
>
> In the specific case of the IXP4xx, you presumably have some userspace
> available because you've just loaded the NPE firmware from it, yes?

Hi David,

you're certainly right on the ixp4xx, but the are other uses
for this driver which we are working on.. for example,
some Cirrus Logic ARM based chips (ep93xx) have an ethernet device
that could benefit from that.

I'm pretty sure that there are and will be more devices
with such requirements, with either proprietary or
open source drivers. My opinion is that a maclist alike
facility can clean some of the mess in that area.

If we implement such a thing in userspace every distribution
will need to be aware of a specific trick for a specific
board. If we have a clean facility in the kernel, userspace
will not need to care.

--

Best regards,

Alessandro Zummo,
Tower Technologies - Turin, Italy

http://www.towertech.it

2006-02-20 13:02:15

by Russell King

[permalink] [raw]
Subject: Re: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

On Mon, Feb 20, 2006 at 01:57:18PM +0100, Alessandro Zummo wrote:
> you're certainly right on the ixp4xx, but the are other uses
> for this driver which we are working on.. for example,
> some Cirrus Logic ARM based chips (ep93xx) have an ethernet device
> that could benefit from that.

An alternative solution (suggested in the past) would be to have a
generic kernel command line option such as: mac=<netdev>,<macaddr>

It nicely solves the "no mac address" issue in a lot (if not all)
of the cases.

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 Serial core

2006-02-20 13:07:15

by Lennert Buytenhek

[permalink] [raw]
Subject: Re: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

On Mon, Feb 20, 2006 at 01:57:18PM +0100, Alessandro Zummo wrote:

> you're certainly right on the ixp4xx, but the are other uses
> for this driver which we are working on.. for example,
> some Cirrus Logic ARM based chips (ep93xx) have an ethernet device
> that could benefit from that.

Many platforms have the same problem (esp. embedded ones), but that
doesn't mean that maclist is necessarily the best solution.

The main problem I see with maclist (correct me if I'm wrong) is that
there can be multiple devices in the system that need to get their
MAC address from somewhere, and maclist doesn't make the distinction
which address belongs to what. The main issue I have with it is that
it's too general, and that it's lots of code.

I don't think something as complex as maclist is necessary to solve
the problem. For example, why don't you just have an unsigned char
ixp4xx_mac_addr[6] in the ixp4xx core code, have the ixp4xx board code
fill that in, and have the ixp4xx ethernet driver use that?

Or just pass the MAC along in platform device style. What I did in
drivers/net/ixp2000/ was to have enp2611.c (board-specific code) read
the MAC from the board, and pass it to ixpdev.c (generic code) in the
net_device structure.


cheers,
Lennert

2006-02-20 13:15:19

by jamal

[permalink] [raw]
Subject: Re: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

On Mon, 2006-20-02 at 14:07 +0100, Lennert Buytenhek wrote:
> On Mon, Feb 20, 2006 at 01:57:18PM +0100, Alessandro Zummo wrote:
>

> Or just pass the MAC along in platform device style. What I did in
> drivers/net/ixp2000/ was to have enp2611.c (board-specific code) read
> the MAC from the board, and pass it to ixpdev.c (generic code) in the
> net_device structure.
>

yep, this is what i have seen done in a lot of embedded boards
containing switching chips (If i am not mistaken there is a 4 port
switch in the IXP4xx)

cheers,
jamal

2006-02-20 13:28:45

by Alessandro Zummo

[permalink] [raw]
Subject: Re: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

On Mon, 20 Feb 2006 14:07:12 +0100
Lennert Buytenhek <[email protected]> wrote:

> > you're certainly right on the ixp4xx, but the are other uses
> > for this driver which we are working on.. for example,
> > some Cirrus Logic ARM based chips (ep93xx) have an ethernet device
> > that could benefit from that.

> Many platforms have the same problem (esp. embedded ones), but that
> doesn't mean that maclist is necessarily the best solution.

of course, that's why I wrote "maclist-alike"


> The main problem I see with maclist (correct me if I'm wrong) is that
> there can be multiple devices in the system that need to get their
> MAC address from somewhere, and maclist doesn't make the distinction
> which address belongs to what. The main issue I have with it is that
> it's too general, and that it's lots of code.

you're right, usually the first device will get the first mac
and so on. it is general because it has been coded to be that way
I think.


> I don't think something as complex as maclist is necessary to solve
> the problem. For example, why don't you just have an unsigned char
> ixp4xx_mac_addr[6] in the ixp4xx core code, have the ixp4xx board code
> fill that in, and have the ixp4xx ethernet driver use that?
>
> Or just pass the MAC along in platform device style. What I did in
> drivers/net/ixp2000/ was to have enp2611.c (board-specific code) read
> the MAC from the board, and pass it to ixpdev.c (generic code) in the
> net_device structure.

that perfectly doable, but maybe having one common interface could
be a cleaner solution. your setup is board -> netdriver
while maclist implements board -> storage -> netdriver.

It is absolutely not a requirement, just a commodity.

--

Best regards,

Alessandro Zummo,
Tower Technologies - Turin, Italy

http://www.towertech.it

2006-02-20 13:29:17

by Alessandro Zummo

[permalink] [raw]
Subject: Re: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

On Mon, 20 Feb 2006 13:02:03 +0000
Russell King <[email protected]> wrote:

> > for this driver which we are working on.. for example,
> > some Cirrus Logic ARM based chips (ep93xx) have an ethernet device
> > that could benefit from that.
>
> An alternative solution (suggested in the past) would be to have a
> generic kernel command line option such as: mac=<netdev>,<macaddr>
>
> It nicely solves the "no mac address" issue in a lot (if not all)
> of the cases.

That would help, but it can't easily be implemented when you are
targeting consumer devices like nas, routers et al which already
have been widely deployed.

I know that the solution would be to fix the bootloader, but
Joe Average is a little bit scared of reflashing it.

A maclist-alike system could help to solve that situation.

--

Best regards,

Alessandro Zummo,
Tower Technologies - Turin, Italy

http://www.towertech.it

2006-02-20 16:23:52

by John Bowler

[permalink] [raw]
Subject: RE: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

From: Adrian Bunk [mailto:[email protected]]
>Why can't setting MAC addresses be done from initramfs?

The submitted version of this code is actually an old version,
which has some potential locking problems and doesn't document
how to solve the problem of different drivers getting different
MAC ids.

This stuff *should* be done in the board level code, that should
load the MAC (somehow) and then set it into Ethernet driver resources
so that the (necessarily later) init of the Ethernet device can
pick up the correct address.

Unfortunately on some systems this (the use of machine level
resources in the board init code) is not possible because the
ethernet driver is in a module. The *same* driver may be in kernel
on other systems.

This creates a combinatorial problem - dealing with *all* the
possibilities creates an enormous mess. It doesn't matter where
the solution happens - boot loader, initramfs or kernel init - the
combinatorial problem is still there because there must be handling
for every combination which occurs in practice.

The problem is very much one of embedded systems. In such systems
a generic board will have a specific manufacturing implementation
which stores the MAC in an implementation specific way. E.g. a
vendor may drop the EEPROM from the Gateworks GW2348 board (that
EEPROM costs real money!) and put the MAC in somewhere else. Gateworks
doesn't *document* a specific place to put the MAC (though they *do*
put it in the EEPROM). The lack of documentation and the certainty of
variation in particular IHV uses of the board creates the problem.

maclist simply breaks the problem into two pieces:

1) store this MAC in a linked list.
2) read a MAC from a linked list.

It's a classic "Gordian Knot" problem...

I thought a linked list was pretty simple ;-)

The locking in this version of the code is *wrong*, my assumptions
were bogus and I don't think the code will work correctly on SMP
systems.

The latest version of the code includes significantly more
documentation in the header file and makes the whole thing fail
safe. Again this is an embedded system problem - the ethernet
may be the only thing on the system! The newer code returns an
appropriate 'random' MAC if there isn't one available. This makes
debugging into a tractable problem on systems with just the
ethernet.

The implementation is still a linked list, but insertion is locked
and checking is done to deal with the unavailable MAC case. As in
the simple case the advantage is that common code is in just one
place, not replicated across multiple instances of board/driver
code.

John Bowler <[email protected]>

2006-02-20 17:04:38

by John Bowler

[permalink] [raw]
Subject: RE: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

My latest version of this patch is here:

http://cvs.sourceforge.net/viewcvs.py/nslu/kernel/2.6.15/91-maclist.patch?rev=1.2&only_with_tag=HEAD&view=markup

In "Recommendations" "With the second strategy" should be "With
the first strategy".

(Note that the '2.6.16' directory in that repo contains an old
version - it is, in fact, rev 1.1 from the 2.6.15 directory.)

John Bowler <[email protected]>

2006-03-03 16:17:53

by Atsushi Nemoto

[permalink] [raw]
Subject: Re: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist

>>>>> On Mon, 20 Feb 2006 01:01:13 +0000, Martin Michlmayr <[email protected]> said:

tbm> Some Ethernet hardware implementations have no built-in storage
tbm> for allocated MAC values - an example is the Intel IXP420 chip
tbm> which has support for Ethernet but no defined way of storing
tbm> allocated MAC values. With such hardware different board level
tbm> implementations store the allocated MAC (or MACs) in different
tbm> ways. Rather than put board level code into a specific Ethernet
tbm> driver this driver provides a generally accessible repository for
tbm> the MACs which can be written by board level code and read by the
tbm> driver.

Slow response:

It can be done with register_netdevice_notifier(). You can catch
NETDEV_REGISTER event, check the device is what you expected by
looking dev->irq or something, and initialize dev->dev_addr. Whole
these can be implemented in your board level code.

---
Atsushi Nemoto