* [PATCH v4] PPTP: PPP over IPv4 (Point-to-Point Tunneling Protocol)
From: Dmitry Kozlov @ 2010-08-18 12:30 UTC (permalink / raw)
To: netdev
This patch contains:
1. pptp driver
2. gre demultiplexer driver for demultiplexing gre packets with different gre version
so ip_gre and pptp may coexists
3. ip_gre modification
4. other stuff
Changes from patch v3:
1. using rcu instead of read-write lock in gre module
2. fixed coding style issues
--
MAINTAINERS | 14 +
drivers/net/Kconfig | 11 +
drivers/net/Makefile | 1 +
drivers/net/pptp.c | 725 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/if_pppox.h | 49 +++-
include/net/gre.h | 18 ++
net/ipv4/Kconfig | 7 +
net/ipv4/Makefile | 1 +
net/ipv4/gre.c | 152 ++++++++++
net/ipv4/ip_gre.c | 10 +-
10 files changed, 968 insertions(+), 20 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 02f75fc..cdae013 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6450,6 +6450,20 @@ M: "Maciej W. Rozycki" <macro@linux-mips.org>
S: Maintained
F: drivers/serial/zs.*
+GRE DEMULTIPLEXER DRIVER
+M: Dmitry Kozlov <xeb@mail.ru>
+L: netdev@vger.kernel.org
+S: Maintained
+F: net/ipv4/gre.c
+F: include/net/gre.h
+
+PPTP DRIVER
+M: Dmitry Kozlov <xeb@mail.ru>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/pptp.c
+W: http://sourceforge.net/projects/accel-pptp
+
THE REST
M: Linus Torvalds <torvalds@linux-foundation.org>
L: linux-kernel@vger.kernel.org
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ce2fcdd..2fa0516 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -3167,6 +3167,17 @@ config PPPOE
which contains instruction on how to use this driver (under
the heading "Kernel mode PPPoE").
+config PPTP
+ tristate "PPP over IPv4 (PPTP) (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && PPP && NET_IPGRE_DEMUX
+ help
+ Support for PPP over IPv4.(Point-to-Point Tunneling Protocol)
+
+ This driver requires pppd plugin to work in client mode or
+ modified pptpd (poptop) to work in server mode.
+ See http://accel-pptp.sourceforge.net/ for information how to
+ utilize this module.
+
config PPPOATM
tristate "PPP over ATM"
depends on ATM && PPP
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 0a0512a..b33fef1 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -162,6 +162,7 @@ obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
obj-$(CONFIG_PPPOL2TP) += pppox.o
+obj-$(CONFIG_PPTP) += pppox.o pptp.o
obj-$(CONFIG_SLIP) += slip.o
obj-$(CONFIG_SLHC) += slhc.o
diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c
new file mode 100644
index 0000000..358fe31
--- /dev/null
+++ b/drivers/net/pptp.c
@@ -0,0 +1,725 @@
+/*
+ * Point-to-Point Tunneling Protocol for Linux
+ *
+ * Authors: Dmitry Kozlov <xeb@mail.ru>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/ppp_channel.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_pppox.h>
+#include <linux/if_ppp.h>
+#include <linux/notifier.h>
+#include <linux/file.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/version.h>
+#include <linux/rcupdate.h>
+#include <linux/semaphore.h>
+
+#include <net/sock.h>
+#include <net/protocol.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <net/route.h>
+#include <net/gre.h>
+
+#include <linux/uaccess.h>
+
+#define PPTP_DRIVER_VERSION "0.8.4"
+
+#define MAX_CALLID 65535
+
+static DECLARE_BITMAP(callid_bitmap, MAX_CALLID + 1);
+static struct pppox_sock **callid_sock;
+
+static DEFINE_MUTEX(chan_lock);
+
+static int pptp_xmit(struct ppp_channel *, struct sk_buff *);
+static int pptp_ppp_ioctl(struct ppp_channel *, unsigned int, unsigned long);
+static int pptp_rcv_core(struct sock *, struct sk_buff *);
+
+static struct ppp_channel_ops pptp_chan_ops = {
+ .start_xmit = pptp_xmit,
+ .ioctl = pptp_ppp_ioctl,
+};
+
+#define PPP_LCP_ECHOREQ 0x09
+#define PPP_LCP_ECHOREP 0x0A
+#define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
+
+#define MISSING_WINDOW 20
+#define WRAPPED(curseq, lastseq)\
+ ((((curseq) & 0xffffff00) == 0) &&\
+ (((lastseq) & 0xffffff00) == 0xffffff00))
+
+#define PPTP_GRE_PROTO 0x880B
+#define PPTP_GRE_VER 0x1
+
+#define PPTP_GRE_FLAG_C 0x80
+#define PPTP_GRE_FLAG_R 0x40
+#define PPTP_GRE_FLAG_K 0x20
+#define PPTP_GRE_FLAG_S 0x10
+#define PPTP_GRE_FLAG_A 0x80
+
+#define PPTP_GRE_IS_C(f) ((f)&PPTP_GRE_FLAG_C)
+#define PPTP_GRE_IS_R(f) ((f)&PPTP_GRE_FLAG_R)
+#define PPTP_GRE_IS_K(f) ((f)&PPTP_GRE_FLAG_K)
+#define PPTP_GRE_IS_S(f) ((f)&PPTP_GRE_FLAG_S)
+#define PPTP_GRE_IS_A(f) ((f)&PPTP_GRE_FLAG_A)
+
+#define PPTP_HEADER_OVERHEAD (2+sizeof(struct pptp_gre_header))
+struct pptp_gre_header {
+ u8 flags;
+ u8 ver;
+ u16 protocol;
+ u16 payload_len;
+ u16 call_id;
+ u32 seq;
+ u32 ack;
+};
+
+static struct pppox_sock *lookup_chan(__u16 call_id, __be32 s_addr)
+{
+ struct pppox_sock *sock;
+ struct pptp_opt *opt;
+
+ rcu_read_lock();
+ sock = rcu_dereference(callid_sock[call_id]);
+ if (sock) {
+ opt = &sock->proto.pptp;
+ if (opt->dst_addr.sin_addr.s_addr != s_addr)
+ sock = NULL;
+ else
+ sock_hold(sk_pppox(sock));
+ }
+ rcu_read_unlock();
+
+ return sock;
+}
+
+static int lookup_chan_dst(__u16 call_id, __be32 d_addr)
+{
+ struct pppox_sock *sock;
+ struct pptp_opt *opt;
+ int i;
+
+ mutex_lock(&chan_lock);
+ for (i = find_next_bit(callid_bitmap, MAX_CALLID, 1); i < MAX_CALLID; i = find_next_bit(callid_bitmap, MAX_CALLID, i + 1)) {
+ sock = callid_sock[i];
+ opt = &sock->proto.pptp;
+ if (opt->dst_addr.call_id == call_id && opt->dst_addr.sin_addr.s_addr == d_addr)
+ break;
+ }
+ mutex_unlock(&chan_lock);
+
+ return i < MAX_CALLID;
+}
+
+static int add_chan(struct pppox_sock *sock)
+{
+ static int call_id;
+
+ mutex_lock(&chan_lock);
+ if (!sock->proto.pptp.src_addr.call_id) {
+ call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1);
+ if (call_id == MAX_CALLID)
+ call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1);
+ if (call_id == MAX_CALLID)
+ goto out_err;
+ sock->proto.pptp.src_addr.call_id = call_id;
+ } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap))
+ goto out_err;
+
+ set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
+ rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock);
+ mutex_unlock(&chan_lock);
+ synchronize_rcu();
+
+ return 0;
+
+out_err:
+ mutex_unlock(&chan_lock);
+ return -1;
+}
+
+static void del_chan(struct pppox_sock *sock)
+{
+ mutex_lock(&chan_lock);
+ clear_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
+ rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], NULL);
+ mutex_unlock(&chan_lock);
+ synchronize_rcu();
+}
+
+static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+{
+ struct sock *sk = (struct sock *) chan->private;
+ struct pppox_sock *po = pppox_sk(sk);
+ struct pptp_opt *opt = &po->proto.pptp;
+ struct pptp_gre_header *hdr;
+ unsigned int header_len = sizeof(*hdr);
+ int err = 0;
+ int islcp;
+ int len;
+ unsigned char *data;
+ __u32 seq_recv;
+
+
+ struct rtable *rt;
+ struct net_device *tdev;
+ struct iphdr *iph;
+ int max_headroom;
+
+ if (sk_pppox(po)->sk_state & PPPOX_DEAD)
+ goto tx_error;
+
+ {
+ struct flowi fl = { .oif = 0,
+ .nl_u = {
+ .ip4_u = {
+ .daddr = opt->dst_addr.sin_addr.s_addr,
+ .saddr = opt->src_addr.sin_addr.s_addr,
+ .tos = RT_TOS(0) } },
+ .proto = IPPROTO_GRE };
+ err = ip_route_output_key(&init_net, &rt, &fl);
+ if (err)
+ goto tx_error;
+ }
+ tdev = rt->u.dst.dev;
+
+ max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(*iph) + sizeof(*hdr) + 2;
+
+ if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+ struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
+ if (!new_skb) {
+ ip_rt_put(rt);
+ goto tx_error;
+ }
+ if (skb->sk)
+ skb_set_owner_w(new_skb, skb->sk);
+ kfree_skb(skb);
+ skb = new_skb;
+ }
+
+ data = skb->data;
+ islcp = ((data[0] << 8) + data[1]) == PPP_LCP && 1 <= data[2] && data[2] <= 7;
+
+ /* compress protocol field */
+ if ((opt->ppp_flags & SC_COMP_PROT) && data[0] == 0 && !islcp)
+ skb_pull(skb, 1);
+
+ /* Put in the address/control bytes if necessary */
+ if ((opt->ppp_flags & SC_COMP_AC) == 0 || islcp) {
+ data = skb_push(skb, 2);
+ data[0] = PPP_ALLSTATIONS;
+ data[1] = PPP_UI;
+ }
+
+ len = skb->len;
+
+ seq_recv = opt->seq_recv;
+
+ if (opt->ack_sent == seq_recv)
+ header_len -= sizeof(hdr->ack);
+
+ /* Push down and install GRE header */
+ skb_push(skb, header_len);
+ hdr = (struct pptp_gre_header *)(skb->data);
+
+ hdr->flags = PPTP_GRE_FLAG_K;
+ hdr->ver = PPTP_GRE_VER;
+ hdr->protocol = htons(PPTP_GRE_PROTO);
+ hdr->call_id = htons(opt->dst_addr.call_id);
+
+ hdr->flags |= PPTP_GRE_FLAG_S;
+ hdr->seq = htonl(++opt->seq_sent);
+ if (opt->ack_sent != seq_recv) {
+ /* send ack with this message */
+ hdr->ver |= PPTP_GRE_FLAG_A;
+ hdr->ack = htonl(seq_recv);
+ opt->ack_sent = seq_recv;
+ }
+ hdr->payload_len = htons(len);
+
+ /* Push down and install the IP header. */
+
+ skb_reset_transport_header(skb);
+ skb_push(skb, sizeof(*iph));
+ skb_reset_network_header(skb);
+ memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+ IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
+
+ iph = ip_hdr(skb);
+ iph->version = 4;
+ iph->ihl = sizeof(struct iphdr) >> 2;
+ if (ip_dont_fragment(sk, &rt->u.dst))
+ iph->frag_off = htons(IP_DF);
+ else
+ iph->frag_off = 0;
+ iph->protocol = IPPROTO_GRE;
+ iph->tos = 0;
+ iph->daddr = rt->rt_dst;
+ iph->saddr = rt->rt_src;
+ iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT);
+ iph->tot_len = htons(skb->len);
+
+ skb_dst_drop(skb);
+ skb_dst_set(skb, &rt->u.dst);
+
+ nf_reset(skb);
+
+ skb->ip_summed = CHECKSUM_NONE;
+ ip_select_ident(iph, &rt->u.dst, NULL);
+ ip_send_check(iph);
+
+ ip_local_out(skb);
+
+tx_error:
+ return 1;
+}
+
+static int pptp_rcv_core(struct sock *sk, struct sk_buff *skb)
+{
+ struct pppox_sock *po = pppox_sk(sk);
+ struct pptp_opt *opt = &po->proto.pptp;
+ int headersize, payload_len, seq;
+ __u8 *payload;
+ struct pptp_gre_header *header;
+
+ if (!(sk->sk_state & PPPOX_CONNECTED)) {
+ if (sock_queue_rcv_skb(sk, skb))
+ goto drop;
+ return NET_RX_SUCCESS;
+ }
+
+ header = (struct pptp_gre_header *)(skb->data);
+
+ /* test if acknowledgement present */
+ if (PPTP_GRE_IS_A(header->ver)) {
+ __u32 ack = (PPTP_GRE_IS_S(header->flags)) ?
+ header->ack : header->seq; /* ack in different place if S = 0 */
+
+ ack = ntohl(ack);
+
+ if (ack > opt->ack_recv)
+ opt->ack_recv = ack;
+ /* also handle sequence number wrap-around */
+ if (WRAPPED(ack, opt->ack_recv))
+ opt->ack_recv = ack;
+ }
+
+ /* test if payload present */
+ if (!PPTP_GRE_IS_S(header->flags))
+ goto drop;
+
+ headersize = sizeof(*header);
+ payload_len = ntohs(header->payload_len);
+ seq = ntohl(header->seq);
+
+ /* no ack present? */
+ if (!PPTP_GRE_IS_A(header->ver))
+ headersize -= sizeof(header->ack);
+ /* check for incomplete packet (length smaller than expected) */
+ if (skb->len - headersize < payload_len)
+ goto drop;
+
+ payload = skb->data + headersize;
+ /* check for expected sequence number */
+ if (seq < opt->seq_recv + 1 || WRAPPED(opt->seq_recv, seq)) {
+ if ((payload[0] == PPP_ALLSTATIONS) && (payload[1] == PPP_UI) &&
+ (PPP_PROTOCOL(payload) == PPP_LCP) &&
+ ((payload[4] == PPP_LCP_ECHOREQ) || (payload[4] == PPP_LCP_ECHOREP)))
+ goto allow_packet;
+ } else {
+ opt->seq_recv = seq;
+allow_packet:
+ skb_pull(skb, headersize);
+
+ if (payload[0] == PPP_ALLSTATIONS && payload[1] == PPP_UI) {
+ /* chop off address/control */
+ if (skb->len < 3)
+ goto drop;
+ skb_pull(skb, 2);
+ }
+
+ if ((*skb->data) & 1) {
+ /* protocol is compressed */
+ skb_push(skb, 1)[0] = 0;
+ }
+
+ skb->ip_summed = CHECKSUM_NONE;
+ skb_set_network_header(skb, skb->head-skb->data);
+ ppp_input(&po->chan, skb);
+
+ return NET_RX_SUCCESS;
+ }
+drop:
+ kfree_skb(skb);
+ return NET_RX_DROP;
+}
+
+static int pptp_rcv(struct sk_buff *skb)
+{
+ struct pppox_sock *po;
+ struct pptp_gre_header *header;
+ struct iphdr *iph;
+
+ if (skb->pkt_type != PACKET_HOST)
+ goto drop;
+
+ if (!pskb_may_pull(skb, 12))
+ goto drop;
+
+ iph = ip_hdr(skb);
+
+ header = (struct pptp_gre_header *)skb->data;
+
+ if (
+ /* version should be 1 */
+ ((header->ver & 0x7F) != PPTP_GRE_VER) ||
+ /* PPTP-GRE protocol for PPTP */
+ (ntohs(header->protocol) != PPTP_GRE_PROTO) ||
+ /* flag C should be clear */
+ PPTP_GRE_IS_C(header->flags) ||
+ /* flag R should be clear */
+ PPTP_GRE_IS_R(header->flags) ||
+ /* flag K should be set */
+ (!PPTP_GRE_IS_K(header->flags)) ||
+ /* routing and recursion ctrl = 0 */
+ ((header->flags&0xF) != 0))
+ /* if invalid, discard this packet */
+ goto drop;
+
+
+ po = lookup_chan(htons(header->call_id), iph->saddr);
+ if (po) {
+ skb_dst_drop(skb);
+ skb_dst_set(skb, NULL);
+ nf_reset(skb);
+ return sk_receive_skb(sk_pppox(po), skb, 0);
+ }
+drop:
+ kfree_skb(skb);
+ return NET_RX_DROP;
+}
+
+static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr, int sockaddr_len)
+{
+ struct sock *sk = sock->sk;
+ struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
+ struct pppox_sock *po = pppox_sk(sk);
+ struct pptp_opt *opt = &po->proto.pptp;
+ int error = 0;
+
+ lock_sock(sk);
+
+ opt->src_addr = sp->sa_addr.pptp;
+ if (add_chan(po)) {
+ release_sock(sk);
+ error = -EBUSY;
+ }
+
+ release_sock(sk);
+ return error;
+}
+
+static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
+ int sockaddr_len, int flags)
+{
+ struct sock *sk = sock->sk;
+ struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
+ struct pppox_sock *po = pppox_sk(sk);
+ struct pptp_opt *opt = &po->proto.pptp;
+ struct rtable *rt;
+ int error = 0;
+
+ if (sp->sa_protocol != PX_PROTO_PPTP)
+ return -EINVAL;
+
+ if (lookup_chan_dst(sp->sa_addr.pptp.call_id, sp->sa_addr.pptp.sin_addr.s_addr))
+ return -EALREADY;
+
+ lock_sock(sk);
+ /* Check for already bound sockets */
+ if (sk->sk_state & PPPOX_CONNECTED) {
+ error = -EBUSY;
+ goto end;
+ }
+
+ /* Check for already disconnected sockets, on attempts to disconnect */
+ if (sk->sk_state & PPPOX_DEAD) {
+ error = -EALREADY;
+ goto end;
+ }
+
+ if (!opt->src_addr.sin_addr.s_addr || !sp->sa_addr.pptp.sin_addr.s_addr) {
+ error = -EINVAL;
+ goto end;
+ }
+
+ po->chan.private = sk;
+ po->chan.ops = &pptp_chan_ops;
+
+ {
+ struct flowi fl = {
+ .nl_u = {
+ .ip4_u = {
+ .daddr = opt->dst_addr.sin_addr.s_addr,
+ .saddr = opt->src_addr.sin_addr.s_addr,
+ .tos = RT_CONN_FLAGS(sk) } },
+ .proto = IPPROTO_GRE };
+ security_sk_classify_flow(sk, &fl);
+ if (ip_route_output_key(&init_net, &rt, &fl)) {
+ error = -EHOSTUNREACH;
+ goto end;
+ }
+ sk_setup_caps(sk, &rt->u.dst);
+ }
+ po->chan.mtu = dst_mtu(&rt->u.dst);
+ if (!po->chan.mtu)
+ po->chan.mtu = PPP_MTU;
+ ip_rt_put(rt);
+ po->chan.mtu -= PPTP_HEADER_OVERHEAD;
+
+ po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header);
+ error = ppp_register_channel(&po->chan);
+ if (error) {
+ printk(KERN_ERR "PPTP: failed to register PPP channel (%d)\n", error);
+ goto end;
+ }
+
+ opt->dst_addr = sp->sa_addr.pptp;
+ sk->sk_state = PPPOX_CONNECTED;
+
+ end:
+ release_sock(sk);
+ return error;
+}
+
+static int pptp_getname(struct socket *sock, struct sockaddr *uaddr,
+ int *usockaddr_len, int peer)
+{
+ int len = sizeof(struct sockaddr_pppox);
+ struct sockaddr_pppox sp;
+
+ sp.sa_family = AF_PPPOX;
+ sp.sa_protocol = PX_PROTO_PPTP;
+ sp.sa_addr.pptp = pppox_sk(sock->sk)->proto.pptp.src_addr;
+
+ memcpy(uaddr, &sp, len);
+
+ *usockaddr_len = len;
+
+ return 0;
+}
+
+static int pptp_release(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+ struct pppox_sock *po;
+ struct pptp_opt *opt;
+ int error = 0;
+
+ if (!sk)
+ return 0;
+
+ lock_sock(sk);
+
+ if (sock_flag(sk, SOCK_DEAD)) {
+ release_sock(sk);
+ return -EBADF;
+ }
+
+ po = pppox_sk(sk);
+ opt = &po->proto.pptp;
+ del_chan(po);
+
+ pppox_unbind_sock(sk);
+ sk->sk_state = PPPOX_DEAD;
+
+ sock_orphan(sk);
+ sock->sk = NULL;
+
+ release_sock(sk);
+ sock_put(sk);
+
+ return error;
+}
+
+
+static struct proto pptp_sk_proto __read_mostly = {
+ .name = "PPTP",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct pppox_sock),
+};
+
+static const struct proto_ops pptp_ops = {
+ .family = AF_PPPOX,
+ .owner = THIS_MODULE,
+ .release = pptp_release,
+ .bind = pptp_bind,
+ .connect = pptp_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = sock_no_accept,
+ .getname = pptp_getname,
+ .poll = sock_no_poll,
+ .listen = sock_no_listen,
+ .shutdown = sock_no_shutdown,
+ .setsockopt = sock_no_setsockopt,
+ .getsockopt = sock_no_getsockopt,
+ .sendmsg = sock_no_sendmsg,
+ .recvmsg = sock_no_recvmsg,
+ .mmap = sock_no_mmap,
+ .ioctl = pppox_ioctl,
+};
+
+static void pptp_sock_destruct(struct sock *sk)
+{
+ if (!(sk->sk_state & PPPOX_DEAD)) {
+ del_chan(pppox_sk(sk));
+ pppox_unbind_sock(sk);
+ }
+ skb_queue_purge(&sk->sk_receive_queue);
+}
+static int pptp_create(struct net *net, struct socket *sock)
+{
+ int error = -ENOMEM;
+ struct sock *sk;
+ struct pppox_sock *po;
+ struct pptp_opt *opt;
+
+ sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pptp_sk_proto);
+ if (!sk)
+ goto out;
+
+ sock_init_data(sock, sk);
+
+ sock->state = SS_UNCONNECTED;
+ sock->ops = &pptp_ops;
+
+ sk->sk_backlog_rcv = pptp_rcv_core;
+ sk->sk_state = PPPOX_NONE;
+ sk->sk_type = SOCK_STREAM;
+ sk->sk_family = PF_PPPOX;
+ sk->sk_protocol = PX_PROTO_PPTP;
+ sk->sk_destruct = pptp_sock_destruct;
+
+ po = pppox_sk(sk);
+ opt = &po->proto.pptp;
+
+ opt->seq_sent = 0; opt->seq_recv = 0;
+ opt->ack_recv = 0; opt->ack_sent = 0;
+
+ error = 0;
+out:
+ return error;
+}
+
+static int pptp_ppp_ioctl(struct ppp_channel *chan, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sock *sk = (struct sock *) chan->private;
+ struct pppox_sock *po = pppox_sk(sk);
+ struct pptp_opt *opt = &po->proto.pptp;
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int err, val;
+
+ err = -EFAULT;
+ switch (cmd) {
+ case PPPIOCGFLAGS:
+ val = opt->ppp_flags;
+ if (put_user(val, p))
+ break;
+ err = 0;
+ break;
+ case PPPIOCSFLAGS:
+ if (get_user(val, p))
+ break;
+ opt->ppp_flags = val & ~SC_RCV_BITS;
+ err = 0;
+ break;
+ default:
+ err = -ENOTTY;
+ }
+
+ return err;
+}
+
+
+static struct pppox_proto pppox_pptp_proto = {
+ .create = pptp_create,
+ .owner = THIS_MODULE,
+};
+
+
+static struct gre_protocol gre_pptp_protocol = {
+ .handler = pptp_rcv,
+};
+
+static int __init pptp_init_module(void)
+{
+ int err = 0;
+ printk(KERN_INFO "PPTP driver version " PPTP_DRIVER_VERSION "\n");
+
+ if (gre_add_protocol(&gre_pptp_protocol, GREPROTO_PPTP) < 0) {
+ printk(KERN_INFO "PPTP: can't add protocol\n");
+ goto out;
+ }
+
+ err = proto_register(&pptp_sk_proto, 0);
+ if (err) {
+ printk(KERN_INFO "PPTP: can't register sk_proto\n");
+ goto out_inet_del_protocol;
+ }
+
+ err = register_pppox_proto(PX_PROTO_PPTP, &pppox_pptp_proto);
+ if (err) {
+ printk(KERN_INFO "PPTP: can't register pppox_proto\n");
+ goto out_unregister_sk_proto;
+ }
+
+ callid_sock = (struct pppox_sock **)vmalloc((MAX_CALLID + 1) * sizeof(void *));
+ memset(callid_sock, 0, (MAX_CALLID + 1) * sizeof(void *));
+
+out:
+ return err;
+out_unregister_sk_proto:
+ proto_unregister(&pptp_sk_proto);
+out_inet_del_protocol:
+ gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
+ return err;
+}
+
+static void __exit pptp_exit_module(void)
+{
+ unregister_pppox_proto(PX_PROTO_PPTP);
+ proto_unregister(&pptp_sk_proto);
+ gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
+ vfree(callid_sock);
+}
+
+module_init(pptp_init_module);
+module_exit(pptp_exit_module);
+
+MODULE_DESCRIPTION("Point-to-Point Tunneling Protocol");
+MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)");
+MODULE_LICENSE("GPL");
+
diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
index a6577af..9bc0717 100644
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -40,26 +40,37 @@
* PPPoE addressing definition
*/
typedef __be16 sid_t;
-struct pppoe_addr{
- sid_t sid; /* Session identifier */
- unsigned char remote[ETH_ALEN]; /* Remote address */
- char dev[IFNAMSIZ]; /* Local device to use */
+struct pppoe_addr {
+ sid_t sid; /* Session identifier */
+ unsigned char remote[ETH_ALEN]; /* Remote address */
+ char dev[IFNAMSIZ]; /* Local device to use */
};
/************************************************************************
- * Protocols supported by AF_PPPOX
- */
+ * PPTP addressing definition
+ */
+struct pptp_addr {
+ __u16 call_id;
+ struct in_addr sin_addr;
+};
+
+/************************************************************************
+ * Protocols supported by AF_PPPOX
+ */
#define PX_PROTO_OE 0 /* Currently just PPPoE */
#define PX_PROTO_OL2TP 1 /* Now L2TP also */
-#define PX_MAX_PROTO 2
+#define PX_PROTO_PPTP 2
+#define PX_MAX_PROTO 3
-struct sockaddr_pppox {
- sa_family_t sa_family; /* address family, AF_PPPOX */
- unsigned int sa_protocol; /* protocol identifier */
- union{
- struct pppoe_addr pppoe;
- }sa_addr;
-}__attribute__ ((packed));
+struct sockaddr_pppox {
+ sa_family_t sa_family; /* address family, AF_PPPOX */
+ unsigned int sa_protocol; /* protocol identifier */
+ union {
+ struct pppoe_addr pppoe;
+ struct pptp_addr pptp;
+ } sa_addr;
+} __attribute__ ((packed));
+/* hm ... why packed here ? */
/* The use of the above union isn't viable because the size of this
* struct must stay fixed over time -- applications use sizeof(struct
@@ -70,7 +81,7 @@ struct sockaddr_pppol2tp {
sa_family_t sa_family; /* address family, AF_PPPOX */
unsigned int sa_protocol; /* protocol identifier */
struct pppol2tp_addr pppol2tp;
-}__attribute__ ((packed));
+} __attribute__ ((packed));
/* The L2TPv3 protocol changes tunnel and session ids from 16 to 32
* bits. So we need a different sockaddr structure.
@@ -150,6 +161,13 @@ struct pppoe_opt {
relayed to (PPPoE relaying) */
};
+struct pptp_opt {
+ struct pptp_addr src_addr;
+ struct pptp_addr dst_addr;
+ __u32 ack_sent, ack_recv;
+ __u32 seq_sent, seq_recv;
+ int ppp_flags;
+};
#include <net/sock.h>
struct pppox_sock {
@@ -159,6 +177,7 @@ struct pppox_sock {
struct pppox_sock *next; /* for hash table */
union {
struct pppoe_opt pppoe;
+ struct pptp_opt pptp;
} proto;
__be16 num;
};
diff --git a/include/net/gre.h b/include/net/gre.h
new file mode 100644
index 0000000..31a0f76
--- /dev/null
+++ b/include/net/gre.h
@@ -0,0 +1,18 @@
+#ifndef __LINUX_GRE_H
+#define __LINUX_GRE_H
+
+#include <linux/skbuff.h>
+
+#define GREPROTO_CISCO 0
+#define GREPROTO_PPTP 1
+#define GREPROTO_MAX 2
+
+struct gre_protocol {
+ int (*handler)(struct sk_buff *skb);
+ void (*err_handler)(struct sk_buff *skb, u32 info);
+};
+
+int gre_add_protocol(const struct gre_protocol *proto, u8 version);
+int gre_del_protocol(const struct gre_protocol *proto, u8 version);
+
+#endif
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 7c3a7d1..7458bda 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -215,8 +215,15 @@ config NET_IPIP
be inserted in and removed from the running kernel whenever you
want). Most people won't need this and can say N.
+config NET_IPGRE_DEMUX
+ tristate "IP: GRE demultiplexer"
+ help
+ This is helper module to demultiplex GRE packets on GRE version field criteria.
+ Required by ip_gre and pptp modules.
+
config NET_IPGRE
tristate "IP: GRE tunnels over IP"
+ depends on NET_IPGRE_DEMUX
help
Tunneling means encapsulating data of one protocol type within
another protocol and sending it over a channel that understands the
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 80ff87c..4978d22 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
obj-$(CONFIG_IP_MROUTE) += ipmr.o
obj-$(CONFIG_NET_IPIP) += ipip.o
+obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o
obj-$(CONFIG_NET_IPGRE) += ip_gre.o
obj-$(CONFIG_SYN_COOKIES) += syncookies.o
obj-$(CONFIG_INET_AH) += ah4.o
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c
new file mode 100644
index 0000000..841a571
--- /dev/null
+++ b/net/ipv4/gre.c
@@ -0,0 +1,152 @@
+/*
+ * GRE over IPv4 demultiplexer driver
+ *
+ * Authors: Dmitry Kozlov (xeb@mail.ru)
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+#include <linux/spinlock.h>
+#include <net/protocol.h>
+#include <net/gre.h>
+
+
+const struct gre_protocol *gre_proto[GREPROTO_MAX] __read_mostly;
+static DEFINE_MUTEX(gre_proto_lock);
+
+int gre_add_protocol(const struct gre_protocol *proto, u8 version)
+{
+ if (version >= GREPROTO_MAX)
+ goto err_out;
+
+ mutex_lock(&gre_proto_lock);
+ if (gre_proto[version])
+ goto err_out_unlock;
+
+ rcu_assign_pointer(gre_proto[version], proto);
+ mutex_unlock(&gre_proto_lock);
+ synchronize_rcu();
+ return 0;
+
+err_out_unlock:
+ mutex_unlock(&gre_proto_lock);
+err_out:
+ return -1;
+}
+EXPORT_SYMBOL_GPL(gre_add_protocol);
+
+int gre_del_protocol(const struct gre_protocol *proto, u8 version)
+{
+ if (version >= GREPROTO_MAX)
+ goto err_out;
+
+ mutex_lock(&gre_proto_lock);
+ if (gre_proto[version] != proto)
+ goto err_out_unlock;
+ rcu_assign_pointer(gre_proto[version], NULL);
+ mutex_unlock(&gre_proto_lock);
+ synchronize_rcu();
+ return 0;
+
+err_out_unlock:
+ mutex_unlock(&gre_proto_lock);
+err_out:
+ return -1;
+}
+EXPORT_SYMBOL_GPL(gre_del_protocol);
+
+static int gre_rcv(struct sk_buff *skb)
+{
+ const struct gre_protocol *proto;
+ u8 ver;
+ int ret;
+
+ if (!pskb_may_pull(skb, 12))
+ goto drop;
+
+ ver = skb->data[1]&0x7f;
+ if (ver >= GREPROTO_MAX)
+ goto drop;
+
+ rcu_read_lock();
+ proto = rcu_dereference(gre_proto[ver]);
+ if (!proto || !proto->handler)
+ goto drop_unlock;
+ ret = proto->handler(skb);
+ rcu_read_unlock();
+ return ret;
+
+drop_unlock:
+ rcu_read_unlock();
+drop:
+ kfree_skb(skb);
+ return NET_RX_DROP;
+}
+
+static void gre_err(struct sk_buff *skb, u32 info)
+{
+ const struct gre_protocol *proto;
+ u8 ver;
+
+ if (!pskb_may_pull(skb, 12))
+ goto drop;
+
+ ver = skb->data[1]&0x7f;
+ if (ver >= GREPROTO_MAX)
+ goto drop;
+
+ rcu_read_lock();
+ proto = rcu_dereference(gre_proto[ver]);
+ if (!proto || !proto->err_handler)
+ goto drop_unlock;
+ proto->err_handler(skb, info);
+ rcu_read_unlock();
+ return;
+
+drop_unlock:
+ rcu_read_unlock();
+drop:
+ kfree_skb(skb);
+}
+
+static const struct net_protocol net_gre_protocol = {
+ .handler = gre_rcv,
+ .err_handler = gre_err,
+ .netns_ok = 1,
+};
+
+static int __init gre_init(void)
+{
+ printk(KERN_INFO "GRE over IPv4 demultiplexor driver");
+
+ if (inet_add_protocol(&net_gre_protocol, IPPROTO_GRE) < 0) {
+ printk(KERN_INFO "gre: can't add protocol\n");
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+static void __exit gre_exit(void)
+{
+ inet_del_protocol(&net_gre_protocol, IPPROTO_GRE);
+}
+
+module_init(gre_init);
+module_exit(gre_exit);
+
+MODULE_DESCRIPTION("GRE over IPv4 demultiplexer driver");
+MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)");
+MODULE_LICENSE("GPL");
+
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 32618e1..f0391b3 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -44,6 +44,7 @@
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <net/rtnetlink.h>
+#include <net/gre.h>
#ifdef CONFIG_IPV6
#include <net/ipv6.h>
@@ -1276,10 +1277,9 @@ static void ipgre_fb_tunnel_init(struct net_device *dev)
}
-static const struct net_protocol ipgre_protocol = {
+static const struct gre_protocol ipgre_protocol = {
.handler = ipgre_rcv,
.err_handler = ipgre_err,
- .netns_ok = 1,
};
static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head)
@@ -1661,7 +1661,7 @@ static int __init ipgre_init(void)
if (err < 0)
return err;
- err = inet_add_protocol(&ipgre_protocol, IPPROTO_GRE);
+ err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
if (err < 0) {
printk(KERN_INFO "ipgre init: can't add protocol\n");
goto add_proto_failed;
@@ -1681,7 +1681,7 @@ out:
tap_ops_failed:
rtnl_link_unregister(&ipgre_link_ops);
rtnl_link_failed:
- inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
+ gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
add_proto_failed:
unregister_pernet_device(&ipgre_net_ops);
goto out;
@@ -1691,7 +1691,7 @@ static void __exit ipgre_fini(void)
{
rtnl_link_unregister(&ipgre_tap_ops);
rtnl_link_unregister(&ipgre_link_ops);
- if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
+ if (gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0)
printk(KERN_INFO "ipgre close: can't remove protocol\n");
unregister_pernet_device(&ipgre_net_ops);
}
^ permalink raw reply related
* [PATCH] netxen: fix a race in netxen_nic_get_stats()
From: Eric Dumazet @ 2010-08-18 12:29 UTC (permalink / raw)
To: Amit Salecha; +Cc: David Miller, netdev
In-Reply-To: <99737F4847ED0A48AECC9F4A1974A4B80F86E69124@MNEXMB2.qlogic.org>
Le mercredi 18 août 2010 à 05:47 -0500, Amit Salecha a écrit :
> Same fix will be require for netxen_nic.
Indeed, here is netxen part
Thanks
[PATCH] netxen: fix a race in netxen_nic_get_stats()
Dont clear netdev->stats, it might give transient wrong values to
concurrent stat readers.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
drivers/net/netxen/netxen_nic_main.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index fd86e18..cb30df1 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -2032,8 +2032,6 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
struct netxen_adapter *adapter = netdev_priv(netdev);
struct net_device_stats *stats = &netdev->stats;
- memset(stats, 0, sizeof(*stats));
-
stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
stats->tx_packets = adapter->stats.xmitfinished;
stats->rx_bytes = adapter->stats.rxbytes;
^ permalink raw reply related
* [PATCH] xilinx_emaclite: netpoll support
From: Michal Simek @ 2010-08-18 11:22 UTC (permalink / raw)
To: davem; +Cc: netdev, Michal Simek
Netconsole requires poll support.
Signed-off-by: Michal Simek <monstr@monstr.eu>
---
drivers/net/xilinx_emaclite.c | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index ecbbb68..71122ee 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -1269,6 +1269,16 @@ static int __devexit xemaclite_of_remove(struct platform_device *of_dev)
return 0;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void
+xemaclite_poll_controller(struct net_device *ndev)
+{
+ disable_irq(ndev->irq);
+ xemaclite_interrupt(ndev->irq, ndev);
+ enable_irq(ndev->irq);
+}
+#endif
+
static struct net_device_ops xemaclite_netdev_ops = {
.ndo_open = xemaclite_open,
.ndo_stop = xemaclite_close,
@@ -1276,6 +1286,9 @@ static struct net_device_ops xemaclite_netdev_ops = {
.ndo_set_mac_address = xemaclite_set_mac_address,
.ndo_tx_timeout = xemaclite_tx_timeout,
.ndo_get_stats = xemaclite_get_stats,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = xemaclite_poll_controller,
+#endif
};
/* Match table for OF platform binding */
--
1.5.5.6
^ permalink raw reply related
* Re: [PATCH 8/8] net_sched: sch_sfq: use proto_ports_offset() to support AH message
From: jamal @ 2010-08-18 11:05 UTC (permalink / raw)
To: Changli Gao; +Cc: David S. Miller, netdev
In-Reply-To: <1282108055-3702-1-git-send-email-xiaosuo@gmail.com>
On Wed, 2010-08-18 at 13:07 +0800, Changli Gao wrote:
> const struct iphdr *iph;
> + int poff;
>
> if (!pskb_network_may_pull(skb, sizeof(*iph)))
> goto err;
> iph = ip_hdr(skb);
> h = (__force u32)iph->daddr;
> h2 = (__force u32)iph->saddr ^ iph->protocol;
> - if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
> - (iph->protocol == IPPROTO_TCP ||
> - iph->protocol == IPPROTO_UDP ||
> - iph->protocol == IPPROTO_UDPLITE ||
> - iph->protocol == IPPROTO_SCTP ||
> - iph->protocol == IPPROTO_DCCP ||
> - iph->protocol == IPPROTO_ESP) &&
> - pskb_network_may_pull(skb, iph->ihl * 4 + 4))
> - h2 ^= *(((u32*)iph) + iph->ihl);
> + if (iph->frag_off & htons(IP_MF|IP_OFFSET))
> + break;
> + poff = proto_ports_offset(iph->protocol);
> + if (poff >= 0 &&
> + pskb_network_may_pull(skb, iph->ihl * 4 + 4 + poff)) {
> + iph = ip_hdr(skb);
> + h2 ^= *(u32*)((void *)iph + iph->ihl * 4 + poff);
> + }
> break;
Same comment with this one as earlier patch? Or it may be too early
here ;->
cheers,
jamal
> case htons(ETH_P_IPV6):
> {
> struct ipv6hdr *iph;
> + int poff;
>
> if (!pskb_network_may_pull(skb, sizeof(*iph)))
> goto err;
> iph = ipv6_hdr(skb);
> h = (__force u32)iph->daddr.s6_addr32[3];
> h2 = (__force u32)iph->saddr.s6_addr32[3] ^ iph->nexthdr;
> - if ((iph->nexthdr == IPPROTO_TCP ||
> - iph->nexthdr == IPPROTO_UDP ||
> - iph->nexthdr == IPPROTO_UDPLITE ||
> - iph->nexthdr == IPPROTO_SCTP ||
> - iph->nexthdr == IPPROTO_DCCP ||
> - iph->nexthdr == IPPROTO_ESP) &&
> - pskb_network_may_pull(skb, sizeof(*iph) + 4))
> - h2 ^= *(u32*)&iph[1];
> + poff = proto_ports_offset(iph->nexthdr);
> + if (poff >= 0 &&
> + pskb_network_may_pull(skb, sizeof(*iph) + 4 + poff)) {
> + iph = ipv6_hdr(skb);
> + h2 ^= *(u32*)((void *)iph + sizeof(*iph) + poff);
> + }
> break;
> }
> default:
^ permalink raw reply
* RE: [RFC Patch] netxen: remove firmware exports
From: Amit Salecha @ 2010-08-18 11:04 UTC (permalink / raw)
To: Amerigo Wang, linux-kernel@vger.kernel.org
Cc: Dhananjay Phadke, Narender Kumar, netdev@vger.kernel.org,
David S. Miller, Ameen Rahman
In-Reply-To: <20100818095908.6606.56224.sendpatchset@localhost.localdomain>
If problem is firmware files are not present in /lib/firmware.
Then we can work with David Woodhouse and make these firmware available in /lib/firmware.
-----Original Message-----
From: Amerigo Wang [mailto:amwang@redhat.com]
Sent: Wednesday, August 18, 2010 3:25 PM
To: linux-kernel@vger.kernel.org
Cc: Dhananjay Phadke; Amit Salecha; Narender Kumar; netdev@vger.kernel.org; David S. Miller; Amerigo Wang
Subject: [RFC Patch] netxen: remove firmware exports
netxen_nic driver can store firmwares on flash, and get them porperly and
dynamically, so the firmwares may not appear in /lib/firmware/. However, netxen_nic
still exports these firmwares via modinfo, this makes our script which parses
modinfo output fail.
Probably netxen_nic has other way to export these firmwares, but not like other
modules in a stardand way. I think we can just remove these exports, but
I am not sure.
Signed-off-by: WANG Cong <amwang@redhat.com>
Cc: Amit Kumar Salecha <amit.salecha@qlogic.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Dhananjay Phadke <dhananjay.phadke@qlogic.com>
Cc: Narender Kumar <narender.kumar@qlogic.com>
---
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index fd86e18..e8443af 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -41,10 +41,6 @@
MODULE_DESCRIPTION("QLogic/NetXen (1/10) GbE Converged Ethernet Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID);
-MODULE_FIRMWARE(NX_P2_MN_ROMIMAGE_NAME);
-MODULE_FIRMWARE(NX_P3_CT_ROMIMAGE_NAME);
-MODULE_FIRMWARE(NX_P3_MN_ROMIMAGE_NAME);
-MODULE_FIRMWARE(NX_UNIFIED_ROMIMAGE_NAME);
char netxen_nic_driver_name[] = "netxen_nic";
static char netxen_nic_driver_string[] = "QLogic/NetXen Network Driver v"
^ permalink raw reply related
* Re: [PATCH 5/8] net_sched: cls_flow: use proto_ports_offset() to support AH message
From: jamal @ 2010-08-18 11:02 UTC (permalink / raw)
To: Changli Gao; +Cc: David S. Miller, netdev
In-Reply-To: <1282107908-3585-1-git-send-email-xiaosuo@gmail.com>
On Wed, 2010-08-18 at 13:05 +0800, Changli Gao wrote:
> -static int has_ports(u8 protocol)
> -{
> - switch (protocol) {
> - case IPPROTO_TCP:
> - case IPPROTO_UDP:
> - case IPPROTO_UDPLITE:
> - case IPPROTO_SCTP:
> - case IPPROTO_DCCP:
> - case IPPROTO_ESP:
> - return 1;
> - default:
> - return 0;
> - }
> -}
> -
> static u32 flow_get_proto_src(struct sk_buff *skb)
> {
> switch (skb->protocol) {
> case htons(ETH_P_IP): {
> struct iphdr *iph;
> + int poff;
>
> if (!pskb_network_may_pull(skb, sizeof(*iph)))
> break;
> iph = ip_hdr(skb);
> - if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
> - has_ports(iph->protocol) &&
> - pskb_network_may_pull(skb, iph->ihl * 4 + 2))
> - return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4));
> + if (iph->frag_off & htons(IP_MF|IP_OFFSET))
> + break;
> + poff = proto_ports_offset(iph->protocol);
> + if (poff >= 0 &&
I dont think this maintains the same semantic. Ex: In the original code
AH returns 0. In your case it returns 4 and passes the above test.
Same with the other spot.
cheers,
jamal
^ permalink raw reply
* Re: [PATCH v2] net/sched: add ACT_CSUM action to update packets checksums
From: jamal @ 2010-08-18 10:52 UTC (permalink / raw)
To: Grégoire Baron; +Cc: netdev
In-Reply-To: <20100817235952.GB24125@n7mm.org>
On Wed, 2010-08-18 at 01:59 +0200, Grégoire Baron wrote:
> +static int tcf_csum_ipv4_icmp(struct sk_buff *skb,
> + unsigned int ihl, unsigned int ipl)
> +{
> + struct icmphdr *icmph;
> +
> + icmph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*icmph));
> + if (icmph == NULL)
> + goto fail;
^^^^^^^^^^^
> + icmph->checksum = 0;
> + skb->csum = csum_partial(icmph, ipl - ihl, 0);
> + icmph->checksum = csum_fold(skb->csum);
> +
> + skb->ip_summed = CHECKSUM_NONE;
> +
> + return 1;
> +
> +fail:
> + return 0;
> +}
> +
I think you missed one of my earlier comments:
Do you really need this goto? You should just "return 0" instead of
"goto fail"
Same with many other similar places where the "fail:" just simply
returns 0 such as igmp, ipv6_icmp, ipv4_udp, etc
BTW, i still think there may be a clever way to unify things - but we
can leave that for another day;-> If you fix the above please add
my Acked-by.
cheers,
jamal
^ permalink raw reply
* RE: [PATCH] qlnic: fix a race in qlcnic_get_stats()
From: Amit Salecha @ 2010-08-18 10:47 UTC (permalink / raw)
To: Eric Dumazet, David Miller; +Cc: netdev
In-Reply-To: <1282128168.2194.49.camel@edumazet-laptop>
Same fix will be require for netxen_nic.
-----Original Message-----
From: Eric Dumazet [mailto:eric.dumazet@gmail.com]
Sent: Wednesday, August 18, 2010 4:13 PM
To: David Miller
Cc: Amit Salecha; netdev
Subject: [PATCH] qlnic: fix a race in qlcnic_get_stats()
Dont clear netdev->stats, it might give transient wrong values to
concurrent stat readers.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
drivers/net/qlcnic/qlcnic_main.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index abd7cd6..d71d44a 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -1980,8 +1980,6 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct net_device_stats *stats = &netdev->stats;
- memset(stats, 0, sizeof(*stats));
-
stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
stats->tx_packets = adapter->stats.xmitfinished;
stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
^ permalink raw reply related
* [PATCH] qlnic: fix a race in qlcnic_get_stats()
From: Eric Dumazet @ 2010-08-18 10:42 UTC (permalink / raw)
To: David Miller; +Cc: Amit Kumar Salecha, netdev
Dont clear netdev->stats, it might give transient wrong values to
concurrent stat readers.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
drivers/net/qlcnic/qlcnic_main.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index abd7cd6..d71d44a 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -1980,8 +1980,6 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct net_device_stats *stats = &netdev->stats;
- memset(stats, 0, sizeof(*stats));
-
stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
stats->tx_packets = adapter->stats.xmitfinished;
stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
^ permalink raw reply related
* Re: [PATCH] net/sched: add ACT_CSUM action to update packets checksums
From: jamal @ 2010-08-18 10:42 UTC (permalink / raw)
To: Grégoire Baron; +Cc: netdev, Eric Dumazet, David Miller
In-Reply-To: <20100818000425.GC24125@n7mm.org>
On Wed, 2010-08-18 at 02:04 +0200, Grégoire Baron wrote:
> Thank you for your help!
> I've just sent a new version (v2) of this patch.
No need for OOB msg - just Cc patch next time.
cheers,
jamal
^ permalink raw reply
* Re: [PATCH v3] PPTP: PPP over IPv4 (Point-to-Point Tunneling Protocol)
From: Dmitry Kozlov @ 2010-08-18 10:38 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev
In-Reply-To: <1282119905.2194.38.camel@edumazet-laptop>
Hi Eric!
Thanks for comments. All your comments was accepted except:
> > +static struct ppp_channel_ops pptp_chan_ops = {
>
> static const ?
not, because po->chan.ops = &pptp_chan_ops which is not const
> > +static DEFINE_RWLOCK(gre_proto_lock);
>
> This could use RCU and a spinlock instead
>
rcu + mutex
Patch v4 will be ready soon...
^ permalink raw reply
* [PATCH] ll_temac: Fix poll implementation
From: Michal Simek @ 2010-08-18 10:26 UTC (permalink / raw)
To: glikely; +Cc: davem, netdev, Michal Simek
Functions ll_temac_rx_irq and ll_temac_tx_irq
have pointer to net_device as second parameter not
pointer to temac_local.
Signed-off-by: Michal Simek <monstr@monstr.eu>
---
drivers/net/ll_temac_main.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index c7b6247..bdf2149 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -902,8 +902,8 @@ temac_poll_controller(struct net_device *ndev)
disable_irq(lp->tx_irq);
disable_irq(lp->rx_irq);
- ll_temac_rx_irq(lp->tx_irq, lp);
- ll_temac_tx_irq(lp->rx_irq, lp);
+ ll_temac_rx_irq(lp->tx_irq, ndev);
+ ll_temac_tx_irq(lp->rx_irq, ndev);
enable_irq(lp->tx_irq);
enable_irq(lp->rx_irq);
--
1.5.5.6
^ permalink raw reply related
* [PATCH] irda: fix a race in irlan_eth_xmit()
From: Eric Dumazet @ 2010-08-18 10:24 UTC (permalink / raw)
To: David Miller; +Cc: Samuel Ortiz, netdev
After skb is queued, its illegal to dereference it.
Cache skb->len into a temporary variable.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
net/irda/irlan/irlan_eth.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
index 9616c32..5bb8353 100644
--- a/net/irda/irlan/irlan_eth.c
+++ b/net/irda/irlan/irlan_eth.c
@@ -169,6 +169,7 @@ static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb,
{
struct irlan_cb *self = netdev_priv(dev);
int ret;
+ unsigned int len;
/* skb headroom large enough to contain all IrDA-headers? */
if ((skb_headroom(skb) < self->max_header_size) || (skb_shared(skb))) {
@@ -188,6 +189,7 @@ static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb,
dev->trans_start = jiffies;
+ len = skb->len;
/* Now queue the packet in the transport layer */
if (self->use_udata)
ret = irttp_udata_request(self->tsap_data, skb);
@@ -209,7 +211,7 @@ static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb,
self->stats.tx_dropped++;
} else {
self->stats.tx_packets++;
- self->stats.tx_bytes += skb->len;
+ self->stats.tx_bytes += len;
}
return NETDEV_TX_OK;
^ permalink raw reply related
* [RFC Patch] netxen: remove firmware exports
From: Amerigo Wang @ 2010-08-18 9:54 UTC (permalink / raw)
To: linux-kernel
Cc: Dhananjay Phadke, Amit Kumar Salecha, Narender Kumar, netdev,
David S. Miller, Amerigo Wang
netxen_nic driver can store firmwares on flash, and get them porperly and
dynamically, so the firmwares may not appear in /lib/firmware/. However, netxen_nic
still exports these firmwares via modinfo, this makes our script which parses
modinfo output fail.
Probably netxen_nic has other way to export these firmwares, but not like other
modules in a stardand way. I think we can just remove these exports, but
I am not sure.
Signed-off-by: WANG Cong <amwang@redhat.com>
Cc: Amit Kumar Salecha <amit.salecha@qlogic.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Dhananjay Phadke <dhananjay.phadke@qlogic.com>
Cc: Narender Kumar <narender.kumar@qlogic.com>
---
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index fd86e18..e8443af 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -41,10 +41,6 @@
MODULE_DESCRIPTION("QLogic/NetXen (1/10) GbE Converged Ethernet Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID);
-MODULE_FIRMWARE(NX_P2_MN_ROMIMAGE_NAME);
-MODULE_FIRMWARE(NX_P3_CT_ROMIMAGE_NAME);
-MODULE_FIRMWARE(NX_P3_MN_ROMIMAGE_NAME);
-MODULE_FIRMWARE(NX_UNIFIED_ROMIMAGE_NAME);
char netxen_nic_driver_name[] = "netxen_nic";
static char netxen_nic_driver_string[] = "QLogic/NetXen Network Driver v"
^ permalink raw reply related
* [PATCH v3] ether3: Use net_device_stats from struct net_device
From: Tobias Klauser @ 2010-08-18 8:46 UTC (permalink / raw)
To: David S. Miller, Russell King, netdev
Cc: linux-arm-kernel, kernel-janitors, Eric Dumazet, Dan Carpenter
In-Reply-To: <1282061733-19700-1-git-send-email-tklauser@distanz.ch>
struct net_device has its own struct net_device_stats member, so use
this one instead of a private copy in the ether1_priv struct. As the new
ndo_get_stats function would just return dev->stats we can omit it.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---
drivers/net/arm/ether3.c | 33 +++++++++++----------------------
drivers/net/arm/ether3.h | 1 -
2 files changed, 11 insertions(+), 23 deletions(-)
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index 1361b73..cebf2da 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -81,7 +81,6 @@ static int ether3_open (struct net_device *dev);
static int ether3_sendpacket (struct sk_buff *skb, struct net_device *dev);
static irqreturn_t ether3_interrupt (int irq, void *dev_id);
static int ether3_close (struct net_device *dev);
-static struct net_device_stats *ether3_getstats (struct net_device *dev);
static void ether3_setmulticastlist (struct net_device *dev);
static void ether3_timeout(struct net_device *dev);
@@ -323,7 +322,7 @@ ether3_init_for_open(struct net_device *dev)
{
int i;
- memset(&priv(dev)->stats, 0, sizeof(struct net_device_stats));
+ memset(&dev->stats, 0, sizeof(struct net_device_stats));
/* Reset the chip */
ether3_outw(CFG2_RESET, REG_CONFIG2);
@@ -442,15 +441,6 @@ ether3_close(struct net_device *dev)
}
/*
- * Get the current statistics. This may be called with the card open or
- * closed.
- */
-static struct net_device_stats *ether3_getstats(struct net_device *dev)
-{
- return &priv(dev)->stats;
-}
-
-/*
* Set or clear promiscuous/multicast mode filter for this adaptor.
*
* We don't attempt any packet filtering. The card may have a SEEQ 8004
@@ -490,7 +480,7 @@ static void ether3_timeout(struct net_device *dev)
local_irq_restore(flags);
priv(dev)->regs.config2 |= CFG2_CTRLO;
- priv(dev)->stats.tx_errors += 1;
+ dev->stats.tx_errors += 1;
ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
priv(dev)->tx_head = priv(dev)->tx_tail = 0;
@@ -509,7 +499,7 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
if (priv(dev)->broken) {
dev_kfree_skb(skb);
- priv(dev)->stats.tx_dropped ++;
+ dev->stats.tx_dropped++;
netif_start_queue(dev);
return NETDEV_TX_OK;
}
@@ -673,7 +663,7 @@ if (next_ptr < RX_START || next_ptr >= RX_END) {
} else
goto dropping;
} else {
- struct net_device_stats *stats = &priv(dev)->stats;
+ struct net_device_stats *stats = &dev->stats;
ether3_outw(next_ptr >> 8, REG_RECVEND);
if (status & RXSTAT_OVERSIZE) stats->rx_over_errors ++;
if (status & RXSTAT_CRCERROR) stats->rx_crc_errors ++;
@@ -685,14 +675,14 @@ if (next_ptr < RX_START || next_ptr >= RX_END) {
while (-- maxcnt);
done:
- priv(dev)->stats.rx_packets += received;
+ dev->stats.rx_packets += received;
priv(dev)->rx_head = next_ptr;
/*
* If rx went off line, then that means that the buffer may be full. We
* have dropped at least one packet.
*/
if (!(ether3_inw(REG_STATUS) & STAT_RXON)) {
- priv(dev)->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
ether3_outw(next_ptr, REG_RECVPTR);
ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND);
}
@@ -710,7 +700,7 @@ dropping:{
last_warned = jiffies;
printk("%s: memory squeeze, dropping packet.\n", dev->name);
}
- priv(dev)->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
goto done;
}
}
@@ -743,13 +733,13 @@ static void ether3_tx(struct net_device *dev)
* Update errors
*/
if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS)))
- priv(dev)->stats.tx_packets++;
+ dev->stats.tx_packets++;
else {
- priv(dev)->stats.tx_errors ++;
+ dev->stats.tx_errors++;
if (status & TXSTAT_16COLLISIONS)
- priv(dev)->stats.collisions += 16;
+ dev->stats.collisions += 16;
if (status & TXSTAT_BABBLED)
- priv(dev)->stats.tx_fifo_errors ++;
+ dev->stats.tx_fifo_errors++;
}
tx_tail = (tx_tail + 1) & 15;
@@ -773,7 +763,6 @@ static const struct net_device_ops ether3_netdev_ops = {
.ndo_open = ether3_open,
.ndo_stop = ether3_close,
.ndo_start_xmit = ether3_sendpacket,
- .ndo_get_stats = ether3_getstats,
.ndo_set_multicast_list = ether3_setmulticastlist,
.ndo_tx_timeout = ether3_timeout,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/arm/ether3.h b/drivers/net/arm/ether3.h
index 1921a3a..2db63b0 100644
--- a/drivers/net/arm/ether3.h
+++ b/drivers/net/arm/ether3.h
@@ -164,7 +164,6 @@ struct dev_priv {
unsigned char tx_head; /* buffer nr to insert next packet */
unsigned char tx_tail; /* buffer nr of transmitting packet */
unsigned int rx_head; /* address to fetch next packet from */
- struct net_device_stats stats;
struct timer_list timer;
int broken; /* 0 = ok, 1 = something went wrong */
};
--
1.7.0.4
^ permalink raw reply related
* [PATCH v3] ether1: Use net_device_stats from struct net_device
From: Tobias Klauser @ 2010-08-18 8:45 UTC (permalink / raw)
To: David S. Miller, Russell King, netdev
Cc: linux-arm-kernel, kernel-janitors, Eric Dumazet, Dan Carpenter
In-Reply-To: <1282061719-19645-1-git-send-email-tklauser@distanz.ch>
struct net_device has its own struct net_device_stats member, so use
this one instead of a private copy in the ether1_priv struct. As the new
ndo_get_stats function would just return dev->stats we can omit it.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---
drivers/net/arm/ether1.c | 34 +++++++++++++---------------------
drivers/net/arm/ether1.h | 1 -
2 files changed, 13 insertions(+), 22 deletions(-)
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
index b17ab51..ad90447 100644
--- a/drivers/net/arm/ether1.c
+++ b/drivers/net/arm/ether1.c
@@ -68,7 +68,6 @@ static int ether1_open(struct net_device *dev);
static int ether1_sendpacket(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t ether1_interrupt(int irq, void *dev_id);
static int ether1_close(struct net_device *dev);
-static struct net_device_stats *ether1_getstats(struct net_device *dev);
static void ether1_setmulticastlist(struct net_device *dev);
static void ether1_timeout(struct net_device *dev);
@@ -649,7 +648,7 @@ ether1_open (struct net_device *dev)
if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
return -EAGAIN;
- memset (&priv(dev)->stats, 0, sizeof (struct net_device_stats));
+ memset(&dev->stats, 0, sizeof(struct net_device_stats));
if (ether1_init_for_open (dev)) {
free_irq (dev->irq, dev);
@@ -673,7 +672,7 @@ ether1_timeout(struct net_device *dev)
if (ether1_init_for_open (dev))
printk (KERN_ERR "%s: unable to restart interface\n", dev->name);
- priv(dev)->stats.tx_errors++;
+ dev->stats.tx_errors++;
netif_wake_queue(dev);
}
@@ -802,21 +801,21 @@ again:
while (nop.nop_status & STAT_COMPLETE) {
if (nop.nop_status & STAT_OK) {
- priv(dev)->stats.tx_packets ++;
- priv(dev)->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
+ dev->stats.tx_packets++;
+ dev->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
} else {
- priv(dev)->stats.tx_errors ++;
+ dev->stats.tx_errors++;
if (nop.nop_status & STAT_COLLAFTERTX)
- priv(dev)->stats.collisions ++;
+ dev->stats.collisions++;
if (nop.nop_status & STAT_NOCARRIER)
- priv(dev)->stats.tx_carrier_errors ++;
+ dev->stats.tx_carrier_errors++;
if (nop.nop_status & STAT_TXLOSTCTS)
printk (KERN_WARNING "%s: cts lost\n", dev->name);
if (nop.nop_status & STAT_TXSLOWDMA)
- priv(dev)->stats.tx_fifo_errors ++;
+ dev->stats.tx_fifo_errors++;
if (nop.nop_status & STAT_COLLEXCESSIVE)
- priv(dev)->stats.collisions += 16;
+ dev->stats.collisions += 16;
}
if (nop.nop_link == caddr) {
@@ -879,13 +878,13 @@ ether1_recv_done (struct net_device *dev)
skb->protocol = eth_type_trans (skb, dev);
netif_rx (skb);
- priv(dev)->stats.rx_packets ++;
+ dev->stats.rx_packets++;
} else
- priv(dev)->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
} else {
printk(KERN_WARNING "%s: %s\n", dev->name,
(rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid");
- priv(dev)->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
}
nexttail = ether1_readw(dev, priv(dev)->rx_tail, rfd_t, rfd_link, NORMALIRQS);
@@ -939,7 +938,7 @@ ether1_interrupt (int irq, void *dev_id)
printk (KERN_WARNING "%s: RU went not ready: RU suspended\n", dev->name);
ether1_writew(dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
writeb(CTRL_CA, REG_CONTROL);
- priv(dev)->stats.rx_dropped ++; /* we suspended due to lack of buffer space */
+ dev->stats.rx_dropped++; /* we suspended due to lack of buffer space */
} else
printk(KERN_WARNING "%s: RU went not ready: %04X\n", dev->name,
ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS));
@@ -962,12 +961,6 @@ ether1_close (struct net_device *dev)
return 0;
}
-static struct net_device_stats *
-ether1_getstats (struct net_device *dev)
-{
- return &priv(dev)->stats;
-}
-
/*
* Set or clear the multicast filter for this adaptor.
* num_addrs == -1 Promiscuous mode, receive all packets.
@@ -994,7 +987,6 @@ static const struct net_device_ops ether1_netdev_ops = {
.ndo_open = ether1_open,
.ndo_stop = ether1_close,
.ndo_start_xmit = ether1_sendpacket,
- .ndo_get_stats = ether1_getstats,
.ndo_set_multicast_list = ether1_setmulticastlist,
.ndo_tx_timeout = ether1_timeout,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/arm/ether1.h b/drivers/net/arm/ether1.h
index c8a4b23..3a5830a 100644
--- a/drivers/net/arm/ether1.h
+++ b/drivers/net/arm/ether1.h
@@ -38,7 +38,6 @@
struct ether1_priv {
void __iomem *base;
- struct net_device_stats stats;
unsigned int tx_link;
unsigned int tx_head;
volatile unsigned int tx_tail;
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH v2] ether1: Use net_device_stats from struct net_device
From: Tobias Klauser @ 2010-08-18 8:33 UTC (permalink / raw)
To: Eric Dumazet
Cc: Russell King - ARM Linux, David S. Miller, netdev,
linux-arm-kernel, kernel-janitors, Dan Carpenter
In-Reply-To: <1282120073.2194.40.camel@edumazet-laptop>
On 2010-08-18 at 10:27:53 +0200, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> Le mercredi 18 août 2010 à 09:13 +0100, Russell King - ARM Linux a
> écrit :
> > On Wed, Aug 18, 2010 at 09:04:24AM +0200, Tobias Klauser wrote:
> > > @@ -965,7 +965,7 @@ ether1_close (struct net_device *dev)
> > > static struct net_device_stats *
> > > ether1_getstats (struct net_device *dev)
> > > {
> > > - return &priv(dev)->stats;
> > > + return &dev->stats;
> > > }
> >
> > Doesn't the core do this for you already if you omit this function?
> >
> > Same comment for ether3.c
>
> Yes, thats right, no need to declare ndo_get_stats() methods that only
> returns &dev->stats
Thanks. I'll send another updated patch, omitting the ether1_getstats
(same for ether3). Sorry for the mess.
^ permalink raw reply
* Re: [PATCH v2] ether1: Use net_device_stats from struct net_device
From: Eric Dumazet @ 2010-08-18 8:27 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: Tobias Klauser, David S. Miller, netdev, linux-arm-kernel,
kernel-janitors, Dan Carpenter
In-Reply-To: <20100818081306.GA9149@n2100.arm.linux.org.uk>
Le mercredi 18 août 2010 à 09:13 +0100, Russell King - ARM Linux a
écrit :
> On Wed, Aug 18, 2010 at 09:04:24AM +0200, Tobias Klauser wrote:
> > @@ -965,7 +965,7 @@ ether1_close (struct net_device *dev)
> > static struct net_device_stats *
> > ether1_getstats (struct net_device *dev)
> > {
> > - return &priv(dev)->stats;
> > + return &dev->stats;
> > }
>
> Doesn't the core do this for you already if you omit this function?
>
> Same comment for ether3.c
Yes, thats right, no need to declare ndo_get_stats() methods that only
returns &dev->stats
^ permalink raw reply
* Re: [PATCH v3] PPTP: PPP over IPv4 (Point-to-Point Tunneling Protocol)
From: Eric Dumazet @ 2010-08-18 8:25 UTC (permalink / raw)
To: Dmitry Kozlov; +Cc: netdev
In-Reply-To: <E1Olbcq-0006hZ-00.xeb-mail-ru@f272.mail.ru>
Le mercredi 18 août 2010 à 09:55 +0400, Dmitry Kozlov a écrit :
> This patch contains:
> 1. pptp driver
> 2. gre demultiplexer driver for demultiplexing gre packets with different gre version so
> ip_gre and pptp may coexists
> 3. ip_gre modification
> 4. other stuff
>
> --
Hi Dmitry
I added some comments in your patch.
Plus, could you please run scripts/checkpatch.pl on it to correct some
style issues ?
> MAINTAINERS | 14 +
> drivers/net/Kconfig | 11 +
> drivers/net/Makefile | 1 +
> drivers/net/pptp.c | 747 ++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/if_pppox.h | 20 ++-
> include/net/gre.h | 18 ++
> net/ipv4/Kconfig | 7 +
> net/ipv4/Makefile | 1 +
> net/ipv4/gre.c | 147 +++++++++
> net/ipv4/ip_gre.c | 10 +-
> 10 files changed, 970 insertions(+), 6 deletions(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 02f75fc..191d7c4 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6450,6 +6450,20 @@ M: "Maciej W. Rozycki" <macro@linux-mips.org>
> S: Maintained
> F: drivers/serial/zs.*
>
> +GRE DEMULTIPLEXER DRIVER
> +M: Dmitry Kozlov <D.Kozlov@protek-vrn.ru>
> +L: netdev@vger.kernel.org
> +S: Maintained
> +F: net/ipv4/gre.c
> +F: include/net/gre.h
> +
> +PPTP DRIVER
> +M: Dmitry Kozlov <D.Kozlov@protek-vrn.ru>
> +L: netdev@vger.kernel.org
> +S: Maintained
> +F: drivers/net/pptp.c
> +W: http://sourceforge.net/projects/accel-pptp
> +
> THE REST
> M: Linus Torvalds <torvalds@linux-foundation.org>
> L: linux-kernel@vger.kernel.org
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index ce2fcdd..2fa0516 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -3167,6 +3167,17 @@ config PPPOE
> which contains instruction on how to use this driver (under
> the heading "Kernel mode PPPoE").
>
> +config PPTP
> + tristate "PPP over IPv4 (PPTP) (EXPERIMENTAL)"
> + depends on EXPERIMENTAL && PPP && NET_IPGRE_DEMUX
> + help
> + Support for PPP over IPv4.(Point-to-Point Tunneling Protocol)
> +
> + This driver requires pppd plugin to work in client mode or
> + modified pptpd (poptop) to work in server mode.
> + See http://accel-pptp.sourceforge.net/ for information how to
> + utilize this module.
> +
> config PPPOATM
> tristate "PPP over ATM"
> depends on ATM && PPP
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 0a0512a..b33fef1 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -162,6 +162,7 @@ obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
> obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
> obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
> obj-$(CONFIG_PPPOL2TP) += pppox.o
> +obj-$(CONFIG_PPTP) += pppox.o pptp.o
>
> obj-$(CONFIG_SLIP) += slip.o
> obj-$(CONFIG_SLHC) += slhc.o
> diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c
> new file mode 100644
> index 0000000..5dad2f0
> --- /dev/null
> +++ b/drivers/net/pptp.c
> @@ -0,0 +1,747 @@
> +/*
> + * Point-to-Point Tunneling Protocol for Linux
> + *
> + * Authors: Dmitry Kozlov <xeb@mail.ru>
> + *
> + * 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.
> + *
> + */
> +
> +#include <linux/string.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/errno.h>
> +#include <linux/netdevice.h>
> +#include <linux/net.h>
> +#include <linux/skbuff.h>
> +#include <linux/init.h>
> +#include <linux/ppp_channel.h>
> +#include <linux/ppp_defs.h>
> +#include <linux/if_pppox.h>
> +#include <linux/if_ppp.h>
> +#include <linux/notifier.h>
> +#include <linux/file.h>
> +#include <linux/in.h>
> +#include <linux/ip.h>
> +#include <linux/netfilter.h>
> +#include <linux/netfilter_ipv4.h>
> +#include <linux/version.h>
> +//#include <linux/spinlock.h>
just delete this line
> +#include <linux/rcupdate.h>
> +#include <linux/semaphore.h>
> +
> +
> +#include <net/sock.h>
> +#include <net/protocol.h>
> +#include <net/ip.h>
> +#include <net/icmp.h>
> +#include <net/route.h>
> +#include <net/gre.h>
> +
> +#include <asm/uaccess.h>
> +
> +#define PPTP_DRIVER_VERSION "0.8.4"
> +
> +#define MAX_CALLID 65535
> +#define PPP_LCP_ECHOREQ 0x09
> +#define PPP_LCP_ECHOREP 0x0A
> +#define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
> +
> +static unsigned long *callid_bitmap = NULL;
Check DECLARE_BITMAP(). I think it is ok in 2010 to add 8192 bytes of
bss in a module, considering typical kernels already use 10 Mbytes of
bss.
> +static struct pppox_sock **callid_sock=NULL;
No need for the "=NULL"
> +
> +
> +static DECLARE_MUTEX(chan_lock);
Hmm... semaphores are deprecated, please use a mutex
static DEFINE_MUTEX(chan_lock);
(check drivers/net/ppp_generic.c for example)
> +
> +static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb);
> +static int pptp_ppp_ioctl(struct ppp_channel *chan, unsigned int cmd,
> + unsigned long arg);
> +static int pptp_rcv_core(struct sock *sk,struct sk_buff *skb);
> +
> +static struct ppp_channel_ops pptp_chan_ops = {
static const ?
> + .start_xmit = pptp_xmit,
> + .ioctl = pptp_ppp_ioctl,
> +};
> +
> +
> +#define MISSING_WINDOW 20
> +#define WRAPPED( curseq, lastseq) \
> + ((((curseq) & 0xffffff00) == 0) && \
> + (((lastseq) & 0xffffff00 ) == 0xffffff00))
> +
> +/* gre header structure: -------------------------------------------- */
> +
> +#define PPTP_GRE_PROTO 0x880B
> +#define PPTP_GRE_VER 0x1
> +
> +#define PPTP_GRE_FLAG_C 0x80
> +#define PPTP_GRE_FLAG_R 0x40
> +#define PPTP_GRE_FLAG_K 0x20
> +#define PPTP_GRE_FLAG_S 0x10
> +#define PPTP_GRE_FLAG_A 0x80
> +
> +#define PPTP_GRE_IS_C(f) ((f)&PPTP_GRE_FLAG_C)
> +#define PPTP_GRE_IS_R(f) ((f)&PPTP_GRE_FLAG_R)
> +#define PPTP_GRE_IS_K(f) ((f)&PPTP_GRE_FLAG_K)
> +#define PPTP_GRE_IS_S(f) ((f)&PPTP_GRE_FLAG_S)
> +#define PPTP_GRE_IS_A(f) ((f)&PPTP_GRE_FLAG_A)
> +
> +#define PPTP_HEADER_OVERHEAD (2+sizeof(struct pptp_gre_header))
> +struct pptp_gre_header {
> + u8 flags; /* bitfield */
> + u8 ver; /* should be PPTP_GRE_VER (enhanced GRE) */
> + u16 protocol; /* should be PPTP_GRE_PROTO (ppp-encaps) */
> + u16 payload_len; /* size of ppp payload, not inc. gre header */
> + u16 call_id; /* peer's call_id for this session */
> + u32 seq; /* sequence number. Present if S==1 */
> + u32 ack; /* seq number of highest packet recieved by */
> + /* sender in this session */
> +};
> +
> +static struct pppox_sock * lookup_chan(__u16 call_id, __be32 s_addr)
> +{
> + struct pppox_sock *sock;
> + struct pptp_opt *opt;
> +
> + rcu_read_lock();
> + sock = rcu_dereference(callid_sock[call_id]);
> + if (sock) {
> + opt = &sock->proto.pptp;
> + if (opt->dst_addr.sin_addr.s_addr != s_addr) sock = NULL;
> + else sock_hold(sk_pppox(sock));
> + }
> + rcu_read_unlock();
> +
> + return sock;
> +}
> +
> +static int lookup_chan_dst(__u16 call_id, __be32 d_addr)
> +{
> + struct pppox_sock *sock;
> + struct pptp_opt *opt;
> + int i;
> +
> + down(&chan_lock);
mutex_lock(&chan_lock) ?
> + for(i = find_next_bit(callid_bitmap,MAX_CALLID,1); i < MAX_CALLID; i = find_next_bit(callid_bitmap,MAX_CALLID,i+1)) {
> + sock = callid_sock[i];
> + opt = &sock->proto.pptp;
> + if (opt->dst_addr.call_id == call_id && opt->dst_addr.sin_addr.s_addr == d_addr) break;
> + }
> + up(&chan_lock);
mutex_unlock()
> +
> + return i < MAX_CALLID;
> +}
> +
> +static int add_chan(struct pppox_sock *sock)
> +{
> + static int call_id = 0;
> + int res = -1;
> +
> + synchronize_rcu();
> +
Why is this synchronize_rcu() necessary ?
> + down(&chan_lock);
> + if (!sock->proto.pptp.src_addr.call_id) {
> + call_id = find_next_zero_bit(callid_bitmap,MAX_CALLID,call_id+1);
> + if (call_id == MAX_CALLID)
> + call_id = find_next_zero_bit(callid_bitmap,MAX_CALLID,1);
> + sock->proto.pptp.src_addr.call_id = call_id;
> + } else if (test_bit(sock->proto.pptp.src_addr.call_id,callid_bitmap))
> + goto exit;
> +
> + set_bit(sock->proto.pptp.src_addr.call_id,callid_bitmap);
> + rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id],sock);
> + res = 0;
> +
> +exit:
> + up(&chan_lock);
> +
> + return res;
> +}
> +
> +static void del_chan(struct pppox_sock *sock)
> +{
> + synchronize_rcu();
Are you sure it is at the right place ?
> +
> + down(&chan_lock);
> + clear_bit(sock->proto.pptp.src_addr.call_id,callid_bitmap);
> + rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id],NULL);
> + up(&chan_lock);
> +}
> +
> +static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
> +{
> + struct sock *sk = (struct sock *) chan->private;
> + struct pppox_sock *po = pppox_sk(sk);
> + struct pptp_opt *opt = &po->proto.pptp;
> + struct pptp_gre_header *hdr;
> + unsigned int header_len = sizeof(*hdr);
> + int err = 0;
> + int islcp;
> + int len;
> + unsigned char *data;
> + __u32 seq_recv;
> +
> +
> + struct rtable *rt; /* Route to the other host */
> + struct net_device *tdev; /* Device to other host */
> + struct iphdr *iph; /* Our new IP header */
> + int max_headroom; /* The extra header space needed */
> +
> + if (sk_pppox(po)->sk_state & PPPOX_DEAD)
> + goto tx_error;
> +
> + {
> + struct flowi fl = { .oif = 0,
> + .nl_u = { .ip4_u =
> + { .daddr = opt->dst_addr.sin_addr.s_addr,
> + .saddr = opt->src_addr.sin_addr.s_addr,
> + .tos = RT_TOS(0) } },
> + .proto = IPPROTO_GRE };
> + if ((err=ip_route_output_key(&init_net,&rt, &fl))) {
> + goto tx_error;
> + }
> + }
> + tdev = rt->u.dst.dev;
> +
> + max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(*iph)+sizeof(*hdr)+2;
> +
> + if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
> + struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
> + if (!new_skb) {
> + ip_rt_put(rt);
> + goto tx_error;
> + }
> + if (skb->sk)
> + skb_set_owner_w(new_skb, skb->sk);
> + kfree_skb(skb);
> + skb = new_skb;
> + }
> +
> + data = skb->data;
> + islcp = ((data[0] << 8) + data[1])== PPP_LCP && 1 <= data[2] && data[2] <= 7;
> +
> + /* compress protocol field */
> + if ((opt->ppp_flags & SC_COMP_PROT) && data[0] == 0 && !islcp)
> + skb_pull(skb,1);
> +
> + /*
> + * Put in the address/control bytes if necessary
> + */
bad indent ?
Also, dont use 3 lines for small comments :
/* Put in the address/control bytes if necessary */
> + if ((opt->ppp_flags & SC_COMP_AC) == 0 || islcp) {
> + data = skb_push(skb,2);
> + data[0] = PPP_ALLSTATIONS;
> + data[1] = PPP_UI;
> + }
> +
> + len = skb->len;
> +
> + seq_recv = opt->seq_recv;
> +
> + if (opt->ack_sent == seq_recv) header_len -= sizeof(hdr->ack);
> +
> + // Push down and install GRE header
> + skb_push(skb,header_len);
> + hdr = (struct pptp_gre_header *)(skb->data);
> +
> + hdr->flags = PPTP_GRE_FLAG_K;
> + hdr->ver = PPTP_GRE_VER;
> + hdr->protocol = htons(PPTP_GRE_PROTO);
> + hdr->call_id = htons(opt->dst_addr.call_id);
> +
> + hdr->flags |= PPTP_GRE_FLAG_S;
> + hdr->seq = htonl(++opt->seq_sent);
> + if (opt->ack_sent != seq_recv) {
> + /* send ack with this message */
> + hdr->ver |= PPTP_GRE_FLAG_A;
> + hdr->ack = htonl(seq_recv);
> + opt->ack_sent = seq_recv;
> + }
> + hdr->payload_len = htons(len);
> +
> + /*
> + * Push down and install the IP header.
> + */
ditto , one line is ok
> +
> + skb_reset_transport_header(skb);
> + skb_push(skb, sizeof(*iph));
> + skb_reset_network_header(skb);
> + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
> + IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
> +
> + iph = ip_hdr(skb);
> + iph->version = 4;
> + iph->ihl = sizeof(struct iphdr) >> 2;
> + if (ip_dont_fragment(sk, &rt->u.dst))
> + iph->frag_off = htons(IP_DF);
> + else
> + iph->frag_off = 0;
> + iph->protocol = IPPROTO_GRE;
> + iph->tos = 0;
> + iph->daddr = rt->rt_dst;
> + iph->saddr = rt->rt_src;
> + iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT);
> + iph->tot_len = htons(skb->len);
> +
> + skb_dst_drop(skb);
> + skb_dst_set(skb,&rt->u.dst);
> +
> + nf_reset(skb);
> +
> + skb->ip_summed = CHECKSUM_NONE;
> + ip_select_ident(iph, &rt->u.dst, NULL);
> + ip_send_check(iph);
> +
> + ip_local_out(skb);
> +
> +tx_error:
> + return 1;
> +}
> +
> +static int pptp_rcv_core(struct sock *sk,struct sk_buff *skb)
> +{
> + struct pppox_sock *po = pppox_sk(sk);
> + struct pptp_opt *opt = &po->proto.pptp;
> + int headersize,payload_len,seq;
> + __u8 *payload;
> + struct pptp_gre_header *header;
> +
> + if (!(sk->sk_state & PPPOX_CONNECTED)) {
> + if (sock_queue_rcv_skb(sk, skb))
> + goto drop;
> + return NET_RX_SUCCESS;
> + }
> +
> + header = (struct pptp_gre_header *)(skb->data);
> +
> + /* test if acknowledgement present */
> + if (PPTP_GRE_IS_A(header->ver)) {
> + __u32 ack = (PPTP_GRE_IS_S(header->flags))?
> + header->ack:header->seq; /* ack in different place if S = 0 */
> +
> + ack = ntohl( ack);
> +
> + if (ack > opt->ack_recv) opt->ack_recv = ack;
> + /* also handle sequence number wrap-around */
> + if (WRAPPED(ack,opt->ack_recv)) opt->ack_recv = ack;
> + }
> +
> + /* test if payload present */
> + if (!PPTP_GRE_IS_S(header->flags)) {
> + goto drop;
> + }
> +
> + headersize = sizeof(*header);
> + payload_len = ntohs(header->payload_len);
> + seq = ntohl(header->seq);
> +
> + /* no ack present? */
> + if (!PPTP_GRE_IS_A(header->ver)) headersize -= sizeof(header->ack);
> + /* check for incomplete packet (length smaller than expected) */
> + if (skb->len - headersize < payload_len) {
> + goto drop;
> + }
> +
> + payload = skb->data+headersize;
> + /* check for expected sequence number */
> + if ( seq < opt->seq_recv + 1 || WRAPPED(opt->seq_recv, seq) ) {
> + if ( (payload[0] == PPP_ALLSTATIONS) && (payload[1] == PPP_UI) &&
> + (PPP_PROTOCOL(payload) == PPP_LCP) &&
> + ((payload[4] == PPP_LCP_ECHOREQ) || (payload[4] == PPP_LCP_ECHOREP)) ) {
> + goto allow_packet;
> + }
> + }else{
> + opt->seq_recv = seq;
> +allow_packet:
> + skb_pull(skb,headersize);
> +
> + if (payload[0] == PPP_ALLSTATIONS && payload[1] == PPP_UI) {
> + /* chop off address/control */
> + if (skb->len < 3)
> + goto drop;
> + skb_pull(skb,2);
> + }
> +
> + if ((*skb->data) & 1) {
> + /* protocol is compressed */
> + skb_push(skb, 1)[0] = 0;
> + }
> +
> + skb->ip_summed = CHECKSUM_NONE;
> + skb_set_network_header(skb,skb->head-skb->data);
> + ppp_input(&po->chan,skb);
> +
> + return NET_RX_SUCCESS;
> + }
> +drop:
> + kfree_skb(skb);
> + return NET_RX_DROP;
> +}
> +
> +static int pptp_rcv(struct sk_buff *skb)
> +{
> + struct pppox_sock *po;
> + struct pptp_gre_header *header;
> + struct iphdr *iph;
> +
> + if (skb->pkt_type != PACKET_HOST)
> + goto drop;
> +
> + if (!pskb_may_pull(skb, 12))
> + goto drop;
> +
> + iph = ip_hdr(skb);
> +
> + header = (struct pptp_gre_header *)skb->data;
> +
> + if ( /* version should be 1 */
> + ((header->ver & 0x7F) != PPTP_GRE_VER) ||
> + /* PPTP-GRE protocol for PPTP */
> + (ntohs(header->protocol) != PPTP_GRE_PROTO)||
> + /* flag C should be clear */
> + PPTP_GRE_IS_C(header->flags) ||
> + /* flag R should be clear */
> + PPTP_GRE_IS_R(header->flags) ||
> + /* flag K should be set */
> + (!PPTP_GRE_IS_K(header->flags)) ||
> + /* routing and recursion ctrl = 0 */
> + ((header->flags&0xF) != 0)) {
> + /* if invalid, discard this packet */
> + goto drop;
> + }
> +
> +
> + if ((po=lookup_chan(htons(header->call_id),iph->saddr))) {
> + skb_dst_drop(skb);
> + skb_dst_set(skb,NULL);
> + nf_reset(skb);
> + return sk_receive_skb(sk_pppox(po), skb, 0);
> + }
> +drop:
> + kfree_skb(skb);
> + return NET_RX_DROP;
> +}
> +
> +static int pptp_bind(struct socket *sock,struct sockaddr *uservaddr,int sockaddr_len)
> +{
> + struct sock *sk = sock->sk;
> + struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
> + struct pppox_sock *po = pppox_sk(sk);
> + struct pptp_opt *opt = &po->proto.pptp;
> + int error = 0;
> +
> + lock_sock(sk);
> +
> + opt->src_addr = sp->sa_addr.pptp;
> + if (add_chan(po)) {
> + release_sock(sk);
> + error = -EBUSY;
> + }
> +
> + release_sock(sk);
> + return error;
> +}
> +
> +static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
> + int sockaddr_len, int flags)
> +{
> + struct sock *sk = sock->sk;
> + struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
> + struct pppox_sock *po = pppox_sk(sk);
> + struct pptp_opt *opt = &po->proto.pptp;
> + struct rtable *rt; /* Route to the other host */
> + int error=0;
> +
> + if (sp->sa_protocol != PX_PROTO_PPTP)
> + return -EINVAL;
> +
> + if (lookup_chan_dst(sp->sa_addr.pptp.call_id,sp->sa_addr.pptp.sin_addr.s_addr))
> + return -EALREADY;
> +
> + lock_sock(sk);
> + /* Check for already bound sockets */
> + if (sk->sk_state & PPPOX_CONNECTED) {
> + error = -EBUSY;
> + goto end;
> + }
> +
> + /* Check for already disconnected sockets, on attempts to disconnect */
> + if (sk->sk_state & PPPOX_DEAD) {
> + error = -EALREADY;
> + goto end;
> + }
> +
> + if (!opt->src_addr.sin_addr.s_addr || !sp->sa_addr.pptp.sin_addr.s_addr) {
> + error = -EINVAL;
> + goto end;
> + }
> +
> + po->chan.private = sk;
> + po->chan.ops = &pptp_chan_ops;
> +
> + {
> + struct flowi fl = {
> + .nl_u = { .ip4_u =
> + { .daddr = opt->dst_addr.sin_addr.s_addr,
> + .saddr = opt->src_addr.sin_addr.s_addr,
> + .tos = RT_CONN_FLAGS(sk) } },
> + .proto = IPPROTO_GRE };
> + security_sk_classify_flow(sk, &fl);
> + if (ip_route_output_key(&init_net, &rt, &fl)) {
> + error = -EHOSTUNREACH;
> + goto end;
> + }
> + sk_setup_caps(sk, &rt->u.dst);
> + }
> + po->chan.mtu = dst_mtu(&rt->u.dst);
> + if (!po->chan.mtu) po->chan.mtu = PPP_MTU;
> + ip_rt_put(rt);
> + po->chan.mtu -= PPTP_HEADER_OVERHEAD;
> +
> + po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header);
> + error = ppp_register_channel(&po->chan);
> + if (error) {
> + printk(KERN_ERR "PPTP: failed to register PPP channel (%d)\n",error);
> + goto end;
> + }
> +
> + opt->dst_addr = sp->sa_addr.pptp;
> + sk->sk_state = PPPOX_CONNECTED;
> +
> + end:
> + release_sock(sk);
> + return error;
> +}
> +
> +static int pptp_getname(struct socket *sock, struct sockaddr *uaddr,
> + int *usockaddr_len, int peer)
> +{
> + int len = sizeof(struct sockaddr_pppox);
> + struct sockaddr_pppox sp;
> +
> + sp.sa_family = AF_PPPOX;
> + sp.sa_protocol = PX_PROTO_PPTP;
> + sp.sa_addr.pptp = pppox_sk(sock->sk)->proto.pptp.src_addr;
> +
> + memcpy(uaddr, &sp, len);
> +
> + *usockaddr_len = len;
> +
> + return 0;
> +}
> +
> +static int pptp_release(struct socket *sock)
> +{
> + struct sock *sk = sock->sk;
> + struct pppox_sock *po;
> + struct pptp_opt *opt;
> + int error = 0;
> +
> + if (!sk)
> + return 0;
> +
> + lock_sock(sk);
> +
> + if (sock_flag(sk, SOCK_DEAD)) {
> + release_sock(sk);
> + return -EBADF;
> + }
> +
> + po = pppox_sk(sk);
> + opt = &po->proto.pptp;
> + del_chan(po);
> +
> + pppox_unbind_sock(sk);
> + sk->sk_state = PPPOX_DEAD;
> +
> + sock_orphan(sk);
> + sock->sk = NULL;
> +
> + release_sock(sk);
> + sock_put(sk);
> +
> + return error;
> +}
> +
> +
> +static struct proto pptp_sk_proto = {
static struct proto pptp_sk_proto __read_mostly = {
> + .name = "PPTP",
> + .owner = THIS_MODULE,
> + .obj_size = sizeof(struct pppox_sock),
> +};
> +
> +static struct proto_ops pptp_ops = {
static const
> + .family = AF_PPPOX,
> + .owner = THIS_MODULE,
> + .release = pptp_release,
> + .bind = pptp_bind,
> + .connect = pptp_connect,
> + .socketpair = sock_no_socketpair,
> + .accept = sock_no_accept,
> + .getname = pptp_getname,
> + .poll = sock_no_poll,
> + .listen = sock_no_listen,
> + .shutdown = sock_no_shutdown,
> + .setsockopt = sock_no_setsockopt,
> + .getsockopt = sock_no_getsockopt,
> + .sendmsg = sock_no_sendmsg,
> + .recvmsg = sock_no_recvmsg,
> + .mmap = sock_no_mmap,
> + .ioctl = pppox_ioctl,
> +};
> +
> +static void pptp_sock_destruct(struct sock *sk)
> +{
> + if (!(sk->sk_state & PPPOX_DEAD)) {
> + del_chan(pppox_sk(sk));
> + pppox_unbind_sock(sk);
> + }
> + skb_queue_purge(&sk->sk_receive_queue);
> +}
> +static int pptp_create(struct net *net, struct socket *sock)
> +{
> + int error = -ENOMEM;
> + struct sock *sk;
> + struct pppox_sock *po;
> + struct pptp_opt *opt;
> +
> + sk = sk_alloc(net,PF_PPPOX, GFP_KERNEL, &pptp_sk_proto);
> + if (!sk)
> + goto out;
> +
> + sock_init_data(sock, sk);
> +
> + sock->state = SS_UNCONNECTED;
> + sock->ops = &pptp_ops;
> +
> + sk->sk_backlog_rcv = pptp_rcv_core;
> + sk->sk_state = PPPOX_NONE;
> + sk->sk_type = SOCK_STREAM;
> + sk->sk_family = PF_PPPOX;
> + sk->sk_protocol = PX_PROTO_PPTP;
> + sk->sk_destruct = pptp_sock_destruct;
> +
> + po = pppox_sk(sk);
> + opt = &po->proto.pptp;
> +
> + opt->seq_sent = 0; opt->seq_recv = 0;
> + opt->ack_recv = 0; opt->ack_sent = 0;
> +
> + error = 0;
> +out:
> + return error;
> +}
> +
> +static int pptp_ppp_ioctl(struct ppp_channel *chan, unsigned int cmd,
> + unsigned long arg)
> +{
> + struct sock *sk = (struct sock *) chan->private;
> + struct pppox_sock *po = pppox_sk(sk);
> + struct pptp_opt *opt = &po->proto.pptp;
> + void __user *argp = (void __user *)arg;
> + int __user *p = argp;
> + int err, val;
> +
> + err = -EFAULT;
> + switch (cmd) {
> + case PPPIOCGFLAGS:
> + val = opt->ppp_flags;
> + if (put_user(val, p))
> + break;
> + err = 0;
> + break;
> + case PPPIOCSFLAGS:
> + if (get_user(val, p))
> + break;
> + opt->ppp_flags = val & ~SC_RCV_BITS;
> + err = 0;
> + break;
> + default:
> + err = -ENOTTY;
> + }
> +
> + return err;
> +}
> +
> +
> +static struct pppox_proto pppox_pptp_proto = {
> + .create = pptp_create,
> + .owner = THIS_MODULE,
> +};
> +
> +
> +static struct gre_protocol gre_pptp_protocol = {
> + .handler = pptp_rcv,
> + //.err_handler = pptp_err,
If you really want to use a comment, please use /* */ delimitors
> +};
> +
> +static int __init pptp_init_module(void)
> +{
> + int err=0;
> + printk(KERN_INFO "PPTP driver version " PPTP_DRIVER_VERSION "\n");
> +
> + if (gre_add_protocol(&gre_pptp_protocol, GREPROTO_PPTP) < 0) {
> + printk(KERN_INFO "PPTP: can't add protocol\n");
> + goto out;
> + }
> +
> + err = proto_register(&pptp_sk_proto, 0);
> + if (err) {
> + printk(KERN_INFO "PPTP: can't register sk_proto\n");
> + goto out_inet_del_protocol;
> + }
> +
> + err = register_pppox_proto(PX_PROTO_PPTP, &pppox_pptp_proto);
> + if (err) {
> + printk(KERN_INFO "PPTP: can't register pppox_proto\n");
> + goto out_unregister_sk_proto;
> + }
> +
> +
> + //assuming PAGESIZE is 4096 bytes
Dont assume things like that ;)
> + callid_bitmap = (unsigned long*)__get_free_pages(GFP_KERNEL,1);
> + memset(callid_bitmap,0,PAGE_SIZE << 1);
and prefer a kzalloc(65536/BITS_PER_BYTE, GFP_KERNEL) call here
> +
> +#if (BITS_PER_LONG == 32)
> + callid_sock = (struct pppox_sock **)__get_free_pages(GFP_KERNEL,6);
> + memset(callid_sock,0,PAGE_SIZE << 6);
ditto here, please use vmalloc(65536 * sizeof(void *)) to avoid
BITS_PER_LONG games
> +#elif (BITS_PER_LONG == 64)
> + callid_sock = (struct pppox_sock **)__get_free_pages(GFP_KERNEL,7);
> + memset(callid_sock,0,PAGE_SIZE << 7);
> +#else
> +#error unknown size of LONG
> +#endif
> +
> +out:
> + return err;
> +out_unregister_sk_proto:
> + proto_unregister(&pptp_sk_proto);
> +out_inet_del_protocol:
> + gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
> + return err;
> +}
> +
> +static void __exit pptp_exit_module(void)
> +{
> + unregister_pppox_proto(PX_PROTO_PPTP);
> + proto_unregister(&pptp_sk_proto);
> + gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
> + if (callid_bitmap) free_pages((unsigned long)callid_bitmap,1);
> + if (callid_sock)
> +#if (BITS_PER_LONG == 32)
> + free_pages((unsigned long)callid_sock,6);
> +#elif (BITS_PER_LONG == 64)
> + free_pages((unsigned long)callid_sock,7);
> +#endif
> +}
> +
> +module_init(pptp_init_module);
> +module_exit(pptp_exit_module);
> +
> +MODULE_DESCRIPTION("Point-to-Point Tunneling Protocol");
> +MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)");
> +MODULE_LICENSE("GPL");
> +
> diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
> index a6577af..455ff56 100644
> --- a/include/linux/if_pppox.h
> +++ b/include/linux/if_pppox.h
> @@ -47,17 +47,27 @@ struct pppoe_addr{
> };
>
> /************************************************************************
> + * PPTP addressing definition
> + */
> +struct pptp_addr{
struct pptp_addr {
> + __u16 call_id;
> + struct in_addr sin_addr;
> +};
> +
> +/************************************************************************
> * Protocols supported by AF_PPPOX
> */
> #define PX_PROTO_OE 0 /* Currently just PPPoE */
> #define PX_PROTO_OL2TP 1 /* Now L2TP also */
> -#define PX_MAX_PROTO 2
> +#define PX_PROTO_PPTP 2
> +#define PX_MAX_PROTO 3
>
> struct sockaddr_pppox {
> sa_family_t sa_family; /* address family, AF_PPPOX */
> unsigned int sa_protocol; /* protocol identifier */
> union{
> struct pppoe_addr pppoe;
> + struct pptp_addr pptp;
> }sa_addr;
> }__attribute__ ((packed));
>
> @@ -150,6 +160,13 @@ struct pppoe_opt {
> relayed to (PPPoE relaying) */
> };
>
> +struct pptp_opt {
> + struct pptp_addr src_addr;
> + struct pptp_addr dst_addr;
> + __u32 ack_sent, ack_recv;
> + __u32 seq_sent, seq_recv;
> + int ppp_flags;
> +};
> #include <net/sock.h>
>
> struct pppox_sock {
> @@ -159,6 +176,7 @@ struct pppox_sock {
> struct pppox_sock *next; /* for hash table */
> union {
> struct pppoe_opt pppoe;
> + struct pptp_opt pptp;
> } proto;
> __be16 num;
> };
> diff --git a/include/net/gre.h b/include/net/gre.h
> new file mode 100644
> index 0000000..31a0f76
> --- /dev/null
> +++ b/include/net/gre.h
> @@ -0,0 +1,18 @@
> +#ifndef __LINUX_GRE_H
> +#define __LINUX_GRE_H
> +
> +#include <linux/skbuff.h>
> +
> +#define GREPROTO_CISCO 0
> +#define GREPROTO_PPTP 1
> +#define GREPROTO_MAX 2
> +
> +struct gre_protocol {
> + int (*handler)(struct sk_buff *skb);
> + void (*err_handler)(struct sk_buff *skb, u32 info);
> +};
> +
> +int gre_add_protocol(const struct gre_protocol *proto, u8 version);
> +int gre_del_protocol(const struct gre_protocol *proto, u8 version);
> +
> +#endif
> diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
> index 7c3a7d1..7458bda 100644
> --- a/net/ipv4/Kconfig
> +++ b/net/ipv4/Kconfig
> @@ -215,8 +215,15 @@ config NET_IPIP
> be inserted in and removed from the running kernel whenever you
> want). Most people won't need this and can say N.
>
> +config NET_IPGRE_DEMUX
> + tristate "IP: GRE demultiplexer"
> + help
> + This is helper module to demultiplex GRE packets on GRE version field criteria.
> + Required by ip_gre and pptp modules.
> +
> config NET_IPGRE
> tristate "IP: GRE tunnels over IP"
> + depends on NET_IPGRE_DEMUX
> help
> Tunneling means encapsulating data of one protocol type within
> another protocol and sending it over a channel that understands the
> diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
> index 80ff87c..4978d22 100644
> --- a/net/ipv4/Makefile
> +++ b/net/ipv4/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_PROC_FS) += proc.o
> obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
> obj-$(CONFIG_IP_MROUTE) += ipmr.o
> obj-$(CONFIG_NET_IPIP) += ipip.o
> +obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o
> obj-$(CONFIG_NET_IPGRE) += ip_gre.o
> obj-$(CONFIG_SYN_COOKIES) += syncookies.o
> obj-$(CONFIG_INET_AH) += ah4.o
> diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c
> new file mode 100644
> index 0000000..f54a0fc
> --- /dev/null
> +++ b/net/ipv4/gre.c
> @@ -0,0 +1,147 @@
> +/*
> + * GRE over IPv4 demultiplexer driver
> + *
> + * Authors: Dmitry Kozlov (xeb@mail.ru)
> + *
> + * 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.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/kmod.h>
> +#include <linux/skbuff.h>
> +#include <linux/in.h>
> +#include <linux/netdevice.h>
> +#include <linux/version.h>
> +#include <linux/spinlock.h>
> +#include <net/protocol.h>
> +#include <net/gre.h>
> +
> +
> +const struct gre_protocol *gre_proto[GREPROTO_MAX] ____cacheline_aligned_in_smp;
No need for ____cacheline_aligned_in_smp here.
Better would be to user __read_mostly
> +static DEFINE_RWLOCK(gre_proto_lock);
This could use RCU and a spinlock instead
> +
> +int gre_add_protocol(const struct gre_protocol *proto, u8 version)
> +{
> + int ret;
> +
> + if (version >= GREPROTO_MAX)
> + return -1;
> +
> + write_lock_bh(&gre_proto_lock);
> + if (gre_proto[version]) {
> + ret = -1;
> + } else {
> + gre_proto[version]=proto;
> + ret = 0;
> + }
> + write_unlock_bh(&gre_proto_lock);
> +
> + return ret;
> +}
> +int gre_del_protocol(const struct gre_protocol *proto, u8 version)
> +{
> + int ret;
> +
> + if (version >= GREPROTO_MAX)
> + return -1;
> +
> + write_lock_bh(&gre_proto_lock);
> + if (gre_proto[version] == proto) {
> + gre_proto[version] = NULL;
> + ret = 0;
> + } else {
> + ret = -1;
> + }
> + write_unlock_bh(&gre_proto_lock);
> +
> + return ret;
> +}
> +static int gre_rcv(struct sk_buff *skb)
> +{
> + u8 ver;
> + int ret;
> +
> + if (!pskb_may_pull(skb, 12))
> + goto drop_nolock;
> +
> + ver = skb->data[1]&0x7f;
> + if (ver >= GREPROTO_MAX)
> + goto drop_nolock;
> +
> + read_lock(&gre_proto_lock);
> + if (!gre_proto[ver] || !gre_proto[ver]->handler)
> + goto drop;
> + ret = gre_proto[ver]->handler(skb);
> + read_unlock(&gre_proto_lock);
rcu locking, no need to touch gre_proto_lock
> + return ret;
> +
> +drop:
> + read_unlock(&gre_proto_lock);
> +drop_nolock:
> + kfree_skb(skb);
> + return NET_RX_DROP;
> +}
> +static void gre_err(struct sk_buff *skb, u32 info)
> +{
> + u8 ver;
> +
> + printk("err\n");
not very usefull string
> +
> + if (!pskb_may_pull(skb, 12))
> + goto drop_nolock;
> +
> + ver=skb->data[1];
> + if (ver>=GREPROTO_MAX)
> + goto drop_nolock;
> +
> + read_lock(&gre_proto_lock);
> + if (!gre_proto[ver] || !gre_proto[ver]->err_handler)
> + goto drop;
> + gre_proto[ver]->err_handler(skb,info);
> + read_unlock(&gre_proto_lock);
> + return;
> +
> +drop:
> + read_unlock(&gre_proto_lock);
> +drop_nolock:
> + kfree_skb(skb);
> +}
> +
> +
> +static struct net_protocol net_gre_protocol = {
const ?
> + .handler = gre_rcv,
> + .err_handler = gre_err,
> + .netns_ok=1,
missing spaces around =
> +};
> +
> +static int __init gre_init(void)
> +{
> + printk(KERN_INFO "GRE over IPv4 demultiplexor driver");
> +
> + if (inet_add_protocol(&net_gre_protocol, IPPROTO_GRE) < 0) {
> + printk(KERN_INFO "gre: can't add protocol\n");
> + return -EAGAIN;
> + }
> +
> + return 0;
> +}
> +
> +static void __exit gre_exit(void)
> +{
> + inet_del_protocol(&net_gre_protocol, IPPROTO_GRE);
> +}
> +
> +module_init(gre_init);
> +module_exit(gre_exit);
> +
> +MODULE_DESCRIPTION("GRE over IPv4 demultiplexer driver");
> +MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)");
> +MODULE_LICENSE("GPL");
> +EXPORT_SYMBOL_GPL(gre_add_protocol);
> +EXPORT_SYMBOL_GPL(gre_del_protocol);
> +
> diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
> index 32618e1..f0391b3 100644
> --- a/net/ipv4/ip_gre.c
> +++ b/net/ipv4/ip_gre.c
> @@ -44,6 +44,7 @@
> #include <net/net_namespace.h>
> #include <net/netns/generic.h>
> #include <net/rtnetlink.h>
> +#include <net/gre.h>
>
> #ifdef CONFIG_IPV6
> #include <net/ipv6.h>
> @@ -1276,10 +1277,9 @@ static void ipgre_fb_tunnel_init(struct net_device *dev)
> }
>
>
> -static const struct net_protocol ipgre_protocol = {
> +static const struct gre_protocol ipgre_protocol = {
> .handler = ipgre_rcv,
> .err_handler = ipgre_err,
> - .netns_ok = 1,
> };
>
> static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head)
> @@ -1661,7 +1661,7 @@ static int __init ipgre_init(void)
> if (err < 0)
> return err;
>
> - err = inet_add_protocol(&ipgre_protocol, IPPROTO_GRE);
> + err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
> if (err < 0) {
> printk(KERN_INFO "ipgre init: can't add protocol\n");
> goto add_proto_failed;
> @@ -1681,7 +1681,7 @@ out:
> tap_ops_failed:
> rtnl_link_unregister(&ipgre_link_ops);
> rtnl_link_failed:
> - inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
> + gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
> add_proto_failed:
> unregister_pernet_device(&ipgre_net_ops);
> goto out;
> @@ -1691,7 +1691,7 @@ static void __exit ipgre_fini(void)
> {
> rtnl_link_unregister(&ipgre_tap_ops);
> rtnl_link_unregister(&ipgre_link_ops);
> - if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
> + if (gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0)
> printk(KERN_INFO "ipgre close: can't remove protocol\n");
> unregister_pernet_device(&ipgre_net_ops);
> }
^ permalink raw reply
* Re: [PATCH v2] ether1: Use net_device_stats from struct net_device
From: Russell King - ARM Linux @ 2010-08-18 8:13 UTC (permalink / raw)
To: Tobias Klauser
Cc: David S. Miller, netdev, linux-arm-kernel, kernel-janitors,
Dan Carpenter
In-Reply-To: <1282115064-3701-1-git-send-email-tklauser@distanz.ch>
On Wed, Aug 18, 2010 at 09:04:24AM +0200, Tobias Klauser wrote:
> @@ -965,7 +965,7 @@ ether1_close (struct net_device *dev)
> static struct net_device_stats *
> ether1_getstats (struct net_device *dev)
> {
> - return &priv(dev)->stats;
> + return &dev->stats;
> }
Doesn't the core do this for you already if you omit this function?
Same comment for ether3.c
^ permalink raw reply
* [Patch 2/2] mlx4: remove num_lro parameter
From: Amerigo Wang @ 2010-08-18 7:51 UTC (permalink / raw)
To: netdev; +Cc: bhutchings, Ramkrishna.Vepa, sgruszka, Amerigo Wang, davem
In-Reply-To: <20100818075530.5926.67960.sendpatchset@localhost.localdomain>
As suggested by David, this parameter can die, we can use ethtool
to turn LRO on/off. Compile tests only.
Signed-off-by: WANG Cong <amwang@redhat.com>
---
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index b275238..398d541 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -398,8 +398,6 @@ static int mlx4_ethtool_op_set_flags(struct net_device *dev, u32 data)
return -EOPNOTSUPP;
if (data & ETH_FLAG_LRO) {
- if (mdev->profile.num_lro == 0)
- return -EOPNOTSUPP;
if (!(dev->features & NETIF_F_LRO))
changed = 1;
} else if (dev->features & NETIF_F_LRO) {
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 97934f1..cacac4e 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -69,10 +69,6 @@ MLX4_EN_PARM_INT(rss_xor, 0, "Use XOR hash function for RSS");
/* RSS hash type mask - default to <saddr, daddr, sport, dport> */
MLX4_EN_PARM_INT(rss_mask, 0xf, "RSS hash type bitmask");
-/* Number of LRO sessions per Rx ring (rounded up to a power of two) */
-MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS,
- "Number of LRO sessions per ring or disabled (0)");
-
/* Priority pausing */
MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]."
" Per priority bit mask");
@@ -109,7 +105,6 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
params->rss_xor = (rss_xor != 0);
params->rss_mask = rss_mask & 0x1f;
- params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS);
for (i = 1; i <= MLX4_MAX_PORTS; i++) {
params->prof[i].rx_pause = 1;
params->prof[i].rx_ppp = pfcrx;
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index a0d8a26..d00bfe2 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -1038,8 +1038,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
dev->features |= NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
- if (mdev->profile.num_lro)
- dev->features |= NETIF_F_LRO;
+ dev->features |= NETIF_F_LRO;
if (mdev->LSO_support) {
dev->features |= NETIF_F_TSO;
dev->features |= NETIF_F_TSO6;
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 8e2fcb7..ee5a2cc 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -320,9 +320,9 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
ring->lro.frag_align_pad = NET_IP_ALIGN;
ring->lro.ip_summed = CHECKSUM_UNNECESSARY;
ring->lro.ip_summed_aggr = CHECKSUM_UNNECESSARY;
- ring->lro.max_desc = mdev->profile.num_lro;
+ ring->lro.max_desc = MLX4_EN_MAX_LRO_DESCRIPTORS;
ring->lro.max_aggr = MAX_SKB_FRAGS;
- ring->lro.lro_arr = kzalloc(mdev->profile.num_lro *
+ ring->lro.lro_arr = kzalloc(MLX4_EN_MAX_LRO_DESCRIPTORS *
sizeof(struct net_lro_desc),
GFP_KERNEL);
if (!ring->lro.lro_arr) {
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 4492109..9d09323 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -313,7 +313,6 @@ struct mlx4_en_port_profile {
struct mlx4_en_profile {
int rss_xor;
- int num_lro;
u8 rss_mask;
u32 active_ports;
u32 small_pkt_int;
^ permalink raw reply related
* [Patch 1/2] s2io: remove lro parameter
From: Amerigo Wang @ 2010-08-18 7:51 UTC (permalink / raw)
To: netdev; +Cc: bhutchings, Ramkrishna.Vepa, sgruszka, Amerigo Wang, davem
As suggested by David, this parameter can die, we can use ethtool
to turn LRO on/off. Compile tests only.
Signed-off-by: WANG Cong <amwang@redhat.com>
---
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 18bc5b7..b981fa9 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -496,8 +496,6 @@ S2IO_PARM_INT(rxsync_frequency, 3);
/* Interrupt type. Values can be 0(INTA), 2(MSI_X) */
S2IO_PARM_INT(intr_type, 2);
/* Large receive offload feature */
-static unsigned int lro_enable = 1;
-module_param_named(lro, lro_enable, uint, 0);
/* Max pkts to be aggregated by LRO at one time. If not specified,
* aggregation happens until we hit max IP pkt size(64K)
@@ -6735,13 +6733,10 @@ static int s2io_ethtool_set_flags(struct net_device *dev, u32 data)
return -EINVAL;
if (data & ETH_FLAG_LRO) {
- if (lro_enable) {
- if (!(dev->features & NETIF_F_LRO)) {
- dev->features |= NETIF_F_LRO;
- changed = 1;
- }
- } else
- rc = -EINVAL;
+ if (!(dev->features & NETIF_F_LRO)) {
+ dev->features |= NETIF_F_LRO;
+ changed = 1;
+ }
} else if (dev->features & NETIF_F_LRO) {
dev->features &= ~NETIF_F_LRO;
changed = 1;
@@ -7911,7 +7906,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
else
sp->device_type = XFRAME_I_DEVICE;
- sp->lro = lro_enable;
+ sp->lro = 1;
/* Initialize some PCI/PCI-X fields of the NIC. */
s2io_init_pci(sp);
@@ -8047,8 +8042,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
dev->netdev_ops = &s2io_netdev_ops;
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- if (lro_enable)
- dev->features |= NETIF_F_LRO;
+ dev->features |= NETIF_F_LRO;
dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
if (sp->high_dma_flag == true)
dev->features |= NETIF_F_HIGHDMA;
^ permalink raw reply related
* Re: [PATCH 1/5] ptp: Added a brand new class driver for ptp clocks.
From: Richard Cochran @ 2010-08-18 7:19 UTC (permalink / raw)
To: john stultz
Cc: netdev, linux-kernel, linuxppc-dev, devicetree-discuss,
linux-arm-kernel, Krzysztof Halasa, Rodolfo Giometti,
Arnd Bergmann
In-Reply-To: <1282090963.1734.97.camel@localhost>
On Tue, Aug 17, 2010 at 05:22:43PM -0700, john stultz wrote:
> Why would system time not be adjusted to the PTP time?
>
> This is my main concern, that we're presenting a fractured API to
> userland. Suddenly there isn't just system time, but ptp time as well,
> and possibly multiple different ptp times.
John, it is a good thing to make thoughts about the big picture with
PTP clocks and the system time, like you are doing. However, the
situation is not as troubled as you think. Let me try to explain.
> The PTP clock is a bit of hardware (usually on the NIC) that can put
> timestamps on packets (both incoming or outgoing?).
Not only on the NIC. There are bunch of new products doing the
timestamping in the PHY or in a switch fabric attached to the host
like a PHY. The synchronization that one can achieve with PHY
timestamps is better that that with MAC timestamping.
> So while to me, it think it would be more ideal (or maybe just less
> different) to have a read-only interface (like the RTC), leaving PTPd to
> manage offset calculations and use that to steer the system time. I can
> acknowledge the need to have some way to correct the freq so the packet
> timestamps are corrected.
The PTPd need not change the system time at all for PTP clock to be
useful. (see below)
> I still feel a little concerned over the timer/alarm related interfaces.
> Could you explain why the alarm interface is necessary?
The timer/alarm stuff is "ancillary" and is not at all necessary. It
is just a "nice to have." I will happily remove it, if it is too
troubling for people.
> So really I think my initial negative gut reaction to this was mostly
> out of the fact that you introduced a char dev that provides almost 100%
> coverage of the posix-time interface. That is duplication we definitely
> don't want.
The reason why I modelled the char device on the posix interface was
to make the API more familiar to application programmers. After the
recent discussion (and having reviewed the posix clock implementation
in Linux), I now think it would be even better to simply offer a new
posic clock ID for PTP.
I was emulating the posix interface. Instead I should use it directly.
> Also I think the documentation I've read about PTP (likely just due to
> the engineering focus) has an odd inverted sense of priority, focusing
> on keeping obscure hardware clocks on NIC cards in sync, rather then the
> the more tangible feature of keeping the system time in sync.
>
> This could be comically interpreted as trying to create a shadow-time on
> the system that is the "real time" and "yea, maybe we'll let the system
> know what time it is, but user-apps who want to know the score can send
> a magic ioctl to /dev/something and get the real deal". ;) I'm sure
> that's not the case, but I'd like to keep any confusion in userland
> about which time is the best time to a minimum (ie: use the system
> time).
You are right. As John Eidson's excellent book points out, modern
computers and operating systems provide surprisingly little support
for programming based on absolute time. It is not PTP's fault. PTP is
actually a step in the right direction, but it doesn't yet really fit
in to the present computing world.
Okay, here is the Big Picture.
1. Use Case: SW timestamping
PTP with software timestamping (ie without special hardware) can
acheive synchronization within a few dozen microseconds, after
about twenty minutes. This is sufficient for very many people. The
new API (whether char device or syscall) fully and simply supports
this use case. When the PTPd adjusts the PTP clock, it is actually
adjusting the system time, just like NTPd.
2. Use Case: HW timestamping for industrial control
PTP with hardware timestamping can acheive synchronization within
100 nanoseconds after one minute. If you want to do something with
your wonderfully synchronization PTP clock, it must have some kind
of special hardware, like timestamping external signals or
generating one-shot or periodic outputs. The new API (whether char
device or syscall) supports this use case via the ancillary
commands.
In this case, the end user has an application that interfaces with
the outside world via the PTP clock API. Such a specialized
application (for example, motor control) uses only the PTP API,
since it knows that the standard posix API cannot help. It is
irrelevant that the system time is not synchronized, in this case.
The PTP clock hardware may or may not provide a hardware interface
(interrupt) to the main CPU. In this case, it does not matter. The
PTP clock is useful all by itself.
3. Use Case: HW timestamping with PPS to host
This case is the same as case 2, with the exception that the PTP
clock can interrupt the main CPU. The PTP clock driver advertises
the "PPS" capability. When enabled, the PTP layer delivers events
via the existing Linux PPS subsystem. Programs like NTPd can use
these events to regulate the system time.
This means that the system clock and the PTP clock will be at least
as well synchronized as when using a traditionial radio clock, GPS,
or IRIG-B method. In my opinion, this will be good enough for any
practical purpose. For example, let's say you want to run a
periodic task synchronized to the absolute wall clock time. Your
scheduling latency will be a dozen microseconds or so. Your PPS
synchronized system clock should be close enough to the PTP clock
to support this.
The API that I have suggested, whether offered as a char device or as
syscalls, supports all of the use cases using a single API.
Richard
^ permalink raw reply
* [PATCH v2] ether3: Use net_device_stats from struct net_device
From: Tobias Klauser @ 2010-08-18 7:04 UTC (permalink / raw)
To: David S. Miller, Russell King, netdev
Cc: linux-arm-kernel, kernel-janitors, Dan Carpenter
In-Reply-To: <1282061733-19700-1-git-send-email-tklauser@distanz.ch>
struct net_device has its own struct net_device_stats member, so use
this one instead of a private copy in the ether1_priv struct.
Cc: Dan Carpenter <error27@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---
drivers/net/arm/ether3.c | 24 ++++++++++++------------
drivers/net/arm/ether3.h | 1 -
2 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index 1361b73..052fc5a 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -323,7 +323,7 @@ ether3_init_for_open(struct net_device *dev)
{
int i;
- memset(&priv(dev)->stats, 0, sizeof(struct net_device_stats));
+ memset(&dev->stats, 0, sizeof(struct net_device_stats));
/* Reset the chip */
ether3_outw(CFG2_RESET, REG_CONFIG2);
@@ -447,7 +447,7 @@ ether3_close(struct net_device *dev)
*/
static struct net_device_stats *ether3_getstats(struct net_device *dev)
{
- return &priv(dev)->stats;
+ return &dev->stats;
}
/*
@@ -490,7 +490,7 @@ static void ether3_timeout(struct net_device *dev)
local_irq_restore(flags);
priv(dev)->regs.config2 |= CFG2_CTRLO;
- priv(dev)->stats.tx_errors += 1;
+ dev->stats.tx_errors += 1;
ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
priv(dev)->tx_head = priv(dev)->tx_tail = 0;
@@ -509,7 +509,7 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
if (priv(dev)->broken) {
dev_kfree_skb(skb);
- priv(dev)->stats.tx_dropped ++;
+ dev->stats.tx_dropped++;
netif_start_queue(dev);
return NETDEV_TX_OK;
}
@@ -673,7 +673,7 @@ if (next_ptr < RX_START || next_ptr >= RX_END) {
} else
goto dropping;
} else {
- struct net_device_stats *stats = &priv(dev)->stats;
+ struct net_device_stats *stats = &dev->stats;
ether3_outw(next_ptr >> 8, REG_RECVEND);
if (status & RXSTAT_OVERSIZE) stats->rx_over_errors ++;
if (status & RXSTAT_CRCERROR) stats->rx_crc_errors ++;
@@ -685,14 +685,14 @@ if (next_ptr < RX_START || next_ptr >= RX_END) {
while (-- maxcnt);
done:
- priv(dev)->stats.rx_packets += received;
+ dev->stats.rx_packets += received;
priv(dev)->rx_head = next_ptr;
/*
* If rx went off line, then that means that the buffer may be full. We
* have dropped at least one packet.
*/
if (!(ether3_inw(REG_STATUS) & STAT_RXON)) {
- priv(dev)->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
ether3_outw(next_ptr, REG_RECVPTR);
ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND);
}
@@ -710,7 +710,7 @@ dropping:{
last_warned = jiffies;
printk("%s: memory squeeze, dropping packet.\n", dev->name);
}
- priv(dev)->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
goto done;
}
}
@@ -743,13 +743,13 @@ static void ether3_tx(struct net_device *dev)
* Update errors
*/
if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS)))
- priv(dev)->stats.tx_packets++;
+ dev->stats.tx_packets++;
else {
- priv(dev)->stats.tx_errors ++;
+ dev->stats.tx_errors++;
if (status & TXSTAT_16COLLISIONS)
- priv(dev)->stats.collisions += 16;
+ dev->stats.collisions += 16;
if (status & TXSTAT_BABBLED)
- priv(dev)->stats.tx_fifo_errors ++;
+ dev->stats.tx_fifo_errors++;
}
tx_tail = (tx_tail + 1) & 15;
diff --git a/drivers/net/arm/ether3.h b/drivers/net/arm/ether3.h
index 1921a3a..2db63b0 100644
--- a/drivers/net/arm/ether3.h
+++ b/drivers/net/arm/ether3.h
@@ -164,7 +164,6 @@ struct dev_priv {
unsigned char tx_head; /* buffer nr to insert next packet */
unsigned char tx_tail; /* buffer nr of transmitting packet */
unsigned int rx_head; /* address to fetch next packet from */
- struct net_device_stats stats;
struct timer_list timer;
int broken; /* 0 = ok, 1 = something went wrong */
};
--
1.7.0.4
^ permalink raw reply related
* [PATCH v2] ether1: Use net_device_stats from struct net_device
From: Tobias Klauser @ 2010-08-18 7:04 UTC (permalink / raw)
To: David S. Miller, Russell King, netdev
Cc: linux-arm-kernel, kernel-janitors, Dan Carpenter
In-Reply-To: <1282061719-19645-1-git-send-email-tklauser@distanz.ch>
struct net_device has its own struct net_device_stats member, so use
this one instead of a private copy in the ether1_priv struct.
Cc: Dan Carpenter <error27@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---
drivers/net/arm/ether1.c | 28 ++++++++++++++--------------
drivers/net/arm/ether1.h | 1 -
2 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
index b17ab51..f08b6b2 100644
--- a/drivers/net/arm/ether1.c
+++ b/drivers/net/arm/ether1.c
@@ -649,7 +649,7 @@ ether1_open (struct net_device *dev)
if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
return -EAGAIN;
- memset (&priv(dev)->stats, 0, sizeof (struct net_device_stats));
+ memset(&dev->stats, 0, sizeof(struct net_device_stats));
if (ether1_init_for_open (dev)) {
free_irq (dev->irq, dev);
@@ -673,7 +673,7 @@ ether1_timeout(struct net_device *dev)
if (ether1_init_for_open (dev))
printk (KERN_ERR "%s: unable to restart interface\n", dev->name);
- priv(dev)->stats.tx_errors++;
+ dev->stats.tx_errors++;
netif_wake_queue(dev);
}
@@ -802,21 +802,21 @@ again:
while (nop.nop_status & STAT_COMPLETE) {
if (nop.nop_status & STAT_OK) {
- priv(dev)->stats.tx_packets ++;
- priv(dev)->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
+ dev->stats.tx_packets++;
+ dev->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
} else {
- priv(dev)->stats.tx_errors ++;
+ dev->stats.tx_errors++;
if (nop.nop_status & STAT_COLLAFTERTX)
- priv(dev)->stats.collisions ++;
+ dev->stats.collisions++;
if (nop.nop_status & STAT_NOCARRIER)
- priv(dev)->stats.tx_carrier_errors ++;
+ dev->stats.tx_carrier_errors++;
if (nop.nop_status & STAT_TXLOSTCTS)
printk (KERN_WARNING "%s: cts lost\n", dev->name);
if (nop.nop_status & STAT_TXSLOWDMA)
- priv(dev)->stats.tx_fifo_errors ++;
+ dev->stats.tx_fifo_errors++;
if (nop.nop_status & STAT_COLLEXCESSIVE)
- priv(dev)->stats.collisions += 16;
+ dev->stats.collisions += 16;
}
if (nop.nop_link == caddr) {
@@ -879,13 +879,13 @@ ether1_recv_done (struct net_device *dev)
skb->protocol = eth_type_trans (skb, dev);
netif_rx (skb);
- priv(dev)->stats.rx_packets ++;
+ dev->stats.rx_packets++;
} else
- priv(dev)->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
} else {
printk(KERN_WARNING "%s: %s\n", dev->name,
(rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid");
- priv(dev)->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
}
nexttail = ether1_readw(dev, priv(dev)->rx_tail, rfd_t, rfd_link, NORMALIRQS);
@@ -939,7 +939,7 @@ ether1_interrupt (int irq, void *dev_id)
printk (KERN_WARNING "%s: RU went not ready: RU suspended\n", dev->name);
ether1_writew(dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
writeb(CTRL_CA, REG_CONTROL);
- priv(dev)->stats.rx_dropped ++; /* we suspended due to lack of buffer space */
+ dev->stats.rx_dropped++; /* we suspended due to lack of buffer space */
} else
printk(KERN_WARNING "%s: RU went not ready: %04X\n", dev->name,
ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS));
@@ -965,7 +965,7 @@ ether1_close (struct net_device *dev)
static struct net_device_stats *
ether1_getstats (struct net_device *dev)
{
- return &priv(dev)->stats;
+ return &dev->stats;
}
/*
diff --git a/drivers/net/arm/ether1.h b/drivers/net/arm/ether1.h
index c8a4b23..3a5830a 100644
--- a/drivers/net/arm/ether1.h
+++ b/drivers/net/arm/ether1.h
@@ -38,7 +38,6 @@
struct ether1_priv {
void __iomem *base;
- struct net_device_stats stats;
unsigned int tx_link;
unsigned int tx_head;
volatile unsigned int tx_tail;
--
1.7.0.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox