Netdev List
 help / color / mirror / Atom feed
* Re: [ofa-general] [PATCH 2.6.25] RDMA/cxgb3: Fail loopbackconnections.
From: Steve Wise @ 2008-02-13 16:03 UTC (permalink / raw)
  To: Roland Dreier; +Cc: netdev, linux-kernel, general
In-Reply-To: <47B3120B.3040409@opengridcomputing.com>

Steve Wise wrote:
> Roland Dreier wrote:
>> Steve, I had to update the patch adding an include and fixing the
>> function declaration (as below)... but how much testing have you done
>> with this??
>>
> 
> Now I understand.  I thought I'd fixed these!  I fixed them locally in 
> the test tree on my victim and then tested, but forgot to update my git 
> tree.
> 
> Sorry for this.
> 
> You want me to resubmit?
> 

BTW: Testing:  I cloned my git tree, resolved the two compile issues 
(void + include), then built and installed the kernel (2.6.25-rc1 + the 
fixed patch).  I then ensured that a connection to the local address 
caused the ENOSYS error.

I just forgot to pull the updated file back into my stg managed git tree.

:(

^ permalink raw reply

* Re: [PATCH] ixgbe: Correctly obtain protocol information on transmit
From: Andy Gospodarek @ 2008-02-13 16:13 UTC (permalink / raw)
  To: Auke Kok; +Cc: e1000-devel, netdev, andy, jeff
In-Reply-To: <20080212232033.13861.17859.stgit@localhost.localdomain>

On Tue, Feb 12, 2008 at 03:20:33PM -0800, Auke Kok wrote:
> In reply to "RE: [Fwd: [PATCH 2.6.25] ixgbe/igb: correctly obtain protocol
> information on transmit]" from Andy Gospodarek:
> 
> The driver was incorrectly looking at socket headers for
> protocol information, needed for checksumming offload. Fix
> this by not looking at the socket but frame headers instead.
> 
> This disregards extension headers but it's unclear that linux
> generates those anyway.
> 
> Tested by Andy Gospodarek.
> 
> Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>

This works well for me too.

Signed-off-by: Andy Gospodarek <andy@greyhouse.net>


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply

* [PATCh TAKE 2] [IPROUTE2] Add addrlabel sub-command.
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2008-02-13 16:20 UTC (permalink / raw)
  To: stephen.hemminger; +Cc: yoshfuji, netdev

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
diff --git a/ip/Makefile b/ip/Makefile
index b427d58..d908817 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -1,4 +1,4 @@
-IPOBJ=ip.o ipaddress.o iproute.o iprule.o \
+IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o \
     rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o \
     ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o \
     ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
diff --git a/ip/ip.c b/ip/ip.c
index aeb8c68..c4c773f 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -46,8 +46,8 @@ static void usage(void)
 	fprintf(stderr,
 "Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n"
 "       ip [ -force ] [-batch filename\n"
-"where  OBJECT := { link | addr | route | rule | neigh | ntable | tunnel |\n"
-"                   maddr | mroute | monitor | xfrm }\n"
+"where  OBJECT := { link | addr | addrlabel | route | rule | neigh | ntable |\n"
+"                   tunnel | maddr | mroute | monitor | xfrm }\n"
 "       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
 "                    -f[amily] { inet | inet6 | ipx | dnet | link } |\n"
 "                    -o[neline] | -t[imestamp] }\n");
@@ -64,6 +64,7 @@ static const struct cmd {
 	int (*func)(int argc, char **argv);
 } cmds[] = {
 	{ "address", 	do_ipaddr },
+	{ "addrlabel",	do_ipaddrlabel },
 	{ "maddress",	do_multiaddr },
 	{ "route",	do_iproute },
 	{ "rule",	do_iprule },
diff --git a/ip/ip_common.h b/ip/ip_common.h
index 39f2507..1bbd50d 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -4,6 +4,9 @@ extern int print_linkinfo(const struct sockaddr_nl *who,
 extern int print_addrinfo(const struct sockaddr_nl *who,
 			  struct nlmsghdr *n,
 			  void *arg);
+extern int print_addrlabelinfo(const struct sockaddr_nl *who,
+			       struct nlmsghdr *n,
+			       void *arg);
 extern int print_neigh(const struct sockaddr_nl *who,
 		       struct nlmsghdr *n, void *arg);
 extern int print_ntable(const struct sockaddr_nl *who,
@@ -23,6 +26,7 @@ extern int print_prefix(const struct sockaddr_nl *who,
 extern int print_rule(const struct sockaddr_nl *who,
 		      struct nlmsghdr *n, void *arg);
 extern int do_ipaddr(int argc, char **argv);
+extern int do_ipaddrlabel(int argc, char **argv);
 extern int do_iproute(int argc, char **argv);
 extern int do_iprule(int argc, char **argv);
 extern int do_ipneigh(int argc, char **argv);
diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c
new file mode 100644
index 0000000..1c873e9
--- /dev/null
+++ b/ip/ipaddrlabel.c
@@ -0,0 +1,260 @@
+/*
+ * ipaddrlabel.c	"ip addrlabel"
+ *
+ * Copyright (C)2007 USAGI/WIDE Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * Based on iprule.c.
+ *
+ * Authors:	YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <linux/types.h>
+#include <linux/if_addrlabel.h>
+
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+
+#define IFAL_RTA(r)	((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrlblmsg))))
+#define IFAL_PAYLOAD(n)	NLMSG_PAYLOAD(n,sizeof(struct ifaddrlblmsg))
+
+extern struct rtnl_handle rth;
+
+static void usage(void) __attribute__((noreturn));
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage: ip addrlabel [ list | add | del | flush ] prefix PREFIX [ dev DEV ] [ label LABEL ]\n");
+	exit(-1);
+}
+
+int print_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+{
+	FILE *fp = (FILE*)arg;
+	struct ifaddrlblmsg *ifal = NLMSG_DATA(n);
+	int len = n->nlmsg_len;
+	int host_len = -1;
+	struct rtattr *tb[IFAL_MAX+1];
+	char abuf[256];
+
+	if (n->nlmsg_type != RTM_NEWADDRLABEL && n->nlmsg_type != RTM_DELADDRLABEL)
+		return 0;
+
+	len -= NLMSG_LENGTH(sizeof(*ifal));
+	if (len < 0)
+		return -1;
+
+	parse_rtattr(tb, IFAL_MAX, IFAL_RTA(ifal), len);
+
+	if (ifal->ifal_family == AF_INET)
+		host_len = 32;
+	else if (ifal->ifal_family == AF_INET6)
+		host_len = 128;
+
+	if (n->nlmsg_type == RTM_DELADDRLABEL)
+		fprintf(fp, "Deleted ");
+
+	if (tb[IFAL_ADDRESS]) {
+		fprintf(fp, "prefix %s/%u ",
+			format_host(ifal->ifal_family,
+				    RTA_PAYLOAD(tb[IFAL_ADDRESS]),
+				    RTA_DATA(tb[IFAL_ADDRESS]),
+				    abuf, sizeof(abuf)),
+			ifal->ifal_prefixlen);
+	}
+
+	if (ifal->ifal_index)
+		fprintf(fp, "dev %s ", ll_index_to_name(ifal->ifal_index));
+
+	if (tb[IFAL_LABEL] && RTA_PAYLOAD(tb[IFAL_LABEL]) == sizeof(int32_t)) {
+		int32_t label;
+		memcpy(&label, RTA_DATA(tb[IFAL_LABEL]), sizeof(label));
+		fprintf(fp, "label %d ", label);
+	}
+
+	fprintf(fp, "\n");
+	fflush(fp);
+	return 0;
+}
+
+static int ipaddrlabel_list(int argc, char **argv)
+{
+	int af = preferred_family;
+
+	if (af == AF_UNSPEC)
+		af = AF_INET6;
+
+	if (argc > 0) {
+		fprintf(stderr, "\"ip addrlabel show\" does not take any arguments.\n");
+		return -1;
+	}
+
+	if (rtnl_wilddump_request(&rth, af, RTM_GETADDRLABEL) < 0) {
+		perror("Cannot send dump request");
+		return 1;
+	}
+
+	if (rtnl_dump_filter(&rth, print_addrlabel, stdout, NULL, NULL) < 0) {
+		fprintf(stderr, "Dump terminated\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+
+static int ipaddrlabel_modify(int cmd, int argc, char **argv)
+{
+	struct {
+		struct nlmsghdr 	n;
+		struct ifaddrlblmsg	ifal;
+		char   			buf[1024];
+	} req;
+
+	inet_prefix prefix;
+	uint32_t label = 0xffffffffUL;
+
+	memset(&req, 0, sizeof(req));
+	memset(&prefix, 0, sizeof(prefix));
+
+	req.n.nlmsg_type = cmd;
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrlblmsg));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.ifal.ifal_family = preferred_family;
+	req.ifal.ifal_prefixlen = 0;
+	req.ifal.ifal_index = 0;
+
+	if (cmd == RTM_NEWADDRLABEL) {
+		req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
+	}
+
+	while (argc > 0) {
+		if (strcmp(*argv, "prefix") == 0) {
+			NEXT_ARG();
+			get_prefix(&prefix, *argv, preferred_family);
+		} else if (strcmp(*argv, "dev") == 0) {
+			NEXT_ARG();
+			if ((req.ifal.ifal_index = ll_name_to_index(*argv)) == 0)
+				invarg("dev is invalid\n", *argv);
+		} else if (strcmp(*argv, "label") == 0) {
+			NEXT_ARG();
+			if (get_u32(&label, *argv, 0) || label == 0xffffffffUL)
+				invarg("label is invalid\n", *argv);
+		}
+		argc--;
+		argv++;
+	}
+
+	addattr32(&req.n, sizeof(req), IFAL_LABEL, label);
+	addattr_l(&req.n, sizeof(req), IFAL_ADDRESS, &prefix.data, prefix.bytelen);
+
+	if (req.ifal.ifal_family == AF_UNSPEC)
+		req.ifal.ifal_family = AF_INET6;
+
+	if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
+		return 2;
+
+	return 0;
+}
+
+
+static int flush_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+{
+	struct rtnl_handle rth2;
+	struct rtmsg *r = NLMSG_DATA(n);
+	int len = n->nlmsg_len;
+	struct rtattr * tb[IFAL_MAX+1];
+
+	len -= NLMSG_LENGTH(sizeof(*r));
+	if (len < 0)
+		return -1;
+
+	parse_rtattr(tb, IFAL_MAX, RTM_RTA(r), len);
+
+	if (tb[IFAL_ADDRESS]) {
+		n->nlmsg_type = RTM_DELADDRLABEL;
+		n->nlmsg_flags = NLM_F_REQUEST;
+
+		if (rtnl_open(&rth2, 0) < 0)
+			return -1;
+
+		if (rtnl_talk(&rth2, n, 0, 0, NULL, NULL, NULL) < 0)
+			return -2;
+
+		rtnl_close(&rth2);
+	}
+
+	return 0;
+}
+
+static int ipaddrlabel_flush(int argc, char **argv)
+{
+	int af = preferred_family;
+
+	if (af == AF_UNSPEC)
+		af = AF_INET6;
+
+	if (argc > 0) {
+		fprintf(stderr, "\"ip addrlabel flush\" does not allow extra arguments\n");
+		return -1;
+	}
+
+	if (rtnl_wilddump_request(&rth, af, RTM_GETADDRLABEL) < 0) {
+		perror("Cannot send dump request");
+		return 1;
+	}
+
+	if (rtnl_dump_filter(&rth, flush_addrlabel, NULL, NULL, NULL) < 0) {
+		fprintf(stderr, "Flush terminated\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int do_ipaddrlabel(int argc, char **argv)
+{
+	if (argc < 1) {
+		return ipaddrlabel_list(0, NULL);
+	} else if (matches(argv[0], "list") == 0 ||
+		   matches(argv[0], "show") == 0) {
+		return ipaddrlabel_list(argc-1, argv+1);
+	} else if (matches(argv[0], "add") == 0) {
+		return ipaddrlabel_modify(RTM_NEWADDRLABEL, argc-1, argv+1);
+	} else if (matches(argv[0], "delete") == 0) {
+		return ipaddrlabel_modify(RTM_DELADDRLABEL, argc-1, argv+1);
+	} else if (matches(argv[0], "flush") == 0) {
+		return ipaddrlabel_flush(argc-1, argv+1);
+	} else if (matches(argv[0], "help") == 0)
+		usage();
+
+	fprintf(stderr, "Command \"%s\" is unknown, try \"ip addrlabel help\".\n", *argv);
+	exit(-1);
+}
+
diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c
index f1a1f27..df0fd91 100644
--- a/ip/ipmonitor.c
+++ b/ip/ipmonitor.c
@@ -54,6 +54,10 @@ int accept_msg(const struct sockaddr_nl *who,
 		print_addrinfo(who, n, arg);
 		return 0;
 	}
+	if (n->nlmsg_type == RTM_NEWADDRLABEL || n->nlmsg_type == RTM_DELADDRLABEL) {
+		print_addrlabel(who, n, arg);
+		return 0;
+	}
 	if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH) {
 		print_neigh(who, n, arg);
 		return 0;
diff --git a/man/man8/ip.8 b/man/man8/ip.8
index 1687045..136448c 100644
--- a/man/man8/ip.8
+++ b/man/man8/ip.8
@@ -13,8 +13,8 @@ ip \- show / manipulate routing, devices, policy routing and tunnels
 
 .ti -8
 .IR OBJECT " := { "
-.BR link " | " addr " | " route " | " rule " | " neigh " | " tunnel " | "\
-maddr " | "  mroute " | " monitor " }"
+.BR link " | " addr " | " addrlabel " | " route " | " rule " | " neigh " | "\
+ tunnel " | " maddr " | "  mroute " | " monitor " }"
 .sp
 
 .ti -8
@@ -97,6 +97,17 @@ maddr " | "  mroute " | " monitor " }"
 tentative " | " deprecated " ]"
 
 .ti -8
+.BR "ip addrlabel" " { " add " | " del " } " prefix 
+.BR PREFIX " [ "
+.B dev
+.IR DEV " ] [ "
+.B label
+.IR NUMBER " ]"
+
+.ti -8
+.BR "ip addrlabel" " { " list " | " flush " }"
+
+.ti -8
 .BR "ip route" " { "
 .BR list " | " flush " } "
 .I  SELECTOR
@@ -404,6 +415,11 @@ host addresses.
 .TP
 .B address
 - protocol (IP or IPv6) address on a device.
+
+.TP
+.B addrlabel
+- label configuration for protocol address selection.
+
 .TP
 .B neighbour
 - ARP or NDISC cache entry.
@@ -708,6 +724,33 @@ this option is given twice,
 also dumps all the deleted addresses in the format described in the
 previous subsection.
 
+.SH ip addrlabel - protocol address label management.
+
+IPv6 address label is used for address selection
+described in RFC 3484.  Precedence is managed by userspace,
+and only label is stored in kernel.
+
+.SS ip addrlabel add - add an address label
+the command adds an address label entry to the kernel.
+.TP
+.BI prefix " PREFIX"
+.TP
+.BI dev " DEV"
+the outgoing interface.
+.TP
+.BI label " NUMBER"
+the label for the prefix.
+0xffffffff is reserved.
+.SS ip addrlabel del - delete an address label
+the command deletes an address label entry in the kernel.
+.B Arguments:
+coincide with the arguments of
+.B ip addrlabel add
+but label is not required.
+.SS ip addrlabel list - list address labels
+the command show contents of address labels.
+.SS ip addrlabel flush - flush address labels
+the commoand flushes the contents of address labels and it does not restore default settings.
 .SH ip neighbour - neighbour/arp tables management.
 
 .B neighbour

-- 
YOSHIFUJI Hideaki @ USAGI Project  <yoshfuji@linux-ipv6.org>
GPG-FP  : 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA

^ permalink raw reply related

* RE: r8169 auto-negotiation problem
From: fgnijuhhu guduggurehug @ 2008-02-13 16:15 UTC (permalink / raw)
  To: Francois Romieu; +Cc: netdev
In-Reply-To: <20080212222015.GA21495@electric-eye.fr.zoreil.com>


Thanks for your response.

> Please try a recent kernel. Your r8169 driver is badly outdated.
OK. Now using 2.6.24-1-amd64. The r8169 version still says 2.2LK-NAPI, though.
_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today it's FREE!
http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/

^ permalink raw reply

* Re: BUG: 2.6.25-rc1: iptables postrouting setup causes oops
From: Andrew G. Morgan @ 2008-02-13 16:42 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Haavard Skinnemoen, Ben Nizette, netfilter-devel, linux-kernel,
	netdev
In-Reply-To: <20080213012231.46865608.akpm@linux-foundation.org>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Haavard,

It means your application is not capable(sic) of using the upper 32-bits
of the 64-bit capability sets supported by this newer kernel.

You might consider rebuilding the offending application linking it
against a newer version of libcap:

http://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/

However, it is a warning and, for any existing app that doesn't care
about newly added capabilities, the warning is benign.

Cheers

Andrew

Andrew Morton wrote:
| On Wed, 13 Feb 2008 10:10:24 +0100 Haavard Skinnemoen
<hskinnemoen@atmel.com> wrote:
|
|> On Wed, 13 Feb 2008 00:48:29 -0800
|> Andrew Morton <akpm@linux-foundation.org> wrote:
|>
|>> On Tue, 12 Feb 2008 22:46:01 +1100 Ben Nizette <bn@niasdigital.com>
wrote:
|>>
|>>> On an AVR32, root over NFS, config attached, running (from a startup
|>>> script):
|>>>
|>>> iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|>>>
|>>> Results in (dmesg extract including a bit of context for good measure):
|>>> -------------8<----------------
|>>> VFS: Mounted root (nfs filesystem).
|>>> Freeing init memory: 72K (90000000 - 90012000)
|>>> eth0: no IPv6 routers present
|>>> warning: `dnsmasq' uses 32-bit capabilities (legacy support in use)
|> Hmm. What does that mean? What size do capabilities normally have?
|
| My near-namesake put than in, but I immediately forgot what it means?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)

iD8DBQFHsx3n+bHCR3gb8jsRAjlNAKDK4RLJsPsMPN96JJnTj3U25Bx91ACdESeN
2P3V2ISny33KY6v107iHsKU=
=1jND
-----END PGP SIGNATURE-----

^ permalink raw reply

* Re: [RFC, PATCH]: Pass link level header from/to PPP interface
From: Urs Thuermann @ 2008-02-13 16:56 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20080212.220603.111665989.davem@davemloft.net>

Hello Dave,

> But if libpcap and tcpdump can already identify PPP packets
> then, besides "consistency", what does this buy us other
> than potential breakage?

My reason for the patch is mostly cleanliness and to make the kernel
match what is described in packet(7).

If you open a PF_PACKET/SOCK_RAW socket and bind it to an interface
you get a fixed type of frame/packet depending on the type of
interface, including the LL header.  Also if you bind to all
interfaces you can look at the interface type to know what type of
packet you get.  But not for PPP interfaces.

I've written a small packet dump util with a packet parser (somewhat
comparable to tcpdump but much smaller), which looks like this

        struct sockaddr_ll addr;
        ...
        s = open(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
        ...
        recvfrom(s, buffer, sizeof(buffer), 0, &addr, &size);
        switch (addr.sll_hatype) {
        case ARPHRD_ETHER:
        case ARPHRD_IEEE80211:
        case ARPHRD_LOOPBACK:
                parse_ether(buffer);
                break;
        case ARPHRD_TUNNEL:
                parse_ip(buffer);
                break;
        case ARPHRD_SIT:
                parse_ipv6(buffer);
                break;

and so on.  Only for PPP I need to switch on the addr.sll_protocol
since with PPP I don't get the PPP header:

        case ARPHRD_PPP:
                switch (ntohs(addr.sll_protocol))
		case ETH_P_IP:
		    parse_ip(buffer);
		    break;
		case ETH_P_IPV6:
		    parse_ipv6(buffer);
		    break;
                ...
		}
		break;

With my patch you would write

        case ARPHRD_PPP:
                parse_ppp(buffer);
                break;

and the parse function can show the complete PPP frame with protocol
field.  Without the patch there is no way to see the 2-byte PPP header
and, in contrast to packet(7), SOCK_DGRAM and SOCK_RAW are the same.

Do you consider this strong enough to justify this change?

urs

^ permalink raw reply

* Re: [PATCH] drivers/base: export gpl (un)register_memory_notifier
From: Dave Hansen @ 2008-02-13 17:05 UTC (permalink / raw)
  To: Jan-Bernd Themann
  Cc: linuxppc-dev, Thomas Klein, Themann, Jan-Bernd, netdev, apw,
	linux-kernel, Thomas Klein, Christoph Raisch, Badari Pulavarty,
	Greg KH
In-Reply-To: <200802131617.58646.ossthema@de.ibm.com>

On Wed, 2008-02-13 at 16:17 +0100, Jan-Bernd Themann wrote:
> Constraints imposed by HW / FW:
> - eHEA has own MMU
> - eHEA  Memory Regions (MRs) are used by the eHEA MMU  to translate virtual
>   addresses to absolute addresses (like DMA mapped memory on a PCI bus)
> - The number of MRs is limited (not enough to have one MR per packet)

Are there enough to have one per 16MB section?

> Our current understanding about the current Memory Hotplug System are
> (please correct me if I'm wrong):
> 
> - depends on sparse mem

You're wrong ;).  In mainline, this is true.  There was a version of the
SUSE kernel that did otherwise.  But you can not and should not depend
on this never changing.  But, someone is perfectly free to go out an
implement something better than sparsemem for memory hotplug.  If they
go and do this, your driver may get left behind. 

> - only whole memory sections are added / removed
> - for each section a memory resource is registered

True, and true. (There might be exceptions to the whole sections one,
but that's blatant abuse and should be fixed. :)

> From the driver side we need:
> - some kind of memory notification mechanism.
>   For memory add we can live without any external memory notification
>   event. For memory remove we do need an external trigger (see explanation
>   above).

You can export and use (un)register_memory_notifier.  You just need to
do it in a reasonable way that compiles for randconfig on your
architecture.  Believe me, we don't want to start teaching drivers about
sparsemem.  

> - a way to iterate over all kernel pages and a way to detect holes in the
>   kernel memory layout in order to build up our own ehea_bmap.

Look at kernel/resource.c

But, I'm really not convinced that you can actually keep this map
yourselves.  It's not as simple as you think.  What happens if you get
on an LPAR with two sections, one 256MB@0x0 and another
16MB@0x1000000000000000.  That's quite possible.  I think your vmalloc'd
array will eat all of memory.  

That's why we have SPARSEMEM_EXTREME and SPARSEMEM_VMEMMAP implemented
in the core, so that we can deal with these kinds of problems, once and
*NOT* in every single little driver out there.  

> Functions to use while building ehea_bmap + MRs:
> - Use either the functions that are used by the memory hotplug system as
>   well, that means using the section defines + functions (section_nr_to_pfn,
>   pfn_valid)

Basically, you can't use anything related to sections outside of the
core code.  You can use things like pfn_valid(), or you can create new
interfaces that are properly abstracted.  

> - Use currently other not exported functions in kernel/resource.c, like
>   walk_memory_resource (where we would still need the maximum possible number
>   of pages NR_MEM_SECTIONS)

It isn't the act of exporting that's the problem.  It's making sure that
the exports won't be prone to abuse and that people are using them
properly.  You should assume that you can export and use
walk_memory_resource().

Do you know what other operating systems do with this hardware?

In the future, please make an effort to get review from knowledgeable
people about these kinds of things before using them in your driver.
Your company has many, many resources available, and all you need to do
is ask.  All that you have to do is look to the tops of the files of the
functions you are calling.

-- Dave


^ permalink raw reply

* Re: [PATCH 1/3][NETLABEL]: Compilation for CONFIG_AUDIT=n case.
From: Paul Moore @ 2008-02-13 17:21 UTC (permalink / raw)
  To: David Miller; +Cc: xemul, netdev
In-Reply-To: <20080212.223544.21007139.davem@davemloft.net>

On Wednesday 13 February 2008 1:35:44 am David Miller wrote:
> From: Pavel Emelyanov <xemul@openvz.org>
> Date: Thu, 07 Feb 2008 20:20:30 +0300
>
> > The audit_log_start() will expand into an empty do { } while (0)
> > construction and the audit_ctx becomes unused.
> >
> > The solution: push current->audit_context into audit_log_start()
> > directly, since it is not required in any other place in the
> > calling function.
> >
> > Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
>
> Applied.

Sorry I missed these three patches when they were posted because my 
email got screwy and I was dropped from netdev (all of vger.kernel.org 
actually).  I just dug them up in the archives and they looks fine to 
me.  Thanks again Pavel.

(better late than never I suppose, applies to all three patches in the 
patchset)

Acked-by: Paul Moore <paul.moore@hp.com>

-- 
paul moore
linux security @ hp

^ permalink raw reply

* RE: [PATCH] [IPROUTE2] Update various classifiers' help output forexpected CLASSID syntax
From: Waskiewicz Jr, Peter P @ 2008-02-13 17:22 UTC (permalink / raw)
  To: Jarek Poplawski; +Cc: stephen.hemminger, netdev
In-Reply-To: <20080213085210.GD2542@ff.dom.local>

> > +	fprintf(stderr, "\nNOTE: CLASSID is parsed as hexidecimal 
> > +input.\n");
> 
> s/hexidecimal/hexadecimal/g (?)

Gah!  Thanks Jarek, I can correct and resend.

-PJ Waskiewicz

^ permalink raw reply

* Re: BUG: 2.6.25-rc1: iptables postrouting setup causes oops
From: Haavard Skinnemoen @ 2008-02-13 18:19 UTC (permalink / raw)
  To: Andrew G. Morgan
  Cc: Andrew Morton, Ben Nizette, netfilter-devel, linux-kernel, netdev
In-Reply-To: <47B31DE7.9060400@kernel.org>

On Wed, 13 Feb 2008 08:42:15 -0800
"Andrew G. Morgan" <morgan@kernel.org> wrote:

> However, it is a warning and, for any existing app that doesn't care
> about newly added capabilities, the warning is benign.

Ok, I see. Thanks for explaining.

Haavard

^ permalink raw reply

* [PATCH] [NET 2.6.26]: Add per-connection option to set max TSO frame size
From: PJ Waskiewicz @ 2008-02-13 11:45 UTC (permalink / raw)
  To: davem; +Cc: stephen.hemminger, netdev

Update: changed max_gso_frame_size and sk_gso_max_size from signed to
unsigned - thanks Stephen!

This patch adds the ability for device drivers to control the size of the
TSO frames being sent to them, per TCP connection.  By setting the
netdevice's max_gso_frame_size value, the socket layer will set the GSO
frame size based on that value.  This will propogate into the TCP layer,
and send TSO's of that size to the hardware.

This can be desirable to help tune the bursty nature of TSO on a
per-adapter basis, where one may have 1 GbE and 10 GbE devices coexisting
in a system, one running multiqueue and the other not, etc.

This can also be desirable for devices that cannot support full 64 KB
TSO's, but still want to benefit from some level of segmentation
offloading.

Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
---

 include/linux/netdevice.h |    6 ++++++
 include/net/sock.h        |    2 ++
 net/core/dev.c            |    1 +
 net/core/sock.c           |    6 ++++--
 net/ipv4/tcp_output.c     |    4 ++--
 5 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 047d432..853caca 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -616,6 +616,7 @@ struct net_device
 
 	/* Partially transmitted GSO packet. */
 	struct sk_buff		*gso_skb;
+	u16			max_gso_frame_size;
 
 	/* ingress path synchronizer */
 	spinlock_t		ingress_lock;
@@ -1475,6 +1476,11 @@ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
 		unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
 }
 
+static inline void netif_set_max_gso_size(struct net_device *dev, u16 size)
+{
+	dev->max_gso_frame_size = size;
+}
+
 /* On bonding slaves other than the currently active slave, suppress
  * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
  * ARP on active-backup slaves with arp_validate enabled.
diff --git a/include/net/sock.h b/include/net/sock.h
index 8a7889b..2b07af0 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -151,6 +151,7 @@ struct sock_common {
   *	@sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets
   *	@sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
   *	@sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
+  *	@sk_gso_max_size: Maximum GSO segment size to build
   *	@sk_lingertime: %SO_LINGER l_linger setting
   *	@sk_backlog: always used with the per-socket spinlock held
   *	@sk_callback_lock: used with the callbacks in the end of this struct
@@ -236,6 +237,7 @@ struct sock {
 	gfp_t			sk_allocation;
 	int			sk_route_caps;
 	int			sk_gso_type;
+	__u16			sk_gso_max_size;
 	int			sk_rcvlowat;
 	unsigned long 		sk_flags;
 	unsigned long	        sk_lingertime;
diff --git a/net/core/dev.c b/net/core/dev.c
index 9549417..f635b29 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4022,6 +4022,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
 	}
 
 	dev->egress_subqueue_count = queue_count;
+	dev->max_gso_frame_size = 65536;
 
 	dev->get_stats = internal_stats;
 	netpoll_netdev_init(dev);
diff --git a/net/core/sock.c b/net/core/sock.c
index 433715f..a8b0ae5 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1076,10 +1076,12 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
 	if (sk->sk_route_caps & NETIF_F_GSO)
 		sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
 	if (sk_can_gso(sk)) {
-		if (dst->header_len)
+		if (dst->header_len) {
 			sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
-		else
+		} else {
 			sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
+			sk->sk_gso_max_size = dst->dev->max_gso_frame_size;
+		}
 	}
 }
 EXPORT_SYMBOL_GPL(sk_setup_caps);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index ed750f9..8cd128d 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -998,7 +998,7 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
 	xmit_size_goal = mss_now;
 
 	if (doing_tso) {
-		xmit_size_goal = (65535 -
+		xmit_size_goal = ((sk->sk_gso_max_size - 1) -
 				  inet_csk(sk)->icsk_af_ops->net_header_len -
 				  inet_csk(sk)->icsk_ext_hdr_len -
 				  tp->tcp_header_len);
@@ -1274,7 +1274,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
 	limit = min(send_win, cong_win);
 
 	/* If a full-sized TSO skb can be sent, do it. */
-	if (limit >= 65536)
+	if (limit >= sk->sk_gso_max_size)
 		goto send_now;
 
 	if (sysctl_tcp_tso_win_divisor) {


^ permalink raw reply related

* [PATCH] [IPROUTE2] Update various classifiers' help output for expected CLASSID syntax
From: PJ Waskiewicz @ 2008-02-13 11:49 UTC (permalink / raw)
  To: stephen.hemminger; +Cc: jarka02, netdev

update: Fix the spelling of "hexidecimal"

This updates the help output to specify that CLASSID should be hexidecimal.
This makes sure that a user entering "flowid 1:10" gets his flow put into
band 15 (0x10) and knows why.

Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
---

 doc/actions/actions-general |    3 +++
 tc/f_basic.c                |    1 +
 tc/f_fw.c                   |    1 +
 tc/f_route.c                |    1 +
 tc/f_rsvp.c                 |    1 +
 tc/f_u32.c                  |    1 +
 6 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/doc/actions/actions-general b/doc/actions/actions-general
index 6561eda..70f7cd6 100644
--- a/doc/actions/actions-general
+++ b/doc/actions/actions-general
@@ -88,6 +88,9 @@ tc filter add dev lo parent ffff: protocol ip prio 8 u32 \
 match ip dst 127.0.0.8/32 flowid 1:12 \
 action ipt -j mark --set-mark 2
 
+NOTE: flowid 1:12 is parsed flowid 0x1:0x12.  Make sure if you want flowid
+decimal 12, then use flowid 1:c.
+
 3) A feature i call pipe
 The motivation is derived from Unix pipe mechanism but applied to packets.
 Essentially take a matching packet and pass it through 
diff --git a/tc/f_basic.c b/tc/f_basic.c
index 19a7edf..aab946b 100644
--- a/tc/f_basic.c
+++ b/tc/f_basic.c
@@ -32,6 +32,7 @@ static void explain(void)
 	fprintf(stderr, "\n");
 	fprintf(stderr, "Where: SELECTOR := SAMPLE SAMPLE ...\n");
 	fprintf(stderr, "       FILTERID := X:Y:Z\n");
+	fprintf(stderr, "\nNOTE: CLASSID is parsed as hexadecimal input.\n");
 }
 
 static int basic_parse_opt(struct filter_util *qu, char *handle,
diff --git a/tc/f_fw.c b/tc/f_fw.c
index 6d1490b..b511735 100644
--- a/tc/f_fw.c
+++ b/tc/f_fw.c
@@ -28,6 +28,7 @@ static void explain(void)
 	fprintf(stderr, "Usage: ... fw [ classid CLASSID ] [ police POLICE_SPEC ]\n");
 	fprintf(stderr, "       POLICE_SPEC := ... look at TBF\n");
 	fprintf(stderr, "       CLASSID := X:Y\n");
+	fprintf(stderr, "\nNOTE: CLASSID is parsed as hexadecimal input.\n");
 }
 
 #define usage() return(-1)
diff --git a/tc/f_route.c b/tc/f_route.c
index a41b9d5..67dd49c 100644
--- a/tc/f_route.c
+++ b/tc/f_route.c
@@ -31,6 +31,7 @@ static void explain(void)
 	fprintf(stderr, "                [ flowid CLASSID ] [ police POLICE_SPEC ]\n");
 	fprintf(stderr, "       POLICE_SPEC := ... look at TBF\n");
 	fprintf(stderr, "       CLASSID := X:Y\n");
+	fprintf(stderr, "\nNOTE: CLASSID is parsed as hexadecimal input.\n");
 }
 
 #define usage() return(-1)
diff --git a/tc/f_rsvp.c b/tc/f_rsvp.c
index 13fcf97..7e1e6d9 100644
--- a/tc/f_rsvp.c
+++ b/tc/f_rsvp.c
@@ -34,6 +34,7 @@ static void explain(void)
 	fprintf(stderr, "                u{8|16|32} NUMBER mask MASK at OFFSET}\n");
 	fprintf(stderr, "       POLICE_SPEC := ... look at TBF\n");
 	fprintf(stderr, "       FILTERID := X:Y\n");
+	fprintf(stderr, "\nNOTE: CLASSID is parsed as hexadecimal input.\n");
 }
 
 #define usage() return(-1)
diff --git a/tc/f_u32.c b/tc/f_u32.c
index 91f2838..d75e76c 100644
--- a/tc/f_u32.c
+++ b/tc/f_u32.c
@@ -36,6 +36,7 @@ static void explain(void)
 	fprintf(stderr, "Where: SELECTOR := SAMPLE SAMPLE ...\n");
 	fprintf(stderr, "       SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} | mark } SAMPLE_ARGS [divisor DIVISOR]\n");
 	fprintf(stderr, "       FILTERID := X:Y:Z\n");
+	fprintf(stderr, "\nNOTE: CLASSID is parsed at hexadecimal input.\n");
 }
 
 #define usage() return(-1)


^ permalink raw reply related

* Patch to latest iproute to get it to compile on FC5
From: Ben Greear @ 2008-02-13 19:32 UTC (permalink / raw)
  To: NetDev, Stephen Hemminger

[-- Attachment #1: Type: text/plain, Size: 459 bytes --]

I notice that the latest snapshot and git repository for iproute
will not compile on FC5 due to not finding __constant_hton* symbols
and a lack of the hdlc/ioctl.h file on FC5.

I am attaching a patch that appears to fix the problems for me.

Please consider applying this or something similar.

Signed-off-by:  Ben Greear <greearb@candelatech.com>


Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


[-- Attachment #2: iproute.fc5.patch --]
[-- Type: text/x-patch, Size: 2002 bytes --]

diff --git a/configure b/configure
index dc14e54..f28e4cf 100755
--- a/configure
+++ b/configure
@@ -25,3 +25,22 @@ else
     echo no
 fi
 rm -f /tmp/atmtest.c /tmp/atmtest
+
+echo -n "HDLC IOCTL:   "
+cat >/tmp/hdlctest.c <<EOF
+#include <net/if.h>
+#include <linux/hdlc/ioctl.h>
+int main(int argc, char **argv) {
+        return 0;
+}
+EOF
+gcc -I$INCLUDE -o /tmp/hdlctest /tmp/hdlctest.c >/dev/null 2>&1
+if [ $? -eq 0 ]
+then
+    echo "IPROUTE_CONFIG_HDLC:=y" >>Config
+    echo yes
+else
+    echo no
+fi
+rm -f /tmp/hdlctest.c /tmp/hdlctest
+
diff --git a/include/linux/if.h b/include/linux/if.h
index 40eb61f..9651cc9 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -23,7 +23,10 @@
 #include <linux/socket.h>		/* for "struct sockaddr" et al	*/
 
 #define	IFNAMSIZ	16
+
+#ifdef HAVE_HDLC_IOCTL
 #include <linux/hdlc/ioctl.h>
+#endif
 
 /* Standard interface flags (netdevice->flags). */
 #define	IFF_UP		0x1		/* interface is up		*/
@@ -133,6 +136,7 @@ struct if_settings
 {
 	unsigned int type;	/* Type of physical device or protocol */
 	unsigned int size;	/* Size of the data allocated by the caller */
+#ifdef HAVE_HDLC_IOCTL
 	union {
 		/* {atm/eth/dsl}_settings anyone ? */
 		raw_hdlc_proto	 *raw_hdlc;
@@ -145,6 +149,7 @@ struct if_settings
 		sync_serial_settings *sync;
 		te1_settings	 *te1;
 	} ifs_ifsu;
+#endif
 };
 
 /*
diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
index 228eb4e..0eb5b04 100644
--- a/include/linux/if_tunnel.h
+++ b/include/linux/if_tunnel.h
@@ -2,6 +2,7 @@
 #define _IF_TUNNEL_H_
 
 #include <linux/types.h>
+#include <asm/byteorder.h>
 
 #define SIOCGETTUNNEL   (SIOCDEVPRIVATE + 0)
 #define SIOCADDTUNNEL   (SIOCDEVPRIVATE + 1)
diff --git a/lib/Makefile b/lib/Makefile
index bc270bf..1c51a42 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -1,3 +1,9 @@
+include ../Config
+
+ifeq ($(IPROUTE_CONFIG_HDLC),y)
+   CFLAGS += -DHAVE_HDLC_IOCTL
+endif
+
 
 UTILOBJ=utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o inet_proto.o
 

^ permalink raw reply related

* Re: Patch to latest iproute to get it to compile on FC5
From: Stephen Hemminger @ 2008-02-13 19:56 UTC (permalink / raw)
  To: Ben Greear; +Cc: NetDev
In-Reply-To: <47B345D0.1020707@candelatech.com>

On Wed, 13 Feb 2008 11:32:32 -0800
Ben Greear <greearb@candelatech.com> wrote:

> I notice that the latest snapshot and git repository for iproute
> will not compile on FC5 due to not finding __constant_hton* symbols
> and a lack of the hdlc/ioctl.h file on FC5.
> 
> I am attaching a patch that appears to fix the problems for me.
> 
> Please consider applying this or something similar.
> 
> Signed-off-by:  Ben Greear <greearb@candelatech.com>
> 
> 
> Thanks,
> Ben
> 

No. please don't change the configure script.
And the linux/if.h comes from kernel stripped headers so it should
not get crufted up by ifdef's.

Short term fix is to include stripped hdlc header if needed.
Long fix is to get rid of hdlc dependency if possible.

-- 
Stephen Hemminger <stephen.hemminger@vyatta.com>

^ permalink raw reply

* [PATCH 2/3] fib_trie: improve output format for /proc/net/fib_trie
From: Stephen Hemminger @ 2008-02-13 19:58 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20080213195805.493794050@vyatta.com>

[-- Attachment #1: fib-trie-format.patch --]
[-- Type: text/plain, Size: 5134 bytes --]

Make output format prettier (more tree like).

   <local>:
   --- 0.0.0.0/0
     |--- 10.111.111.0/24
     |  +-- 10.111.111.0/32 link broadcast
     |  |--- 10.111.111.254/31
     |  |  +-- 10.111.111.254/32 host local
     |  |  +-- 10.111.111.255/32 link broadcast
     |--- 127.0.0.0/8
     |  |--- 127.0.0.0/31
     |  |  +-- 127.0.0.0/32 link broadcast
     |  |  +-- 127.0.0.0/8 host local
     |  |  +-- 127.0.0.1/32 host local
     |  +-- 127.255.255.255/32 link broadcast
     |--- 192.168.1.0/24
     |  |--- 192.168.1.0/28
     |  |  +-- 192.168.1.0/32 link broadcast
     |  |  +-- 192.168.1.9/32 host local
     |  +-- 192.168.1.255/32 link broadcast
   <main>:
   --- 0.0.0.0/0
     |--- 0.0.0.0/4
     |  +-- 0.0.0.0/0 universe unicast
     |  +-- 10.111.111.0/24 link unicast
     +-- 169.254.0.0/16 link unicast
     +-- 192.168.1.0/24 link unicast
   
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
---
 net/ipv4/fib_trie.c |  106 ++++++++++++++++++++++++++------------------------
 1 files changed, 55 insertions(+), 51 deletions(-)

--- a/net/ipv4/fib_trie.c	2008-02-13 11:33:43.000000000 -0800
+++ b/net/ipv4/fib_trie.c	2008-02-13 11:41:23.000000000 -0800
@@ -2334,46 +2334,57 @@ static void fib_trie_seq_stop(struct seq
 	rcu_read_unlock();
 }
 
+/* print left side of tree */
 static void seq_indent(struct seq_file *seq, int n)
 {
-	while (n-- > 0) seq_puts(seq, "   ");
+	while (n-- > 0)
+		seq_puts(seq, "  |");
 }
 
-static inline const char *rtn_scope(char *buf, size_t len, enum rt_scope_t s)
+static const char *rtn_type_names[__RTN_MAX] = {
+	[RTN_UNSPEC]	= "unspec",
+	[RTN_UNICAST]	= "unicast",
+	[RTN_LOCAL]	= "local",
+	[RTN_BROADCAST] = "broadcast",
+	[RTN_ANYCAST]	= "anycast",
+	[RTN_MULTICAST] = "multicast",
+	[RTN_BLACKHOLE] = "blackhole",
+	[RTN_UNREACHABLE] = "unreachable",
+	[RTN_PROHIBIT] 	= "prohibit",
+	[RTN_THROW]	= "throw",
+	[RTN_NAT]	= "nat",
+	[RTN_XRESOLVE]	= "xresolve",
+};
+
+static void fib_trie_show_alias(struct seq_file *seq, const struct fib_alias *fa)
 {
-	switch (s) {
-	case RT_SCOPE_UNIVERSE: return "universe";
-	case RT_SCOPE_SITE:	return "site";
-	case RT_SCOPE_LINK:	return "link";
-	case RT_SCOPE_HOST:	return "host";
-	case RT_SCOPE_NOWHERE:	return "nowhere";
+	switch (fa->fa_scope) {
+	case RT_SCOPE_UNIVERSE:
+		seq_puts(seq, "universe");
+		break;
+	case RT_SCOPE_SITE:
+		seq_puts(seq,  "site");
+		break;
+	case RT_SCOPE_LINK:
+		seq_puts(seq,  "link");
+		break;
+	case RT_SCOPE_HOST:
+		seq_puts(seq,  "host");
+		break;
+	case RT_SCOPE_NOWHERE:
+		seq_puts(seq,  "nowhere");
+		break;
 	default:
-		snprintf(buf, len, "scope=%d", s);
-		return buf;
+		seq_printf(seq, "scope:%d", fa->fa_scope);
 	}
-}
 
-static const char *rtn_type_names[__RTN_MAX] = {
-	[RTN_UNSPEC] = "UNSPEC",
-	[RTN_UNICAST] = "UNICAST",
-	[RTN_LOCAL] = "LOCAL",
-	[RTN_BROADCAST] = "BROADCAST",
-	[RTN_ANYCAST] = "ANYCAST",
-	[RTN_MULTICAST] = "MULTICAST",
-	[RTN_BLACKHOLE] = "BLACKHOLE",
-	[RTN_UNREACHABLE] = "UNREACHABLE",
-	[RTN_PROHIBIT] = "PROHIBIT",
-	[RTN_THROW] = "THROW",
-	[RTN_NAT] = "NAT",
-	[RTN_XRESOLVE] = "XRESOLVE",
-};
+	if (fa->fa_type < __RTN_MAX && rtn_type_names[fa->fa_type])
+		seq_printf(seq, " %s", rtn_type_names[fa->fa_type]);
+	else
+		seq_printf(seq, " type:%u", fa->fa_type);
 
-static inline const char *rtn_type(char *buf, size_t len, unsigned t)
-{
-	if (t < __RTN_MAX && rtn_type_names[t])
-		return rtn_type_names[t];
-	snprintf(buf, len, "type %u", t);
-	return buf;
+	if (fa->fa_tos)
+		seq_printf(seq, " tos:%#x", fa->fa_tos);
 }
 
 /* Pretty print the trie */
@@ -2396,10 +2407,8 @@ static int fib_trie_seq_show(struct seq_
 		struct tnode *tn = (struct tnode *) n;
 		__be32 prf = htonl(mask_pfx(tn->key, tn->pos));
 
-		seq_indent(seq, iter->depth-1);
-		seq_printf(seq, "  +-- %d.%d.%d.%d/%d %d %d %d\n",
-			   NIPQUAD(prf), tn->pos, tn->bits, tn->full_children,
-			   tn->empty_children);
+		seq_indent(seq, iter->depth - 1);
+		seq_printf(seq, "--- %d.%d.%d.%d/%d\n", NIPQUAD(prf), tn->pos);
 
 	} else {
 		struct leaf *l = (struct leaf *) n;
@@ -2407,24 +2416,19 @@ static int fib_trie_seq_show(struct seq_
 		struct hlist_node *node;
 		__be32 val = htonl(l->key);
 
-		seq_indent(seq, iter->depth);
-		seq_printf(seq, "  |-- %d.%d.%d.%d\n", NIPQUAD(val));
-
 		hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
 			struct fib_alias *fa;
 
-			list_for_each_entry_rcu(fa, &li->falh, fa_list) {
-				char buf1[32], buf2[32];
+			seq_indent(seq, iter->depth - 1);
+			seq_printf(seq, "  +-- %d.%d.%d.%d/%d ",
+				   NIPQUAD(val), li->plen);
 
-				seq_indent(seq, iter->depth+1);
-				seq_printf(seq, "  /%d %s %s", li->plen,
-					   rtn_scope(buf1, sizeof(buf1),
-						     fa->fa_scope),
-					   rtn_type(buf2, sizeof(buf2),
-						    fa->fa_type));
-				if (fa->fa_tos)
-					seq_printf(seq, " tos=%d", fa->fa_tos);
-				seq_putc(seq, '\n');
+			list_for_each_entry_rcu(fa, &li->falh, fa_list) {
+				fib_trie_show_alias(seq, fa);
+				if (list_is_last(&fa->fa_list, &li->falh))
+					seq_putc(seq, '\n');
+				else
+					seq_puts(seq, ", ");
 			}
 		}
 	}

-- 
Stephen Hemminger <shemminger@vyatta.com>


^ permalink raw reply

* [PATCH 0/3] fib_trie: update (redo)
From: Stephen Hemminger @ 2008-02-13 19:58 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

This supersedes yesterday's changes. It doesn't change list.h
because that seems to make people queasy, even if it is a clone
of existing code.  Moves the trie related special files to debugfs.

-- 
Stephen Hemminger <shemminger@vyatta.com>


^ permalink raw reply

* [PATCH 1/3] fib_trie: move statistics to debugfs
From: Stephen Hemminger @ 2008-02-13 19:58 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20080213195805.493794050@vyatta.com>

[-- Attachment #1: fib-trie-debugfs.patch --]
[-- Type: text/plain, Size: 7952 bytes --]

Don't want /proc/net/fib_trie and /proc/net/fib_triestat to become
permanent kernel space ABI issues, so move to the safer confines of debugfs.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

---
 net/ipv4/Kconfig    |    9 ++-
 net/ipv4/fib_trie.c |  127 +++++++++++++++++++++++++++++++++-------------------
 2 files changed, 86 insertions(+), 50 deletions(-)

--- a/net/ipv4/Kconfig	2008-02-13 10:58:51.000000000 -0800
+++ b/net/ipv4/Kconfig	2008-02-13 10:59:06.000000000 -0800
@@ -85,11 +85,12 @@ endchoice
 config IP_FIB_HASH
 	def_bool ASK_IP_FIB_HASH || !IP_ADVANCED_ROUTER
 
-config IP_FIB_TRIE_STATS
-	bool "FIB TRIE statistics"
-	depends on IP_FIB_TRIE
+config IP_FIB_TRIE_DEBUG
+	bool "FIB TRIE debugging information"
+	depends on IP_FIB_TRIE && DEBUG_FS
 	---help---
-	  Keep track of statistics on structure of FIB TRIE table.
+	  Provides interface for looking at internal structure, and
+	  statistics on for the  FIB TRIE table.
 	  Useful for testing and measuring TRIE performance.
 
 config IP_MULTIPLE_TABLES
--- a/net/ipv4/fib_trie.c	2008-02-13 10:58:51.000000000 -0800
+++ b/net/ipv4/fib_trie.c	2008-02-13 11:33:43.000000000 -0800
@@ -68,6 +68,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/proc_fs.h>
+#include <linux/debugfs.h>
 #include <linux/rcupdate.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
@@ -126,7 +127,8 @@ struct tnode {
 	struct node *child[0];
 };
 
-#ifdef CONFIG_IP_FIB_TRIE_STATS
+#ifdef CONFIG_IP_FIB_TRIE_DEBUG
+
 struct trie_use_stats {
 	unsigned int gets;
 	unsigned int backtrack;
@@ -135,7 +137,6 @@ struct trie_use_stats {
 	unsigned int null_node_hit;
 	unsigned int resize_node_skipped;
 };
-#endif
 
 struct trie_stat {
 	unsigned int totdepth;
@@ -146,10 +147,11 @@ struct trie_stat {
 	unsigned int prefixes;
 	unsigned int nodesizes[MAX_STAT_DEPTH];
 };
+#endif
 
 struct trie {
 	struct node *trie;
-#ifdef CONFIG_IP_FIB_TRIE_STATS
+#ifdef CONFIG_IP_FIB_TRIE_DEBUG
 	struct trie_use_stats stats;
 #endif
 };
@@ -588,7 +590,7 @@ static struct node *resize(struct trie *
 
 		if (IS_ERR(tn)) {
 			tn = old_tn;
-#ifdef CONFIG_IP_FIB_TRIE_STATS
+#ifdef CONFIG_IP_FIB_TRIE_DEBUG
 			t->stats.resize_node_skipped++;
 #endif
 			break;
@@ -631,7 +633,7 @@ static struct node *resize(struct trie *
 		tn = halve(t, tn);
 		if (IS_ERR(tn)) {
 			tn = old_tn;
-#ifdef CONFIG_IP_FIB_TRIE_STATS
+#ifdef CONFIG_IP_FIB_TRIE_DEBUG
 			t->stats.resize_node_skipped++;
 #endif
 			break;
@@ -1341,7 +1343,7 @@ static int check_leaf(struct trie *t, st
 		err = fib_semantic_match(&li->falh, flp, res,
 					 htonl(l->key), mask, plen);
 
-#ifdef CONFIG_IP_FIB_TRIE_STATS
+#ifdef CONFIG_IP_FIB_TRIE_DEBUG
 		if (err <= 0)
 			t->stats.semantic_match_passed++;
 		else
@@ -1376,7 +1378,7 @@ static int fn_trie_lookup(struct fib_tab
 	if (!n)
 		goto failed;
 
-#ifdef CONFIG_IP_FIB_TRIE_STATS
+#ifdef CONFIG_IP_FIB_TRIE_DEBUG
 	t->stats.gets++;
 #endif
 
@@ -1403,7 +1405,7 @@ static int fn_trie_lookup(struct fib_tab
 		n = tnode_get_child(pn, cindex);
 
 		if (n == NULL) {
-#ifdef CONFIG_IP_FIB_TRIE_STATS
+#ifdef CONFIG_IP_FIB_TRIE_DEBUG
 			t->stats.null_node_hit++;
 #endif
 			goto backtrace;
@@ -1546,7 +1548,7 @@ backtrace:
 			pn = parent;
 			chopped_off = 0;
 
-#ifdef CONFIG_IP_FIB_TRIE_STATS
+#ifdef CONFIG_IP_FIB_TRIE_DEBUG
 			t->stats.backtrack++;
 #endif
 			goto backtrace;
@@ -2022,7 +2024,8 @@ struct fib_table *fib_hash_table(u32 id)
 	return tb;
 }
 
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_IP_FIB_TRIE_DEBUG
+
 /* Depth first Trie walk iterator */
 struct fib_trie_iter {
 	struct seq_net_private p;
@@ -2147,7 +2150,7 @@ static void trie_collect_stats(struct tr
 }
 
 /*
- *	This outputs /proc/net/fib_triestats
+ *	This outputs debugfs/fib/triestats
  */
 static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
 {
@@ -2189,7 +2192,6 @@ static void trie_show_stats(struct seq_f
 	seq_printf(seq, "Total size: %u  kB\n", (bytes + 1023) / 1024);
 }
 
-#ifdef CONFIG_IP_FIB_TRIE_STATS
 static void trie_show_usage(struct seq_file *seq,
 			    const struct trie_use_stats *stats)
 {
@@ -2204,7 +2206,7 @@ static void trie_show_usage(struct seq_f
 	seq_printf(seq, "skipped node resize = %u\n\n",
 		   stats->resize_node_skipped);
 }
-#endif /*  CONFIG_IP_FIB_TRIE_STATS */
+
 
 static void fib_trie_show(struct seq_file *seq, const char *name,
 			  struct trie *trie)
@@ -2214,9 +2216,7 @@ static void fib_trie_show(struct seq_fil
 	trie_collect_stats(trie, &stat);
 	seq_printf(seq, "%s:\n", name);
 	trie_show_stats(seq, &stat);
-#ifdef CONFIG_IP_FIB_TRIE_STATS
 	trie_show_usage(seq, &trie->stats);
-#endif
 }
 
 static int fib_triestat_seq_show(struct seq_file *seq, void *v)
@@ -2242,18 +2242,12 @@ static int fib_triestat_seq_show(struct 
 
 static int fib_triestat_seq_open(struct inode *inode, struct file *file)
 {
-	int err;
-	struct net *net;
+	struct net *net = maybe_get_net((struct net *)inode->i_private);
 
-	net = get_proc_net(inode);
-	if (net == NULL)
+	if (!net)
 		return -ENXIO;
-	err = single_open(file, fib_triestat_seq_show, net);
-	if (err < 0) {
-		put_net(net);
-		return err;
-	}
-	return 0;
+
+	return single_open(file, fib_triestat_seq_show, net);
 }
 
 static int fib_triestat_seq_release(struct inode *ino, struct file *f)
@@ -2447,8 +2441,19 @@ static const struct seq_operations fib_t
 
 static int fib_trie_seq_open(struct inode *inode, struct file *file)
 {
-	return seq_open_net(inode, file, &fib_trie_seq_ops,
-			    sizeof(struct fib_trie_iter));
+	struct net *net = maybe_get_net((struct net *)inode->i_private);
+	struct fib_trie_iter *iter;
+
+	if (!net)
+		return -ENXIO;
+
+	iter = __seq_open_private(file, &fib_trie_seq_ops, sizeof(*iter));
+	if (!iter) {
+		put_net(net);
+		return -ENOMEM;
+	}
+	iter->p.net = net;
+	return 0;
 }
 
 static const struct file_operations fib_trie_fops = {
@@ -2459,6 +2464,51 @@ static const struct file_operations fib_
 	.release = seq_release_net,
 };
 
+
+static struct dentry *fib_debug, *trie_debug, *triestat_debug;
+
+static void __net_init trie_debug_init(struct net *net)
+{
+	fib_debug = debugfs_create_dir("fib", NULL);
+	if (!fib_debug || IS_ERR(fib_debug))
+		goto out1;
+
+	trie_debug = debugfs_create_file("trie", S_IRUGO, fib_debug,
+					 net, &fib_trie_fops);
+	if (!trie_debug || IS_ERR(trie_debug))
+		goto out2;
+
+	triestat_debug = debugfs_create_file("triestat", S_IRUGO, fib_debug,
+					     net, &fib_triestat_fops);
+	if (!triestat_debug || IS_ERR(triestat_debug))
+		goto out3;
+
+	hold_net(net);
+	return;
+out3:
+	debugfs_remove(trie_debug);
+out2:
+	debugfs_remove(fib_debug);
+out1:
+	fib_debug = NULL;
+}
+
+static void __net_exit trie_debug_exit(struct net *net)
+{
+	if (!fib_debug)
+		return;
+
+	debugfs_remove(trie_debug);
+	debugfs_remove(triestat_debug);
+	debugfs_remove(fib_debug);
+	put_net(net);
+}
+#else
+#define trie_debug_init(n)
+#define trie_debug_exit(n)
+#endif
+
+#ifdef CONFIG_PROC_FS
 struct fib_route_iter {
 	struct seq_net_private p;
 	struct trie *main_trie;
@@ -2632,34 +2682,19 @@ static const struct file_operations fib_
 	.llseek = seq_lseek,
 	.release = seq_release_net,
 };
+#endif /* CONFIG_PROC_FS */
 
 int __net_init fib_proc_init(struct net *net)
 {
-	if (!proc_net_fops_create(net, "fib_trie", S_IRUGO, &fib_trie_fops))
-		goto out1;
-
-	if (!proc_net_fops_create(net, "fib_triestat", S_IRUGO,
-				  &fib_triestat_fops))
-		goto out2;
-
 	if (!proc_net_fops_create(net, "route", S_IRUGO, &fib_route_fops))
-		goto out3;
+		return -ENOMEM;
 
+	trie_debug_init(net);
 	return 0;
-
-out3:
-	proc_net_remove(net, "fib_triestat");
-out2:
-	proc_net_remove(net, "fib_trie");
-out1:
-	return -ENOMEM;
 }
 
 void __net_exit fib_proc_exit(struct net *net)
 {
-	proc_net_remove(net, "fib_trie");
-	proc_net_remove(net, "fib_triestat");
 	proc_net_remove(net, "route");
+	trie_debug_exit(net);
 }
-
-#endif /* CONFIG_PROC_FS */

-- 
Stephen Hemminger <shemminger@vyatta.com>


^ permalink raw reply

* [PATCH 3/3] fib_trie: print statistics for multiple tables
From: Stephen Hemminger @ 2008-02-13 19:58 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Stephen Hemminger
In-Reply-To: <20080213195805.493794050@vyatta.com>

[-- Attachment #1: fib-trie-tables.patch --]
[-- Type: text/plain, Size: 7257 bytes --]

Make debugfs/fib/trie and debugfs/fib/triestat handle
multiple (alternate) route tables.

Note: this usage of seq_file doesn't need/want SEQ_START_TOKEN

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/net/ipv4/fib_trie.c	2008-02-13 11:41:23.000000000 -0800
+++ b/net/ipv4/fib_trie.c	2008-02-13 11:41:35.000000000 -0800
@@ -2029,14 +2029,13 @@ struct fib_table *fib_hash_table(u32 id)
 /* Depth first Trie walk iterator */
 struct fib_trie_iter {
 	struct seq_net_private p;
-	struct trie *trie_local, *trie_main;
+	struct fib_table *tb;
 	struct tnode *tnode;
-	struct trie *trie;
 	unsigned index;
 	unsigned depth;
 };
 
-static struct node *fib_trie_get_next(struct fib_trie_iter *iter)
+static struct node *trie_get_next(struct fib_trie_iter *iter)
 {
 	struct tnode *tn = iter->tnode;
 	unsigned cindex = iter->index;
@@ -2081,34 +2080,29 @@ rescan:
 	return NULL;
 }
 
-static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
-				       struct trie *t)
+static struct node *trie_get_first(struct fib_trie_iter *iter,
+				   struct trie *t)
 {
-	struct node *n ;
+	struct node *n;
 
 	if (!t)
 		return NULL;
 
 	n = rcu_dereference(t->trie);
-
-	if (!iter)
+	if (!n)
 		return NULL;
 
-	if (n) {
-		if (IS_TNODE(n)) {
-			iter->tnode = (struct tnode *) n;
-			iter->trie = t;
-			iter->index = 0;
-			iter->depth = 1;
-		} else {
-			iter->tnode = NULL;
-			iter->trie  = t;
-			iter->index = 0;
-			iter->depth = 0;
-		}
-		return n;
+	if (IS_TNODE(n)) {
+		iter->tnode = (struct tnode *) n;
+		iter->index = 0;
+		iter->depth = 1;
+	} else {
+		iter->tnode = NULL;
+		iter->index = 0;
+		iter->depth = 0;
 	}
-	return NULL;
+
+	return n;
 }
 
 static void trie_collect_stats(struct trie *t, struct trie_stat *s)
@@ -2119,8 +2113,7 @@ static void trie_collect_stats(struct tr
 	memset(s, 0, sizeof(*s));
 
 	rcu_read_lock();
-	for (n = fib_trie_get_first(&iter, t); n;
-	     n = fib_trie_get_next(&iter)) {
+	for (n = trie_get_first(&iter, t); n; n = trie_get_next(&iter)) {
 		if (IS_LEAF(n)) {
 			struct leaf *l = (struct leaf *)n;
 			struct leaf_info *li;
@@ -2207,35 +2200,46 @@ static void trie_show_usage(struct seq_f
 		   stats->resize_node_skipped);
 }
 
-
-static void fib_trie_show(struct seq_file *seq, const char *name,
-			  struct trie *trie)
+static void fib_table_print(struct seq_file *seq, struct fib_table *tb)
 {
-	struct trie_stat stat;
-
-	trie_collect_stats(trie, &stat);
-	seq_printf(seq, "%s:\n", name);
-	trie_show_stats(seq, &stat);
-	trie_show_usage(seq, &trie->stats);
+	if (tb->tb_id == RT_TABLE_LOCAL)
+		seq_puts(seq, "Local:\n");
+	else if (tb->tb_id == RT_TABLE_MAIN)
+		seq_puts(seq, "Main:\n");
+	else
+		seq_printf(seq, "Id %d:\n", tb->tb_id);
 }
 
+
 static int fib_triestat_seq_show(struct seq_file *seq, void *v)
 {
 	struct net *net = (struct net *)seq->private;
-	struct fib_table *tb;
+	unsigned int h;
 
 	seq_printf(seq,
 		   "Basic info: size of leaf:"
 		   " %Zd bytes, size of tnode: %Zd bytes.\n",
 		   sizeof(struct leaf), sizeof(struct tnode));
 
-	tb = fib_get_table(net, RT_TABLE_LOCAL);
-	if (tb)
-		fib_trie_show(seq, "Local", (struct trie *) tb->tb_data);
-
-	tb = fib_get_table(net, RT_TABLE_MAIN);
-	if (tb)
-		fib_trie_show(seq, "Main", (struct trie *) tb->tb_data);
+	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
+		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
+		struct hlist_node *node;
+		struct fib_table *tb;
+
+		hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
+			struct trie *t = (struct trie *) tb->tb_data;
+			struct trie_stat stat;
+
+			if (!t)
+				continue;
+
+			fib_table_print(seq, tb);
+
+			trie_collect_stats(t, &stat);
+			trie_show_stats(seq, &stat);
+			trie_show_usage(seq, &t->stats);
+		}
+	}
 
 	return 0;
 }
@@ -2265,23 +2269,30 @@ static const struct file_operations fib_
 	.release = fib_triestat_seq_release,
 };
 
-static struct node *fib_trie_get_idx(struct fib_trie_iter *iter,
-				      loff_t pos)
+static struct node *fib_trie_get_idx(struct fib_trie_iter *iter, loff_t pos)
 {
+	struct net *net = iter->p.net;
 	loff_t idx = 0;
-	struct node *n;
+	unsigned int h;
 
-	for (n = fib_trie_get_first(iter, iter->trie_local);
-	     n; ++idx, n = fib_trie_get_next(iter)) {
-		if (pos == idx)
-			return n;
-	}
+	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
+		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
+		struct hlist_node *node;
+		struct fib_table *tb;
 
-	for (n = fib_trie_get_first(iter, iter->trie_main);
-	     n; ++idx, n = fib_trie_get_next(iter)) {
-		if (pos == idx)
-			return n;
+		hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
+			struct node *n;
+
+			for (n = trie_get_first(iter,
+						(struct trie *) tb->tb_data);
+			     n; n = trie_get_next(iter))
+				if (pos == idx++) {
+					iter->tb = tb;
+					return n;
+				}
+		}
 	}
+
 	return NULL;
 }
 
@@ -2289,43 +2300,52 @@ static void *fib_trie_seq_start(struct s
 	__acquires(RCU)
 {
 	struct fib_trie_iter *iter = seq->private;
-	struct fib_table *tb;
 
-	if (!iter->trie_local) {
-		tb = fib_get_table(iter->p.net, RT_TABLE_LOCAL);
-		if (tb)
-			iter->trie_local = (struct trie *) tb->tb_data;
-	}
-	if (!iter->trie_main) {
-		tb = fib_get_table(iter->p.net, RT_TABLE_MAIN);
-		if (tb)
-			iter->trie_main = (struct trie *) tb->tb_data;
-	}
 	rcu_read_lock();
-	if (*pos == 0)
-		return SEQ_START_TOKEN;
-	return fib_trie_get_idx(iter, *pos - 1);
+	return fib_trie_get_idx(iter, *pos);
 }
 
+
+
 static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	struct fib_trie_iter *iter = seq->private;
-	void *l = v;
+	struct net *net = iter->p.net;
+	struct fib_table *tb = iter->tb;
+	struct hlist_node *tb_node;
+	unsigned int h;
+	struct node *n;
 
 	++*pos;
-	if (v == SEQ_START_TOKEN)
-		return fib_trie_get_idx(iter, 0);
+	/* next node in same table */
+	n = trie_get_next(iter);
+	if (n)
+		return n;
 
-	v = fib_trie_get_next(iter);
-	BUG_ON(v == l);
-	if (v)
-		return v;
-
-	/* continue scan in next trie */
-	if (iter->trie == iter->trie_local)
-		return fib_trie_get_first(iter, iter->trie_main);
+	/* walk rest of this hash chain */
+	h = tb->tb_id & (FIB_TABLE_HASHSZ - 1);
+	while ( (tb_node = rcu_dereference(tb->tb_hlist.next)) ) {
+		tb = hlist_entry(tb_node, struct fib_table, tb_hlist);
+		n = trie_get_first(iter, (struct trie *) tb->tb_data);
+		if (n)
+			goto found;
+	}
+
+	/* new hash chain */
+	while (++h < FIB_TABLE_HASHSZ) {
+		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
+		hlist_for_each_entry_rcu(tb, tb_node, head, tb_hlist) {
+			n = trie_get_first(iter, (struct trie *) tb->tb_data);
+			if (n)
+				goto found;
+		}
+	}
 
 	return NULL;
+
+found:
+	iter->tb = tb;
+	return n;
 }
 
 static void fib_trie_seq_stop(struct seq_file *seq, void *v)
@@ -2393,15 +2413,8 @@ static int fib_trie_seq_show(struct seq_
 	const struct fib_trie_iter *iter = seq->private;
 	struct node *n = v;
 
-	if (v == SEQ_START_TOKEN)
-		return 0;
-
-	if (!node_parent_rcu(n)) {
-		if (iter->trie == iter->trie_local)
-			seq_puts(seq, "<local>:\n");
-		else
-			seq_puts(seq, "<main>:\n");
-	}
+	if (!node_parent_rcu(n))
+		fib_table_print(seq, iter->tb);
 
 	if (IS_TNODE(n)) {
 		struct tnode *tn = (struct tnode *) n;

-- 
Stephen Hemminger <shemminger@vyatta.com>


^ permalink raw reply

* 64bit counters: iproute(netlink) vs ifconfig
From: Krzysztof Oledzki @ 2008-02-13 20:20 UTC (permalink / raw)
  To: netdev

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1212 bytes --]

Hello,

Just discovered that counters returned by the "ip" tool are truncated:

# ip -s link show bond0
1: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue
     link/ether 00:1d:09:67:6e:2f brd ff:ff:ff:ff:ff:ff
     RX: bytes  packets  errors  dropped overrun mcast
     2485605521 9010211  0       0       0       6
     TX: bytes  packets  errors  dropped carrier collsns
     3023237974 9345397  0       0       0       0

# ifconfig bond0
bond0     Link encap:Ethernet  HWaddr 00:1D:09:67:6E:2F
           inet addr:192.168.152.62  Bcast:192.168.152.255  Mask:255.255.255.0
           inet6 addr: fe80::21d:9ff:fe67:6e2f/64 Scope:Link
           UP BROADCAST RUNNING MASTER MULTICAST  MTU:1500  Metric:1
           RX packets:9010367 errors:0 dropped:351 overruns:0 frame:0
           TX packets:9345521 errors:0 dropped:0 overruns:0 carrier:0
           collisions:0 txqueuelen:0
           RX bytes:2485631020 (2370.4 Mb)  TX bytes:7318232294 (6979.2 Mb)

Is it possible to get 64-bit counters in ip via netlink? Struct 
rtnl_link_stats does not look very optimistic, as it has rx_bytes/tx_bytes 
defined with __u32.

Best regards,

 				Krzysztof Olędzki

^ permalink raw reply

* Re: Patch to latest iproute to get it to compile on FC5
From: Stephen Hemminger @ 2008-02-13 20:34 UTC (permalink / raw)
  To: Ben Greear; +Cc: NetDev
In-Reply-To: <47B345D0.1020707@candelatech.com>

On Wed, 13 Feb 2008 11:32:32 -0800
Ben Greear <greearb@candelatech.com> wrote:

> I notice that the latest snapshot and git repository for iproute
> will not compile on FC5 due to not finding __constant_hton* symbols
> and a lack of the hdlc/ioctl.h file on FC5.
> 
> I am attaching a patch that appears to fix the problems for me.
> 
> Please consider applying this or something similar.
> 
> Signed-off-by:  Ben Greear <greearb@candelatech.com>
> 
> 
> Thanks,
> Ben
> 

I added include/linux/hdlc/ioctl.h to the santized headers in the
current git.

-- 
Stephen Hemminger <stephen.hemminger@vyatta.com>

^ permalink raw reply

* Re: 64bit counters: iproute(netlink) vs ifconfig
From: Stephen Hemminger @ 2008-02-13 20:35 UTC (permalink / raw)
  To: netdev
In-Reply-To: <Pine.LNX.4.64.0802132114110.16999@bizon.gios.gov.pl>

On Wed, 13 Feb 2008 21:20:59 +0100 (CET)
Krzysztof Oledzki <olel@ans.pl> wrote:

> Hello,
> 
> Just discovered that counters returned by the "ip" tool are truncated:
> 
> # ip -s link show bond0
> 1: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue
>      link/ether 00:1d:09:67:6e:2f brd ff:ff:ff:ff:ff:ff
>      RX: bytes  packets  errors  dropped overrun mcast
>      2485605521 9010211  0       0       0       6
>      TX: bytes  packets  errors  dropped carrier collsns
>      3023237974 9345397  0       0       0       0
> 
> # ifconfig bond0
> bond0     Link encap:Ethernet  HWaddr 00:1D:09:67:6E:2F
>            inet addr:192.168.152.62  Bcast:192.168.152.255  Mask:255.255.255.0
>            inet6 addr: fe80::21d:9ff:fe67:6e2f/64 Scope:Link
>            UP BROADCAST RUNNING MASTER MULTICAST  MTU:1500  Metric:1
>            RX packets:9010367 errors:0 dropped:351 overruns:0 frame:0
>            TX packets:9345521 errors:0 dropped:0 overruns:0 carrier:0
>            collisions:0 txqueuelen:0
>            RX bytes:2485631020 (2370.4 Mb)  TX bytes:7318232294 (6979.2 Mb)
> 
> Is it possible to get 64-bit counters in ip via netlink? Struct 
> rtnl_link_stats does not look very optimistic, as it has rx_bytes/tx_bytes 
> defined with __u32.
> 
> Best regards,
> 
>  				Krzysztof Olędzki

The problem is the kernel binary API is now hard coded to 32 bit values.

-- 
Stephen Hemminger <stephen.hemminger@vyatta.com>



^ permalink raw reply

* Re: [PATCh TAKE 2] [IPROUTE2] Add addrlabel sub-command.
From: Stephen Hemminger @ 2008-02-13 20:37 UTC (permalink / raw)
  To: netdev
In-Reply-To: <20080214.032012.71214842.yoshfuji@linux-ipv6.org>

On Thu, 14 Feb 2008 03:20:12 +1100 (EST)
YOSHIFUJI Hideaki / 吉藤英明  <yoshfuji@linux-ipv6.org> wrote:

> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> ---
> diff --git a/ip/Makefile b/ip/Makefile
> index b427d58..d908817 100644
> --- a/ip/Makefile
> +++ b/ip/Makefile
> @@ -1,4 +1,4 @@
> -IPOBJ=ip.o ipaddress.o iproute.o iprule.o \
> +IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o \
>      rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o \
>      ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o \
>      ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
> diff --git a/ip/ip.c b/ip/ip.c
> index aeb8c68..c4c773f 100644
> --- a/ip/ip.c
> +++ b/ip/ip.c
> @@ -46,8 +46,8 @@ static void usage(void)
>  	fprintf(stderr,
>  "Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n"
>  "       ip [ -force ] [-batch filename\n"
> -"where  OBJECT := { link | addr | route | rule | neigh | ntable | tunnel |\n"
> -"                   maddr | mroute | monitor | xfrm }\n"
> +"where  OBJECT := { link | addr | addrlabel | route | rule | neigh | ntable |\n"
> +"                   tunnel | maddr | mroute | monitor | xfrm }\n"
>  "       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
>  "                    -f[amily] { inet | inet6 | ipx | dnet | link } |\n"
>  "                    -o[neline] | -t[imestamp] }\n");
> @@ -64,6 +64,7 @@ static const struct cmd {
>  	int (*func)(int argc, char **argv);
>  } cmds[] = {
>  	{ "address", 	do_ipaddr },
> +	{ "addrlabel",	do_ipaddrlabel },
>  	{ "maddress",	do_multiaddr },
>  	{ "route",	do_iproute },
>  	{ "rule",	do_iprule },
> diff --git a/ip/ip_common.h b/ip/ip_common.h
> index 39f2507..1bbd50d 100644
> --- a/ip/ip_common.h
> +++ b/ip/ip_common.h
> @@ -4,6 +4,9 @@ extern int print_linkinfo(const struct sockaddr_nl *who,
>  extern int print_addrinfo(const struct sockaddr_nl *who,
>  			  struct nlmsghdr *n,
>  			  void *arg);
> +extern int print_addrlabelinfo(const struct sockaddr_nl *who,
> +			       struct nlmsghdr *n,
> +			       void *arg);
>  extern int print_neigh(const struct sockaddr_nl *who,
>  		       struct nlmsghdr *n, void *arg);
>  extern int print_ntable(const struct sockaddr_nl *who,
> @@ -23,6 +26,7 @@ extern int print_prefix(const struct sockaddr_nl *who,
>  extern int print_rule(const struct sockaddr_nl *who,
>  		      struct nlmsghdr *n, void *arg);
>  extern int do_ipaddr(int argc, char **argv);
> +extern int do_ipaddrlabel(int argc, char **argv);
>  extern int do_iproute(int argc, char **argv);
>  extern int do_iprule(int argc, char **argv);
>  extern int do_ipneigh(int argc, char **argv);
> diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c
> new file mode 100644
> index 0000000..1c873e9
> --- /dev/null
> +++ b/ip/ipaddrlabel.c
> @@ -0,0 +1,260 @@
> +/*
> + * ipaddrlabel.c	"ip addrlabel"
> + *
> + * Copyright (C)2007 USAGI/WIDE Project
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + *
> + * Based on iprule.c.
> + *
> + * Authors:	YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> + *
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <syslog.h>
> +#include <fcntl.h>
> +#include <sys/socket.h>
> +#include <netinet/in.h>
> +#include <netinet/ip.h>
> +#include <arpa/inet.h>
> +#include <string.h>
> +#include <linux/types.h>
> +#include <linux/if_addrlabel.h>
> +
> +#include "rt_names.h"
> +#include "utils.h"
> +#include "ip_common.h"
> +
> +#define IFAL_RTA(r)	((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrlblmsg))))
> +#define IFAL_PAYLOAD(n)	NLMSG_PAYLOAD(n,sizeof(struct ifaddrlblmsg))
> +
> +extern struct rtnl_handle rth;
> +
> +static void usage(void) __attribute__((noreturn));
> +
> +static void usage(void)
> +{
> +	fprintf(stderr, "Usage: ip addrlabel [ list | add | del | flush ] prefix PREFIX [ dev DEV ] [ label LABEL ]\n");
> +	exit(-1);
> +}
> +
> +int print_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
> +{
> +	FILE *fp = (FILE*)arg;
> +	struct ifaddrlblmsg *ifal = NLMSG_DATA(n);
> +	int len = n->nlmsg_len;
> +	int host_len = -1;
> +	struct rtattr *tb[IFAL_MAX+1];
> +	char abuf[256];
> +
> +	if (n->nlmsg_type != RTM_NEWADDRLABEL && n->nlmsg_type != RTM_DELADDRLABEL)
> +		return 0;
> +
> +	len -= NLMSG_LENGTH(sizeof(*ifal));
> +	if (len < 0)
> +		return -1;
> +
> +	parse_rtattr(tb, IFAL_MAX, IFAL_RTA(ifal), len);
> +
> +	if (ifal->ifal_family == AF_INET)
> +		host_len = 32;
> +	else if (ifal->ifal_family == AF_INET6)
> +		host_len = 128;
> +
> +	if (n->nlmsg_type == RTM_DELADDRLABEL)
> +		fprintf(fp, "Deleted ");
> +
> +	if (tb[IFAL_ADDRESS]) {
> +		fprintf(fp, "prefix %s/%u ",
> +			format_host(ifal->ifal_family,
> +				    RTA_PAYLOAD(tb[IFAL_ADDRESS]),
> +				    RTA_DATA(tb[IFAL_ADDRESS]),
> +				    abuf, sizeof(abuf)),
> +			ifal->ifal_prefixlen);
> +	}
> +
> +	if (ifal->ifal_index)
> +		fprintf(fp, "dev %s ", ll_index_to_name(ifal->ifal_index));
> +
> +	if (tb[IFAL_LABEL] && RTA_PAYLOAD(tb[IFAL_LABEL]) == sizeof(int32_t)) {
> +		int32_t label;
> +		memcpy(&label, RTA_DATA(tb[IFAL_LABEL]), sizeof(label));
> +		fprintf(fp, "label %d ", label);
> +	}
> +
> +	fprintf(fp, "\n");
> +	fflush(fp);
> +	return 0;
> +}
> +
> +static int ipaddrlabel_list(int argc, char **argv)
> +{
> +	int af = preferred_family;
> +
> +	if (af == AF_UNSPEC)
> +		af = AF_INET6;
> +
> +	if (argc > 0) {
> +		fprintf(stderr, "\"ip addrlabel show\" does not take any arguments.\n");
> +		return -1;
> +	}
> +
> +	if (rtnl_wilddump_request(&rth, af, RTM_GETADDRLABEL) < 0) {
> +		perror("Cannot send dump request");
> +		return 1;
> +	}
> +
> +	if (rtnl_dump_filter(&rth, print_addrlabel, stdout, NULL, NULL) < 0) {
> +		fprintf(stderr, "Dump terminated\n");
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +
> +
> +static int ipaddrlabel_modify(int cmd, int argc, char **argv)
> +{
> +	struct {
> +		struct nlmsghdr 	n;
> +		struct ifaddrlblmsg	ifal;
> +		char   			buf[1024];
> +	} req;
> +
> +	inet_prefix prefix;
> +	uint32_t label = 0xffffffffUL;
> +
> +	memset(&req, 0, sizeof(req));
> +	memset(&prefix, 0, sizeof(prefix));
> +
> +	req.n.nlmsg_type = cmd;
> +	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrlblmsg));
> +	req.n.nlmsg_flags = NLM_F_REQUEST;
> +	req.ifal.ifal_family = preferred_family;
> +	req.ifal.ifal_prefixlen = 0;
> +	req.ifal.ifal_index = 0;
> +
> +	if (cmd == RTM_NEWADDRLABEL) {
> +		req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
> +	}
> +
> +	while (argc > 0) {
> +		if (strcmp(*argv, "prefix") == 0) {
> +			NEXT_ARG();
> +			get_prefix(&prefix, *argv, preferred_family);
> +		} else if (strcmp(*argv, "dev") == 0) {
> +			NEXT_ARG();
> +			if ((req.ifal.ifal_index = ll_name_to_index(*argv)) == 0)
> +				invarg("dev is invalid\n", *argv);
> +		} else if (strcmp(*argv, "label") == 0) {
> +			NEXT_ARG();
> +			if (get_u32(&label, *argv, 0) || label == 0xffffffffUL)
> +				invarg("label is invalid\n", *argv);
> +		}
> +		argc--;
> +		argv++;
> +	}
> +
> +	addattr32(&req.n, sizeof(req), IFAL_LABEL, label);
> +	addattr_l(&req.n, sizeof(req), IFAL_ADDRESS, &prefix.data, prefix.bytelen);
> +
> +	if (req.ifal.ifal_family == AF_UNSPEC)
> +		req.ifal.ifal_family = AF_INET6;
> +
> +	if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
> +		return 2;
> +
> +	return 0;
> +}
> +
> +
> +static int flush_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
> +{
> +	struct rtnl_handle rth2;
> +	struct rtmsg *r = NLMSG_DATA(n);
> +	int len = n->nlmsg_len;
> +	struct rtattr * tb[IFAL_MAX+1];
> +
> +	len -= NLMSG_LENGTH(sizeof(*r));
> +	if (len < 0)
> +		return -1;
> +
> +	parse_rtattr(tb, IFAL_MAX, RTM_RTA(r), len);
> +
> +	if (tb[IFAL_ADDRESS]) {
> +		n->nlmsg_type = RTM_DELADDRLABEL;
> +		n->nlmsg_flags = NLM_F_REQUEST;
> +
> +		if (rtnl_open(&rth2, 0) < 0)
> +			return -1;
> +
> +		if (rtnl_talk(&rth2, n, 0, 0, NULL, NULL, NULL) < 0)
> +			return -2;
> +
> +		rtnl_close(&rth2);
> +	}
> +
> +	return 0;
> +}
> +
> +static int ipaddrlabel_flush(int argc, char **argv)
> +{
> +	int af = preferred_family;
> +
> +	if (af == AF_UNSPEC)
> +		af = AF_INET6;
> +
> +	if (argc > 0) {
> +		fprintf(stderr, "\"ip addrlabel flush\" does not allow extra arguments\n");
> +		return -1;
> +	}
> +
> +	if (rtnl_wilddump_request(&rth, af, RTM_GETADDRLABEL) < 0) {
> +		perror("Cannot send dump request");
> +		return 1;
> +	}
> +
> +	if (rtnl_dump_filter(&rth, flush_addrlabel, NULL, NULL, NULL) < 0) {
> +		fprintf(stderr, "Flush terminated\n");
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +
> +int do_ipaddrlabel(int argc, char **argv)
> +{
> +	if (argc < 1) {
> +		return ipaddrlabel_list(0, NULL);
> +	} else if (matches(argv[0], "list") == 0 ||
> +		   matches(argv[0], "show") == 0) {
> +		return ipaddrlabel_list(argc-1, argv+1);
> +	} else if (matches(argv[0], "add") == 0) {
> +		return ipaddrlabel_modify(RTM_NEWADDRLABEL, argc-1, argv+1);
> +	} else if (matches(argv[0], "delete") == 0) {
> +		return ipaddrlabel_modify(RTM_DELADDRLABEL, argc-1, argv+1);
> +	} else if (matches(argv[0], "flush") == 0) {
> +		return ipaddrlabel_flush(argc-1, argv+1);
> +	} else if (matches(argv[0], "help") == 0)
> +		usage();
> +
> +	fprintf(stderr, "Command \"%s\" is unknown, try \"ip addrlabel help\".\n", *argv);
> +	exit(-1);
> +}
> +
> diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c
> index f1a1f27..df0fd91 100644
> --- a/ip/ipmonitor.c
> +++ b/ip/ipmonitor.c
> @@ -54,6 +54,10 @@ int accept_msg(const struct sockaddr_nl *who,
>  		print_addrinfo(who, n, arg);
>  		return 0;
>  	}
> +	if (n->nlmsg_type == RTM_NEWADDRLABEL || n->nlmsg_type == RTM_DELADDRLABEL) {
> +		print_addrlabel(who, n, arg);
> +		return 0;
> +	}
>  	if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH) {
>  		print_neigh(who, n, arg);
>  		return 0;
> diff --git a/man/man8/ip.8 b/man/man8/ip.8
> index 1687045..136448c 100644
> --- a/man/man8/ip.8
> +++ b/man/man8/ip.8
> @@ -13,8 +13,8 @@ ip \- show / manipulate routing, devices, policy routing and tunnels
>  
>  .ti -8
>  .IR OBJECT " := { "
> -.BR link " | " addr " | " route " | " rule " | " neigh " | " tunnel " | "\
> -maddr " | "  mroute " | " monitor " }"
> +.BR link " | " addr " | " addrlabel " | " route " | " rule " | " neigh " | "\
> + tunnel " | " maddr " | "  mroute " | " monitor " }"
>  .sp
>  
>  .ti -8
> @@ -97,6 +97,17 @@ maddr " | "  mroute " | " monitor " }"
>  tentative " | " deprecated " ]"
>  
>  .ti -8
> +.BR "ip addrlabel" " { " add " | " del " } " prefix 
> +.BR PREFIX " [ "
> +.B dev
> +.IR DEV " ] [ "
> +.B label
> +.IR NUMBER " ]"
> +
> +.ti -8
> +.BR "ip addrlabel" " { " list " | " flush " }"
> +
> +.ti -8
>  .BR "ip route" " { "
>  .BR list " | " flush " } "
>  .I  SELECTOR
> @@ -404,6 +415,11 @@ host addresses.
>  .TP
>  .B address
>  - protocol (IP or IPv6) address on a device.
> +
> +.TP
> +.B addrlabel
> +- label configuration for protocol address selection.
> +
>  .TP
>  .B neighbour
>  - ARP or NDISC cache entry.
> @@ -708,6 +724,33 @@ this option is given twice,
>  also dumps all the deleted addresses in the format described in the
>  previous subsection.
>  
> +.SH ip addrlabel - protocol address label management.
> +
> +IPv6 address label is used for address selection
> +described in RFC 3484.  Precedence is managed by userspace,
> +and only label is stored in kernel.
> +
> +.SS ip addrlabel add - add an address label
> +the command adds an address label entry to the kernel.
> +.TP
> +.BI prefix " PREFIX"
> +.TP
> +.BI dev " DEV"
> +the outgoing interface.
> +.TP
> +.BI label " NUMBER"
> +the label for the prefix.
> +0xffffffff is reserved.
> +.SS ip addrlabel del - delete an address label
> +the command deletes an address label entry in the kernel.
> +.B Arguments:
> +coincide with the arguments of
> +.B ip addrlabel add
> +but label is not required.
> +.SS ip addrlabel list - list address labels
> +the command show contents of address labels.
> +.SS ip addrlabel flush - flush address labels
> +the commoand flushes the contents of address labels and it does not restore default settings.
>  .SH ip neighbour - neighbour/arp tables management.
>  
>  .B neighbour
> 

applied

-- 
Stephen Hemminger <stephen.hemminger@vyatta.com>



^ permalink raw reply

* Re: [PATCH] [IPROUTE2] Update various classifiers' help output for expected CLASSID syntax
From: Stephen Hemminger @ 2008-02-13 20:37 UTC (permalink / raw)
  To: netdev
In-Reply-To: <20080213114909.13171.97451.stgit@localhost.localdomain>

On Wed, 13 Feb 2008 03:49:09 -0800
PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com> wrote:

> update: Fix the spelling of "hexidecimal"
> 
> This updates the help output to specify that CLASSID should be hexidecimal.
> This makes sure that a user entering "flowid 1:10" gets his flow put into
> band 15 (0x10) and knows why.
> 
> Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
> ---
> 
>  doc/actions/actions-general |    3 +++
>  tc/f_basic.c                |    1 +
>  tc/f_fw.c                   |    1 +
>  tc/f_route.c                |    1 +
>  tc/f_rsvp.c                 |    1 +
>  tc/f_u32.c                  |    1 +
>  6 files changed, 8 insertions(+), 0 deletions(-)
> 
> diff --git a/doc/actions/actions-general b/doc/actions/actions-general
> index 6561eda..70f7cd6 100644
> --- a/doc/actions/actions-general
> +++ b/doc/actions/actions-general
> @@ -88,6 +88,9 @@ tc filter add dev lo parent ffff: protocol ip prio 8 u32 \
>  match ip dst 127.0.0.8/32 flowid 1:12 \
>  action ipt -j mark --set-mark 2
>  
> +NOTE: flowid 1:12 is parsed flowid 0x1:0x12.  Make sure if you want flowid
> +decimal 12, then use flowid 1:c.
> +
>  3) A feature i call pipe
>  The motivation is derived from Unix pipe mechanism but applied to packets.
>  Essentially take a matching packet and pass it through 
> diff --git a/tc/f_basic.c b/tc/f_basic.c
> index 19a7edf..aab946b 100644
> --- a/tc/f_basic.c
> +++ b/tc/f_basic.c
> @@ -32,6 +32,7 @@ static void explain(void)
>  	fprintf(stderr, "\n");
>  	fprintf(stderr, "Where: SELECTOR := SAMPLE SAMPLE ...\n");
>  	fprintf(stderr, "       FILTERID := X:Y:Z\n");
> +	fprintf(stderr, "\nNOTE: CLASSID is parsed as hexadecimal input.\n");
>  }
>  
>  static int basic_parse_opt(struct filter_util *qu, char *handle,
> diff --git a/tc/f_fw.c b/tc/f_fw.c
> index 6d1490b..b511735 100644
> --- a/tc/f_fw.c
> +++ b/tc/f_fw.c
> @@ -28,6 +28,7 @@ static void explain(void)
>  	fprintf(stderr, "Usage: ... fw [ classid CLASSID ] [ police POLICE_SPEC ]\n");
>  	fprintf(stderr, "       POLICE_SPEC := ... look at TBF\n");
>  	fprintf(stderr, "       CLASSID := X:Y\n");
> +	fprintf(stderr, "\nNOTE: CLASSID is parsed as hexadecimal input.\n");
>  }
>  
>  #define usage() return(-1)
> diff --git a/tc/f_route.c b/tc/f_route.c
> index a41b9d5..67dd49c 100644
> --- a/tc/f_route.c
> +++ b/tc/f_route.c
> @@ -31,6 +31,7 @@ static void explain(void)
>  	fprintf(stderr, "                [ flowid CLASSID ] [ police POLICE_SPEC ]\n");
>  	fprintf(stderr, "       POLICE_SPEC := ... look at TBF\n");
>  	fprintf(stderr, "       CLASSID := X:Y\n");
> +	fprintf(stderr, "\nNOTE: CLASSID is parsed as hexadecimal input.\n");
>  }
>  
>  #define usage() return(-1)
> diff --git a/tc/f_rsvp.c b/tc/f_rsvp.c
> index 13fcf97..7e1e6d9 100644
> --- a/tc/f_rsvp.c
> +++ b/tc/f_rsvp.c
> @@ -34,6 +34,7 @@ static void explain(void)
>  	fprintf(stderr, "                u{8|16|32} NUMBER mask MASK at OFFSET}\n");
>  	fprintf(stderr, "       POLICE_SPEC := ... look at TBF\n");
>  	fprintf(stderr, "       FILTERID := X:Y\n");
> +	fprintf(stderr, "\nNOTE: CLASSID is parsed as hexadecimal input.\n");
>  }
>  
>  #define usage() return(-1)
> diff --git a/tc/f_u32.c b/tc/f_u32.c
> index 91f2838..d75e76c 100644
> --- a/tc/f_u32.c
> +++ b/tc/f_u32.c
> @@ -36,6 +36,7 @@ static void explain(void)
>  	fprintf(stderr, "Where: SELECTOR := SAMPLE SAMPLE ...\n");
>  	fprintf(stderr, "       SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} | mark } SAMPLE_ARGS [divisor DIVISOR]\n");
>  	fprintf(stderr, "       FILTERID := X:Y:Z\n");
> +	fprintf(stderr, "\nNOTE: CLASSID is parsed at hexadecimal input.\n");
>  }
>  
>  #define usage() return(-1)
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

applied

-- 
Stephen Hemminger <stephen.hemminger@vyatta.com>



^ permalink raw reply

* Re: Patch to latest iproute to get it to compile on FC5
From: Ben Greear @ 2008-02-13 20:52 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: NetDev
In-Reply-To: <20080213123402.43cdbd45@extreme>

[-- Attachment #1: Type: text/plain, Size: 1785 bytes --]

Stephen Hemminger wrote:
> On Wed, 13 Feb 2008 11:32:32 -0800
> Ben Greear <greearb@candelatech.com> wrote:
> 
>> I notice that the latest snapshot and git repository for iproute
>> will not compile on FC5 due to not finding __constant_hton* symbols
>> and a lack of the hdlc/ioctl.h file on FC5.
>>
>> I am attaching a patch that appears to fix the problems for me.
>>
>> Please consider applying this or something similar.
>>
>> Signed-off-by:  Ben Greear <greearb@candelatech.com>
>>
>>
>> Thanks,
>> Ben
>>
> 
> I added include/linux/hdlc/ioctl.h to the santized headers in the
> current git.
> 

That seems to fix the hdlc issue, but it still will not link due to missing
symbols:

gcc -Wl,-export-dynamic  ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o iplink_vlan.o link_veth.o ../lib/libnetlink.a ../lib/libutil.a  -lresolv -L../lib -lnetlink -lutil -ldl -o ip
iptunnel.o: In function `parse_args':
iptunnel.c:(.text+0x2c6): undefined reference to `__constant_htons'
iptunnel.c:(.text+0x404): undefined reference to `__constant_htons'
iptunnel.c:(.text+0x48d): undefined reference to `__constant_htons'
iptunnel.c:(.text+0x4a6): undefined reference to `__constant_htons'
iptunnel.c:(.text+0x4e2): undefined reference to `__constant_htons'
iptunnel.o:iptunnel.c:(.text+0x4fb): more undefined references to `__constant_htons' follow
collect2: ld returned 1 exit status
make[1]: *** [ip] Error 1
make[1]: Leaving directory `/root/iproute2/ip'
make: *** [all] Error 2


The attached patch fixes this.

Thanks,
Ben


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


[-- Attachment #2: iproute.fc5.patch --]
[-- Type: text/x-patch, Size: 350 bytes --]

diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
index 228eb4e..0eb5b04 100644
--- a/include/linux/if_tunnel.h
+++ b/include/linux/if_tunnel.h
@@ -2,6 +2,7 @@
 #define _IF_TUNNEL_H_
 
 #include <linux/types.h>
+#include <asm/byteorder.h>
 
 #define SIOCGETTUNNEL   (SIOCDEVPRIVATE + 0)
 #define SIOCADDTUNNEL   (SIOCDEVPRIVATE + 1)

^ permalink raw reply related

* [PATCH] [resend] 3c509: convert to isa_driver and pnp_driver v5
From: Ondrej Zary @ 2008-02-13 21:28 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Stephen Hemminger, linux-kernel, netdev
In-Reply-To: <20080210051855.GA22064@infradead.org>

Hello,
this patch converts 3c509 driver to isa_driver and pnp_driver. The result is 
that autoloading using udev and hibernation works with ISA PnP cards. It also 
adds hibernation support for non-PnP ISA cards.

xcvr module parameter was removed as its value was not used.

Tested using 3 ISA cards in various combinations of PnP and non-PnP modes. 
EISA and MCA only compile-tested.

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>

--- linux-2.6.24-orig/drivers/net/3c509.c	2008-01-27 19:48:19.000000000 +0100
+++ linux-2.6.24-pentium/drivers/net/3c509.c	2008-02-10 21:52:04.000000000 +0100
@@ -54,25 +54,24 @@
 		v1.19a 28Oct2002 Davud Ruggiero <jdr@farfalle.com>
 			- Increase *read_eeprom udelay to workaround oops with 2 cards.
 		v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
-		    - Introduce driver model for EISA cards.
+			- Introduce driver model for EISA cards.
+		v1.20  04Feb2008 Ondrej Zary <linux@rainbow-software.org>
+			- convert to isa_driver and pnp_driver and some cleanups
 */
 
 #define DRV_NAME	"3c509"
-#define DRV_VERSION	"1.19b"
-#define DRV_RELDATE	"08Nov2002"
+#define DRV_VERSION	"1.20"
+#define DRV_RELDATE	"04Feb2008"
 
 /* A few values that may be tweaked. */
 
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (400*HZ/1000)
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 10;
 
 #include <linux/module.h>
-#ifdef CONFIG_MCA
 #include <linux/mca.h>
-#endif
-#include <linux/isapnp.h>
+#include <linux/isa.h>
+#include <linux/pnp.h>
 #include <linux/string.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
@@ -97,10 +96,6 @@
 
 static char version[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
 
-#if defined(CONFIG_PM) && (defined(CONFIG_MCA) || defined(CONFIG_EISA))
-#define EL3_SUSPEND
-#endif
-
 #ifdef EL3_DEBUG
 static int el3_debug = EL3_DEBUG;
 #else
@@ -111,6 +106,7 @@
  * a global variable so that the mca/eisa probe routines can increment
  * it */
 static int el3_cards = 0;
+#define EL3_MAX_CARDS 8
 
 /* To minimize the size of the driver source I only define operating
    constants if they are used several times.  You'll need the manual
@@ -119,7 +115,7 @@
 #define EL3_DATA 0x00
 #define EL3_CMD 0x0e
 #define EL3_STATUS 0x0e
-#define	 EEPROM_READ 0x80
+#define	EEPROM_READ 0x80
 
 #define EL3_IO_EXTENT	16
 
@@ -168,23 +164,31 @@
  */
 #define SKB_QUEUE_SIZE	64
 
+enum el3_cardtype { EL3_ISA, EL3_PNP, EL3_MCA, EL3_EISA };
+
 struct el3_private {
 	struct net_device_stats stats;
-	struct net_device *next_dev;
 	spinlock_t lock;
 	/* skb send-queue */
 	int head, size;
 	struct sk_buff *queue[SKB_QUEUE_SIZE];
-	enum {
-		EL3_MCA,
-		EL3_PNP,
-		EL3_EISA,
-	} type;						/* type of device */
-	struct device *dev;
+	enum el3_cardtype type;
 };
-static int id_port __initdata = 0x110;	/* Start with 0x110 to avoid new sound cards.*/
-static struct net_device *el3_root_dev;
+static int id_port;
+static int current_tag;
+static struct net_device *el3_devs[EL3_MAX_CARDS];
+
+/* Parameters that may be passed into the module. */
+static int debug = -1;
+static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 10;
+#ifdef CONFIG_PNP
+static int nopnp;
+#endif
 
+static int __init el3_common_init(struct net_device *dev);
+static void el3_common_remove(struct net_device *dev);
 static ushort id_read_eeprom(int index);
 static ushort read_eeprom(int ioaddr, int index);
 static int el3_open(struct net_device *dev);
@@ -199,23 +203,279 @@
 static void el3_down(struct net_device *dev);
 static void el3_up(struct net_device *dev);
 static const struct ethtool_ops ethtool_ops;
-#ifdef EL3_SUSPEND
+#ifdef CONFIG_PM
 static int el3_suspend(struct device *, pm_message_t);
 static int el3_resume(struct device *);
-#else
-#define el3_suspend NULL
-#define el3_resume NULL
 #endif
 
 
 /* generic device remove for all device types */
-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
 static int el3_device_remove (struct device *device);
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void el3_poll_controller(struct net_device *dev);
 #endif
 
+/* Return 0 on success, 1 on error, 2 when found already detected PnP card */
+static int el3_isa_id_sequence(__be16 *phys_addr)
+{
+	short lrs_state = 0xff;
+	int i;
+
+	/* ISA boards are detected by sending the ID sequence to the
+	   ID_PORT.  We find cards past the first by setting the 'current_tag'
+	   on cards as they are found.  Cards with their tag set will not
+	   respond to subsequent ID sequences. */
+
+	outb(0x00, id_port);
+	outb(0x00, id_port);
+	for (i = 0; i < 255; i++) {
+		outb(lrs_state, id_port);
+		lrs_state <<= 1;
+		lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
+	}
+	/* For the first probe, clear all board's tag registers. */
+	if (current_tag == 0)
+		outb(0xd0, id_port);
+	else			/* Otherwise kill off already-found boards. */
+		outb(0xd8, id_port);
+	if (id_read_eeprom(7) != 0x6d50)
+		return 1;
+	/* Read in EEPROM data, which does contention-select.
+	   Only the lowest address board will stay "on-line".
+	   3Com got the byte order backwards. */
+	for (i = 0; i < 3; i++)
+		phys_addr[i] = htons(id_read_eeprom(i));
+#ifdef CONFIG_PNP
+	if (!nopnp) {
+		/* The ISA PnP 3c509 cards respond to the ID sequence too.
+		   This check is needed in order not to register them twice. */
+		for (i = 0; i < el3_cards; i++) {
+			struct el3_private *lp = netdev_priv(el3_devs[i]);
+			if (lp->type == EL3_PNP
+			    && !memcmp(phys_addr, el3_devs[i]->dev_addr,
+				       ETH_ALEN)) {
+				if (el3_debug > 3)
+					printk(KERN_DEBUG "3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
+						phys_addr[0] & 0xff, phys_addr[0] >> 8,
+						phys_addr[1] & 0xff, phys_addr[1] >> 8,
+						phys_addr[2] & 0xff, phys_addr[2] >> 8);
+				/* Set the adaptor tag so that the next card can be found. */
+				outb(0xd0 + ++current_tag, id_port);
+				return 2;
+			}
+		}
+	}
+#endif /* CONFIG_PNP */
+	return 0;
+
+}
+
+static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
+				   int ioaddr, int irq, int if_port,
+				   enum el3_cardtype type)
+{
+	struct el3_private *lp = netdev_priv(dev);
+
+	memcpy(dev->dev_addr, phys_addr, ETH_ALEN);
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+	dev->if_port = if_port;
+	lp->type = type;
+}
+
+static int __devinit el3_isa_match(struct device *pdev,
+				   unsigned int ndev)
+{
+	struct net_device *dev;
+	int ioaddr, isa_irq, if_port, err;
+	unsigned int iobase;
+	__be16 phys_addr[3];
+
+	while ((err = el3_isa_id_sequence(phys_addr)) == 2)
+		;	/* Skip to next card when PnP card found */
+	if (err == 1)
+		return 0;
+
+	iobase = id_read_eeprom(8);
+	if_port = iobase >> 14;
+	ioaddr = 0x200 + ((iobase & 0x1f) << 4);
+	if (irq[el3_cards] > 1 && irq[el3_cards] < 16)
+		isa_irq = irq[el3_cards];
+	else
+		isa_irq = id_read_eeprom(9) >> 12;
+
+	dev = alloc_etherdev(sizeof(struct el3_private));
+	if (!dev)
+		return -ENOMEM;
+
+	netdev_boot_setup_check(dev);
+
+	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-isa")) {
+		free_netdev(dev);
+		return 0;
+	}
+
+	/* Set the adaptor tag so that the next card can be found. */
+	outb(0xd0 + ++current_tag, id_port);
+
+	/* Activate the adaptor at the EEPROM location. */
+	outb((ioaddr >> 4) | 0xe0, id_port);
+
+	EL3WINDOW(0);
+	if (inw(ioaddr) != 0x6d50) {
+		free_netdev(dev);
+		return 0;
+	}
+
+	/* Free the interrupt so that some other card can use it. */
+	outw(0x0f00, ioaddr + WN0_IRQ);
+
+	el3_dev_fill(dev, phys_addr, ioaddr, isa_irq, if_port, EL3_ISA);
+	dev_set_drvdata(pdev, dev);
+	if (el3_common_init(dev)) {
+		free_netdev(dev);
+		return 0;
+	}
+
+	el3_devs[el3_cards++] = dev;
+	return 1;
+}
+
+static int __devexit el3_isa_remove(struct device *pdev,
+				    unsigned int ndev)
+{
+	el3_device_remove(pdev);
+	dev_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int el3_isa_suspend(struct device *dev, unsigned int n,
+			   pm_message_t state)
+{
+	current_tag = 0;
+	return el3_suspend(dev, state);
+}
+
+static int el3_isa_resume(struct device *dev, unsigned int n)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	int ioaddr = ndev->base_addr, err;
+	__be16 phys_addr[3];
+
+	while ((err = el3_isa_id_sequence(phys_addr)) == 2)
+		;	/* Skip to next card when PnP card found */
+	if (err == 1)
+		return 0;
+	/* Set the adaptor tag so that the next card can be found. */
+	outb(0xd0 + ++current_tag, id_port);
+	/* Enable the card */
+	outb((ioaddr >> 4) | 0xe0, id_port);
+	EL3WINDOW(0);
+	if (inw(ioaddr) != 0x6d50)
+		return 1;
+	/* Free the interrupt so that some other card can use it. */
+	outw(0x0f00, ioaddr + WN0_IRQ);
+	return el3_resume(dev);
+}
+#endif
+
+static struct isa_driver el3_isa_driver = {
+	.match		= el3_isa_match,
+	.remove		= __devexit_p(el3_isa_remove),
+#ifdef CONFIG_PM
+	.suspend	= el3_isa_suspend,
+	.resume		= el3_isa_resume,
+#endif
+	.driver		= {
+		.name	= "3c509"
+	},
+};
+static int isa_registered;
+
+#ifdef CONFIG_PNP
+static struct pnp_device_id el3_pnp_ids[] = {
+	{ .id = "TCM5090" }, /* 3Com Etherlink III (TP) */
+	{ .id = "TCM5091" }, /* 3Com Etherlink III */
+	{ .id = "TCM5094" }, /* 3Com Etherlink III (combo) */
+	{ .id = "TCM5095" }, /* 3Com Etherlink III (TPO) */
+	{ .id = "TCM5098" }, /* 3Com Etherlink III (TPC) */
+	{ .id = "PNP80f7" }, /* 3Com Etherlink III compatible */
+	{ .id = "PNP80f8" }, /* 3Com Etherlink III compatible */
+	{ .id = "" }
+};
+MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);
+
+static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
+				    const struct pnp_device_id *id)
+{
+	short i;
+	int ioaddr, irq, if_port;
+	u16 phys_addr[3];
+	struct net_device *dev = NULL;
+	int err;
+
+	ioaddr = pnp_port_start(pdev, 0);
+	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-pnp"))
+		return -EBUSY;
+	irq = pnp_irq(pdev, 0);
+	EL3WINDOW(0);
+	for (i = 0; i < 3; i++)
+		phys_addr[i] = htons(read_eeprom(ioaddr, i));
+	if_port = read_eeprom(ioaddr, 8) >> 14;
+	dev = alloc_etherdev(sizeof(struct el3_private));
+	if (!dev) {
+		release_region(ioaddr, EL3_IO_EXTENT);
+		return -ENOMEM;
+	}
+	SET_NETDEV_DEV(dev, &pdev->dev);
+	netdev_boot_setup_check(dev);
+
+	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_PNP);
+	pnp_set_drvdata(pdev, dev);
+	err = el3_common_init(dev);
+
+	if (err) {
+		pnp_set_drvdata(pdev, NULL);
+		free_netdev(dev);
+		return err;
+	}
+
+	el3_devs[el3_cards++] = dev;
+	return 0;
+}
+
+static void __devexit el3_pnp_remove(struct pnp_dev *pdev)
+{
+	el3_common_remove(pnp_get_drvdata(pdev));
+	pnp_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int el3_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
+{
+	return el3_suspend(&pdev->dev, state);
+}
+
+static int el3_pnp_resume(struct pnp_dev *pdev)
+{
+	return el3_resume(&pdev->dev);
+}
+#endif
+
+static struct pnp_driver el3_pnp_driver = {
+	.name		= "3c509",
+	.id_table	= el3_pnp_ids,
+	.probe		= el3_pnp_probe,
+	.remove		= __devexit_p(el3_pnp_remove),
+#ifdef CONFIG_PM
+	.suspend	= el3_pnp_suspend,
+	.resume		= el3_pnp_resume,
+#endif
+};
+static int pnp_registered;
+#endif /* CONFIG_PNP */
+
 #ifdef CONFIG_EISA
 static struct eisa_device_id el3_eisa_ids[] = {
 		{ "TCM5092" },
@@ -230,13 +490,14 @@
 static struct eisa_driver el3_eisa_driver = {
 		.id_table = el3_eisa_ids,
 		.driver   = {
-				.name    = "3c509",
+				.name    = "3c579",
 				.probe   = el3_eisa_probe,
 				.remove  = __devexit_p (el3_device_remove),
 				.suspend = el3_suspend,
 				.resume  = el3_resume,
 		}
 };
+static int eisa_registered;
 #endif
 
 #ifdef CONFIG_MCA
@@ -271,45 +532,9 @@
 				.resume  = el3_resume,
 		},
 };
+static int mca_registered;
 #endif /* CONFIG_MCA */
 
-#if defined(__ISAPNP__)
-static struct isapnp_device_id el3_isapnp_adapters[] __initdata = {
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090),
-		(long) "3Com Etherlink III (TP)" },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5091),
-		(long) "3Com Etherlink III" },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5094),
-		(long) "3Com Etherlink III (combo)" },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5095),
-		(long) "3Com Etherlink III (TPO)" },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5098),
-		(long) "3Com Etherlink III (TPC)" },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x80f7),
-		(long) "3Com Etherlink III compatible" },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x80f8),
-		(long) "3Com Etherlink III compatible" },
-	{ }	/* terminate list */
-};
-
-static __be16 el3_isapnp_phys_addr[8][3];
-static int nopnp;
-#endif /* __ISAPNP__ */
-
-/* With the driver model introduction for EISA devices, both init
- * and cleanup have been split :
- * - EISA devices probe/remove starts in el3_eisa_probe/el3_device_remove
- * - MCA/ISA still use el3_probe
- *
- * Both call el3_common_init/el3_common_remove. */
-
 static int __init el3_common_init(struct net_device *dev)
 {
 	struct el3_private *lp = netdev_priv(dev);
@@ -360,231 +585,11 @@
 
 static void el3_common_remove (struct net_device *dev)
 {
-	struct el3_private *lp = netdev_priv(dev);
-
-	(void) lp;				/* Keep gcc quiet... */
-#if defined(__ISAPNP__)
-	if (lp->type == EL3_PNP)
-		pnp_device_detach(to_pnp_dev(lp->dev));
-#endif
-
 	unregister_netdev (dev);
 	release_region(dev->base_addr, EL3_IO_EXTENT);
 	free_netdev (dev);
 }
 
-static int __init el3_probe(int card_idx)
-{
-	struct net_device *dev;
-	struct el3_private *lp;
-	short lrs_state = 0xff, i;
-	int ioaddr, irq, if_port;
-	__be16 phys_addr[3];
-	static int current_tag;
-	int err = -ENODEV;
-#if defined(__ISAPNP__)
-	static int pnp_cards;
-	struct pnp_dev *idev = NULL;
-	int pnp_found = 0;
-
-	if (nopnp == 1)
-		goto no_pnp;
-
-	for (i=0; el3_isapnp_adapters[i].vendor != 0; i++) {
-		int j;
-		while ((idev = pnp_find_dev(NULL,
-					    el3_isapnp_adapters[i].vendor,
-					    el3_isapnp_adapters[i].function,
-					    idev))) {
-			if (pnp_device_attach(idev) < 0)
-				continue;
-			if (pnp_activate_dev(idev) < 0) {
-__again:
-				pnp_device_detach(idev);
-				continue;
-			}
-			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0))
-				goto __again;
-			ioaddr = pnp_port_start(idev, 0);
-			if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509 PnP")) {
-				pnp_device_detach(idev);
-				return -EBUSY;
-			}
-			irq = pnp_irq(idev, 0);
-			if (el3_debug > 3)
-				printk ("ISAPnP reports %s at i/o 0x%x, irq %d\n",
-					(char*) el3_isapnp_adapters[i].driver_data, ioaddr, irq);
-			EL3WINDOW(0);
-			for (j = 0; j < 3; j++)
-				el3_isapnp_phys_addr[pnp_cards][j] =
-					phys_addr[j] =
-						htons(read_eeprom(ioaddr, j));
-			if_port = read_eeprom(ioaddr, 8) >> 14;
-			dev = alloc_etherdev(sizeof (struct el3_private));
-			if (!dev) {
-					release_region(ioaddr, EL3_IO_EXTENT);
-					pnp_device_detach(idev);
-					return -ENOMEM;
-			}
-
-			SET_NETDEV_DEV(dev, &idev->dev);
-			pnp_cards++;
-
-			netdev_boot_setup_check(dev);
-			pnp_found = 1;
-			goto found;
-		}
-	}
-no_pnp:
-#endif /* __ISAPNP__ */
-
-	/* Select an open I/O location at 0x1*0 to do contention select. */
-	for ( ; id_port < 0x200; id_port += 0x10) {
-		if (!request_region(id_port, 1, "3c509"))
-			continue;
-		outb(0x00, id_port);
-		outb(0xff, id_port);
-		if (inb(id_port) & 0x01){
-			release_region(id_port, 1);
-			break;
-		} else
-			release_region(id_port, 1);
-	}
-	if (id_port >= 0x200) {
-		/* Rare -- do we really need a warning? */
-		printk(" WARNING: No I/O port available for 3c509 activation.\n");
-		return -ENODEV;
-	}
-
-	/* Next check for all ISA bus boards by sending the ID sequence to the
-	   ID_PORT.  We find cards past the first by setting the 'current_tag'
-	   on cards as they are found.  Cards with their tag set will not
-	   respond to subsequent ID sequences. */
-
-	outb(0x00, id_port);
-	outb(0x00, id_port);
-	for(i = 0; i < 255; i++) {
-		outb(lrs_state, id_port);
-		lrs_state <<= 1;
-		lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
-	}
-
-	/* For the first probe, clear all board's tag registers. */
-	if (current_tag == 0)
-		outb(0xd0, id_port);
-	else				/* Otherwise kill off already-found boards. */
-		outb(0xd8, id_port);
-
-	if (id_read_eeprom(7) != 0x6d50) {
-		return -ENODEV;
-	}
-
-	/* Read in EEPROM data, which does contention-select.
-	   Only the lowest address board will stay "on-line".
-	   3Com got the byte order backwards. */
-	for (i = 0; i < 3; i++) {
-		phys_addr[i] = htons(id_read_eeprom(i));
-	}
-
-#if defined(__ISAPNP__)
-	if (nopnp == 0) {
-		/* The ISA PnP 3c509 cards respond to the ID sequence.
-		   This check is needed in order not to register them twice. */
-		for (i = 0; i < pnp_cards; i++) {
-			if (phys_addr[0] == el3_isapnp_phys_addr[i][0] &&
-			    phys_addr[1] == el3_isapnp_phys_addr[i][1] &&
-			    phys_addr[2] == el3_isapnp_phys_addr[i][2])
-			{
-				if (el3_debug > 3)
-					printk("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
-						phys_addr[0] & 0xff, phys_addr[0] >> 8,
-						phys_addr[1] & 0xff, phys_addr[1] >> 8,
-						phys_addr[2] & 0xff, phys_addr[2] >> 8);
-				/* Set the adaptor tag so that the next card can be found. */
-				outb(0xd0 + ++current_tag, id_port);
-				goto no_pnp;
-			}
-		}
-	}
-#endif /* __ISAPNP__ */
-
-	{
-		unsigned int iobase = id_read_eeprom(8);
-		if_port = iobase >> 14;
-		ioaddr = 0x200 + ((iobase & 0x1f) << 4);
-	}
-	irq = id_read_eeprom(9) >> 12;
-
-	dev = alloc_etherdev(sizeof (struct el3_private));
-	if (!dev)
-		return -ENOMEM;
-
-	netdev_boot_setup_check(dev);
-
-	/* Set passed-in IRQ or I/O Addr. */
-	if (dev->irq > 1  &&  dev->irq < 16)
-			irq = dev->irq;
-
-	if (dev->base_addr) {
-		if (dev->mem_end == 0x3c509 	/* Magic key */
-		    && dev->base_addr >= 0x200  &&  dev->base_addr <= 0x3e0)
-			ioaddr = dev->base_addr & 0x3f0;
-		else if (dev->base_addr != ioaddr)
-			goto out;
-	}
-
-	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509")) {
-		err = -EBUSY;
-		goto out;
-	}
-
-	/* Set the adaptor tag so that the next card can be found. */
-	outb(0xd0 + ++current_tag, id_port);
-
-	/* Activate the adaptor at the EEPROM location. */
-	outb((ioaddr >> 4) | 0xe0, id_port);
-
-	EL3WINDOW(0);
-	if (inw(ioaddr) != 0x6d50)
-		goto out1;
-
-	/* Free the interrupt so that some other card can use it. */
-	outw(0x0f00, ioaddr + WN0_IRQ);
-
-#if defined(__ISAPNP__)
- found:							/* PNP jumps here... */
-#endif /* __ISAPNP__ */
-
-	memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	dev->if_port = if_port;
-	lp = netdev_priv(dev);
-#if defined(__ISAPNP__)
-	lp->dev = &idev->dev;
-	if (pnp_found)
-		lp->type = EL3_PNP;
-#endif
-	err = el3_common_init(dev);
-
-	if (err)
-		goto out1;
-
-	el3_cards++;
-	lp->next_dev = el3_root_dev;
-	el3_root_dev = dev;
-	return 0;
-
-out1:
-#if defined(__ISAPNP__)
-	if (idev)
-		pnp_device_detach(idev);
-#endif
-out:
-	free_netdev(dev);
-	return err;
-}
-
 #ifdef CONFIG_MCA
 static int __init el3_mca_probe(struct device *device)
 {
@@ -596,7 +601,6 @@
 	 * redone for multi-card detection by ZP Gu (zpg@castle.net)
 	 * now works as a module */
 
-	struct el3_private *lp;
 	short i;
 	int ioaddr, irq, if_port;
 	u16 phys_addr[3];
@@ -613,7 +617,7 @@
 	irq = pos5 & 0x0f;
 
 
-	printk("3c529: found %s at slot %d\n",
+	printk(KERN_INFO "3c529: found %s at slot %d\n",
 		   el3_mca_adapter_names[mdev->index], slot + 1);
 
 	/* claim the slot */
@@ -626,7 +630,7 @@
 	irq = mca_device_transform_irq(mdev, irq);
 	ioaddr = mca_device_transform_ioport(mdev, ioaddr);
 	if (el3_debug > 2) {
-			printk("3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
+			printk(KERN_DEBUG "3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
 	}
 	EL3WINDOW(0);
 	for (i = 0; i < 3; i++) {
@@ -641,13 +645,7 @@
 
 	netdev_boot_setup_check(dev);
 
-	memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	dev->if_port = if_port;
-	lp = netdev_priv(dev);
-	lp->dev = device;
-	lp->type = EL3_MCA;
+	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_MCA);
 	device->driver_data = dev;
 	err = el3_common_init(dev);
 
@@ -657,7 +655,7 @@
 		return -ENOMEM;
 	}
 
-	el3_cards++;
+	el3_devs[el3_cards++] = dev;
 	return 0;
 }
 
@@ -666,7 +664,6 @@
 #ifdef CONFIG_EISA
 static int __init el3_eisa_probe (struct device *device)
 {
-	struct el3_private *lp;
 	short i;
 	int ioaddr, irq, if_port;
 	u16 phys_addr[3];
@@ -678,7 +675,7 @@
 	edev = to_eisa_device (device);
 	ioaddr = edev->base_addr;
 
-	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509"))
+	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c579-eisa"))
 		return -EBUSY;
 
 	/* Change the register set to the configuration window 0. */
@@ -700,13 +697,7 @@
 
 	netdev_boot_setup_check(dev);
 
-	memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	dev->if_port = if_port;
-	lp = netdev_priv(dev);
-	lp->dev = device;
-	lp->type = EL3_EISA;
+	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_EISA);
 	eisa_set_drvdata (edev, dev);
 	err = el3_common_init(dev);
 
@@ -716,12 +707,11 @@
 		return err;
 	}
 
-	el3_cards++;
+	el3_devs[el3_cards++] = dev;
 	return 0;
 }
 #endif
 
-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
 /* This remove works for all device types.
  *
  * The net dev must be stored in the driver_data field */
@@ -734,7 +724,6 @@
 	el3_common_remove (dev);
 	return 0;
 }
-#endif
 
 /* Read a word from the EEPROM using the regular EEPROM access register.
    Assume that we are in register window zero.
@@ -749,7 +738,7 @@
 }
 
 /* Read a word from the EEPROM when in the ISA ID probe state. */
-static ushort __init id_read_eeprom(int index)
+static ushort id_read_eeprom(int index)
 {
 	int bit, word = 0;
 
@@ -765,7 +754,7 @@
 		word = (word << 1) + (inb(id_port) & 0x01);
 
 	if (el3_debug > 3)
-		printk("  3c509 EEPROM word %d %#4.4x.\n", index, word);
+		printk(KERN_DEBUG "  3c509 EEPROM word %d %#4.4x.\n", index, word);
 
 	return word;
 }
@@ -787,13 +776,13 @@
 
 	EL3WINDOW(0);
 	if (el3_debug > 3)
-		printk("%s: Opening, IRQ %d	 status@%x %4.4x.\n", dev->name,
+		printk(KERN_DEBUG "%s: Opening, IRQ %d	 status@%x %4.4x.\n", dev->name,
 			   dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
 
 	el3_up(dev);
 
 	if (el3_debug > 3)
-		printk("%s: Opened 3c509  IRQ %d  status %4.4x.\n",
+		printk(KERN_DEBUG "%s: Opened 3c509  IRQ %d  status %4.4x.\n",
 			   dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
 
 	return 0;
@@ -806,7 +795,7 @@
 	int ioaddr = dev->base_addr;
 
 	/* Transmitter timeout, serious problems. */
-	printk("%s: transmit timed out, Tx_status %2.2x status %4.4x "
+	printk(KERN_WARNING "%s: transmit timed out, Tx_status %2.2x status %4.4x "
 		   "Tx FIFO room %d.\n",
 		   dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
 		   inw(ioaddr + TX_FREE));
@@ -831,7 +820,7 @@
 	lp->stats.tx_bytes += skb->len;
 
 	if (el3_debug > 4) {
-		printk("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
+		printk(KERN_DEBUG "%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
 			   dev->name, skb->len, inw(ioaddr + EL3_STATUS));
 	}
 #if 0
@@ -840,7 +829,7 @@
 		ushort status = inw(ioaddr + EL3_STATUS);
 		if (status & 0x0001 		/* IRQ line active, missed one. */
 			&& inw(ioaddr + EL3_STATUS) & 1) { 			/* Make sure. */
-			printk("%s: Missed interrupt, status then %04x now %04x"
+			printk(KERN_DEBUG "%s: Missed interrupt, status then %04x now %04x"
 				   "  Tx %2.2x Rx %4.4x.\n", dev->name, status,
 				   inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
 				   inw(ioaddr + RX_STATUS));
@@ -914,7 +903,7 @@
 
 	if (el3_debug > 4) {
 		status = inw(ioaddr + EL3_STATUS);
-		printk("%s: interrupt, status %4.4x.\n", dev->name, status);
+		printk(KERN_DEBUG "%s: interrupt, status %4.4x.\n", dev->name, status);
 	}
 
 	while ((status = inw(ioaddr + EL3_STATUS)) &
@@ -925,7 +914,7 @@
 
 		if (status & TxAvailable) {
 			if (el3_debug > 5)
-				printk("	TX room bit was handled.\n");
+				printk(KERN_DEBUG "	TX room bit was handled.\n");
 			/* There's room in the FIFO for a full-sized packet. */
 			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
 			netif_wake_queue (dev);
@@ -964,7 +953,7 @@
 		}
 
 		if (--i < 0) {
-			printk("%s: Infinite loop in interrupt, status %4.4x.\n",
+			printk(KERN_ERR "%s: Infinite loop in interrupt, status %4.4x.\n",
 				   dev->name, status);
 			/* Clear all interrupts. */
 			outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
@@ -975,7 +964,7 @@
 	}
 
 	if (el3_debug > 4) {
-		printk("%s: exiting interrupt, status %4.4x.\n", dev->name,
+		printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", dev->name,
 			   inw(ioaddr + EL3_STATUS));
 	}
 	spin_unlock(&lp->lock);
@@ -1450,7 +1439,7 @@
 }
 
 /* Power Management support functions */
-#ifdef EL3_SUSPEND
+#ifdef CONFIG_PM
 
 static int
 el3_suspend(struct device *pdev, pm_message_t state)
@@ -1500,79 +1489,102 @@
 	return 0;
 }
 
-#endif /* EL3_SUSPEND */
-
-/* Parameters that may be passed into the module. */
-static int debug = -1;
-static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int xcvr[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+#endif /* CONFIG_PM */
 
 module_param(debug,int, 0);
 module_param_array(irq, int, NULL, 0);
-module_param_array(xcvr, int, NULL, 0);
 module_param(max_interrupt_work, int, 0);
 MODULE_PARM_DESC(debug, "debug level (0-6)");
 MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
-MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)");
 MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
-#if defined(__ISAPNP__)
+#ifdef CONFIG_PNP
 module_param(nopnp, int, 0);
 MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
-MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters);
-#endif	/* __ISAPNP__ */
-MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B) ISA/PnP ethernet driver");
+#endif	/* CONFIG_PNP */
+MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B, 3c529, 3c579) ethernet driver");
 MODULE_LICENSE("GPL");
 
 static int __init el3_init_module(void)
 {
 	int ret = 0;
-	el3_cards = 0;
 
 	if (debug >= 0)
 		el3_debug = debug;
 
-	el3_root_dev = NULL;
-	while (el3_probe(el3_cards) == 0) {
-		if (irq[el3_cards] > 1)
-			el3_root_dev->irq = irq[el3_cards];
-		if (xcvr[el3_cards] >= 0)
-			el3_root_dev->if_port = xcvr[el3_cards];
-		el3_cards++;
+#ifdef CONFIG_PNP
+	if (!nopnp) {
+		ret = pnp_register_driver(&el3_pnp_driver);
+		if (!ret)
+			pnp_registered = 1;
+	}
+#endif
+	/* Select an open I/O location at 0x1*0 to do ISA contention select. */
+	/* Start with 0x110 to avoid some sound cards.*/
+	for (id_port = 0x110 ; id_port < 0x200; id_port += 0x10) {
+		if (!request_region(id_port, 1, "3c509-control"))
+			continue;
+		outb(0x00, id_port);
+		outb(0xff, id_port);
+		if (inb(id_port) & 0x01)
+			break;
+		else
+			release_region(id_port, 1);
+	}
+	if (id_port >= 0x200) {
+		id_port = 0;
+		printk(KERN_ERR "No I/O port available for 3c509 activation.\n");
+	} else {
+		ret = isa_register_driver(&el3_isa_driver, EL3_MAX_CARDS);
+		if (!ret)
+			isa_registered = 1;
 	}
-
 #ifdef CONFIG_EISA
 	ret = eisa_driver_register(&el3_eisa_driver);
+	if (!ret)
+		eisa_registered = 1;
 #endif
 #ifdef CONFIG_MCA
-	{
-		int err = mca_register_driver(&el3_mca_driver);
-		if (ret == 0)
-			ret = err;
-	}
+	ret = mca_register_driver(&el3_mca_driver);
+	if (!ret)
+		mca_registered = 1;
+#endif
+
+#ifdef CONFIG_PNP
+	if (pnp_registered)
+		ret = 0;
+#endif
+	if (isa_registered)
+		ret = 0;
+#ifdef CONFIG_EISA
+	if (eisa_registered)
+		ret = 0;
+#endif
+#ifdef CONFIG_MCA
+	if (mca_registered)
+		ret = 0;
 #endif
 	return ret;
 }
 
 static void __exit el3_cleanup_module(void)
 {
-	struct net_device *next_dev;
-
-	while (el3_root_dev) {
-		struct el3_private *lp = netdev_priv(el3_root_dev);
-
-		next_dev = lp->next_dev;
-		el3_common_remove (el3_root_dev);
-		el3_root_dev = next_dev;
-	}
-
+#ifdef CONFIG_PNP
+	if (pnp_registered)
+		pnp_unregister_driver(&el3_pnp_driver);
+#endif
+	if (isa_registered)
+		isa_unregister_driver(&el3_isa_driver);
+	if (id_port)
+		release_region(id_port, 1);
 #ifdef CONFIG_EISA
-	eisa_driver_unregister (&el3_eisa_driver);
+	if (eisa_registered)
+		eisa_driver_unregister(&el3_eisa_driver);
 #endif
 #ifdef CONFIG_MCA
-	mca_unregister_driver(&el3_mca_driver);
+	if (mca_registered)
+		mca_unregister_driver(&el3_mca_driver);
 #endif
 }
 
 module_init (el3_init_module);
 module_exit (el3_cleanup_module);
-


-- 
Ondrej Zary

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox