[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20081001133233.GG970@ghostprotocols.net>
Date: Wed, 1 Oct 2008 10:32:33 -0300
From: Arnaldo Carvalho de Melo <acme@...hat.com>
To: Remi Denis-Courmont <remi.denis-courmont@...ia.com>
Cc: netdev@...r.kernel.org
Subject: Re: [PATCH 5/6] Phonet: implement GPRS virtual interface over PEP
socket
Em Wed, Oct 01, 2008 at 01:13:04PM +0300, Remi Denis-Courmont escreveu:
> From: Rémi Denis-Courmont <remi.denis-courmont@...ia.com>
>
> Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@...ia.com>
> ---
> include/linux/phonet.h | 8 +
> include/linux/socket.h | 1 +
> include/net/phonet/gprs.h | 38 +++++
> include/net/phonet/pep.h | 1 +
> net/phonet/Makefile | 2 +-
> net/phonet/pep-gprs.c | 341 +++++++++++++++++++++++++++++++++++++++++++++
> net/phonet/pep.c | 157 ++++++++++++++++++++--
> net/phonet/socket.c | 8 +-
> 8 files changed, 542 insertions(+), 14 deletions(-)
> create mode 100644 include/net/phonet/gprs.h
> create mode 100644 net/phonet/pep-gprs.c
>
> diff --git a/include/linux/phonet.h b/include/linux/phonet.h
> index f921852..c9609f9 100644
> --- a/include/linux/phonet.h
> +++ b/include/linux/phonet.h
> @@ -31,9 +31,17 @@
> #define PN_PROTO_PIPE 2
> #define PHONET_NPROTO 3
>
> +/* Socket options for SOL_PNPIPE level */
> +#define PNPIPE_ENCAP 1
> +#define PNPIPE_IFINDEX 2
> +
> #define PNADDR_ANY 0
> #define PNPORT_RESOURCE_ROUTING 0
>
> +/* Values for PNPIPE_ENCAP option */
> +#define PNPIPE_ENCAP_NONE 0
> +#define PNPIPE_ENCAP_IP 1
> +
> /* ioctls */
> #define SIOCPNGETOBJECT (SIOCPROTOPRIVATE + 0)
>
> diff --git a/include/linux/socket.h b/include/linux/socket.h
> index 818ca33..20fc4bb 100644
> --- a/include/linux/socket.h
> +++ b/include/linux/socket.h
> @@ -297,6 +297,7 @@ struct ucred {
> #define SOL_RXRPC 272
> #define SOL_PPPOL2TP 273
> #define SOL_BLUETOOTH 274
> +#define SOL_PNPIPE 275
>
> /* IPX options */
> #define IPX_TYPE 1
> diff --git a/include/net/phonet/gprs.h b/include/net/phonet/gprs.h
> new file mode 100644
> index 0000000..928daf5
> --- /dev/null
> +++ b/include/net/phonet/gprs.h
> @@ -0,0 +1,38 @@
> +/*
> + * File: pep_gprs.h
> + *
> + * GPRS over Phonet pipe end point socket
> + *
> + * Copyright (C) 2008 Nokia Corporation.
> + *
> + * Author: Rémi Denis-Courmont <remi.denis-courmont@...ia.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> + * 02110-1301 USA
> + */
> +
> +#ifndef NET_PHONET_GPRS_H
> +#define NET_PHONET_GPRS_H
> +
> +struct sock;
> +struct sk_buff;
> +
> +int pep_writeable(struct sock *sk);
> +int pep_write(struct sock *sk, struct sk_buff *skb);
> +struct sk_buff *pep_read(struct sock *sk);
> +
> +int gprs_attach(struct sock *sk);
> +void gprs_detach(struct sock *sk);
> +
> +#endif
> diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h
> index b06852b..a202adc 100644
> --- a/include/net/phonet/pep.h
> +++ b/include/net/phonet/pep.h
> @@ -35,6 +35,7 @@ struct pep_sock {
> struct sock *listener;
> struct sk_buff_head ctrlreq_queue;
> #define PNPIPE_CTRLREQ_MAX 10
> + int ifindex;
> u16 peer_type; /* peer type/subtype */
> u8 pipe_handle;
>
> diff --git a/net/phonet/Makefile b/net/phonet/Makefile
> index 505df2a..d62bbba 100644
> --- a/net/phonet/Makefile
> +++ b/net/phonet/Makefile
> @@ -8,4 +8,4 @@ phonet-objs := \
> sysctl.o \
> af_phonet.o
>
> -pn_pep-objs := pep.o
> +pn_pep-objs := pep.o pep-gprs.o
> diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c
> new file mode 100644
> index 0000000..3341346
> --- /dev/null
> +++ b/net/phonet/pep-gprs.c
> @@ -0,0 +1,341 @@
> +/*
> + * File: pep-gprs.c
> + *
> + * GPRS over Phonet pipe end point socket
> + *
> + * Copyright (C) 2008 Nokia Corporation.
> + *
> + * Author: Rémi Denis-Courmont <remi.denis-courmont@...ia.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> + * 02110-1301 USA
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/netdevice.h>
> +#include <linux/if_ether.h>
> +#include <linux/if_arp.h>
> +#include <net/sock.h>
> +
> +#include <linux/if_phonet.h>
> +#include <net/tcp_states.h>
> +#include <net/phonet/gprs.h>
> +
> +#define GPRS_DEFAULT_MTU 1400
> +
> +struct gprs_dev {
> + struct sock *sk;
> + void (*old_state_change)(struct sock *);
> + void (*old_data_ready)(struct sock *, int);
> + void (*old_write_space)(struct sock *);
> +
> + struct net_device *net;
> + struct net_device_stats stats;
> +
> + struct sk_buff_head tx_queue;
> + struct work_struct tx_work;
> + spinlock_t tx_lock;
> + unsigned tx_max;
> +};
> +
> +/*
> + * Socket callbacks
> + */
> +
> +static void gprs_state_change(struct sock *sk)
> +{
> + struct gprs_dev *dev = sk->sk_user_data;
> +
> + if (sk->sk_state == TCP_CLOSE_WAIT) {
> + netif_stop_queue(dev->net);
> + netif_carrier_off(dev->net);
> + }
> +}
> +
> +static int gprs_recv(struct gprs_dev *dev, struct sk_buff *skb)
> +{
> + int err = 0;
> + u16 protocol;
> +
> + if (!pskb_may_pull(skb, 1))
> + goto drop;
> +
> + /* Look at IP version field */
> + switch (skb->data[0] >> 4) {
> + case 4:
> + protocol = htons(ETH_P_IP);
> + break;
> + case 6:
> + protocol = htons(ETH_P_IPV6);
> + break;
> + default:
> + err = -EINVAL;
> + goto drop;
> + }
> +
> + if (likely(skb_headroom(skb) & 3)) {
> + struct sk_buff *rskb, *fs;
> + int flen = 0;
> +
> + /* Phonet Pipe data header is misaligned (3 bytes),
> + * so wrap the IP packet as a single fragment of an head-less
> + * socket buffer. The network stack will pull what it needs,
> + * but at least, the whole IP payload is not memcpy'd. */
> + rskb = netdev_alloc_skb(dev->net, 0);
> + if (!rskb) {
> + err = -ENOBUFS;
> + goto drop;
> + }
> + skb_shinfo(rskb)->frag_list = skb;
> + rskb->len += skb->len;
> + rskb->data_len += rskb->len;
> + rskb->truesize += rskb->len;
> +
> + /* Avoid nested fragments */
> + for (fs = skb_shinfo(skb)->frag_list; fs; fs = fs->next)
> + flen += fs->len;
> + skb->next = skb_shinfo(skb)->frag_list;
> + skb_shinfo(skb)->frag_list = NULL;
> + skb->len -= flen;
> + skb->data_len -= flen;
> + skb->truesize -= flen;
> +
> + skb = rskb;
> + }
> +
> + skb->protocol = protocol;
> + skb_reset_mac_header(skb);
> + skb->dev = dev->net;
Perhaps introduce gprs_type_trans() and do:
skb->protocol = gprs_type_trans() ?
Look at:
[acme@...pio linux-2.6]$ grep _type_trans tags | cut -f 1 | sort -u
ax25_type_trans
cisco_type_trans
dvb_net_eth_type_trans
ether1394_type_trans
eth_type_trans
farsync_type_trans
fddi_type_trans
hdlc_type_trans
hippi_type_trans
isdn_net_type_trans
lan_type_trans
mpt_lan_type_trans
myri_type_trans
plip_type_trans
ppp_type_trans
raw_type_trans
tr_type_trans
x25_type_trans
[acme@...pio linux-2.6]$
> +
> + if (likely(dev->net->flags & IFF_UP)) {
> + dev->stats.rx_packets++;
> + dev->stats.rx_bytes += skb->len;
> + netif_rx(skb);
> + skb = NULL;
> + } else
> + err = -ENODEV;
> +
> +drop:
> + if (skb) {
> + dev_kfree_skb(skb);
> + dev->stats.rx_dropped++;
> + }
> + return err;
> +}
> +
> +static void gprs_data_ready(struct sock *sk, int len)
> +{
> + struct gprs_dev *dev = sk->sk_user_data;
> + struct sk_buff *skb;
> +
> + while ((skb = pep_read(sk)) != NULL) {
> + skb_orphan(skb);
> + gprs_recv(dev, skb);
> + }
> +}
> +
> +static void gprs_write_space(struct sock *sk)
> +{
> + struct gprs_dev *dev = sk->sk_user_data;
> + unsigned credits = pep_writeable(sk);
> +
> + spin_lock_bh(&dev->tx_lock);
> + dev->tx_max = credits;
> + if (credits > skb_queue_len(&dev->tx_queue))
> + netif_wake_queue(dev->net);
> + spin_unlock_bh(&dev->tx_lock);
> +}
> +
> +/*
> + * Network device callbacks
> + */
> +
> +static int gprs_xmit(struct sk_buff *skb, struct net_device *net)
> +{
> + struct gprs_dev *dev = netdev_priv(net);
> +
> + switch (skb->protocol) {
> + case htons(ETH_P_IP):
> + case htons(ETH_P_IPV6):
> + break;
> + default:
> + dev_kfree_skb(skb);
> + return 0;
> + }
> +
> + spin_lock(&dev->tx_lock);
> + if (likely(skb_queue_len(&dev->tx_queue) < dev->tx_max)) {
> + skb_queue_tail(&dev->tx_queue, skb);
> + skb = NULL;
> + }
> + if (skb_queue_len(&dev->tx_queue) >= dev->tx_max)
> + netif_stop_queue(net);
> + spin_unlock(&dev->tx_lock);
> +
> + schedule_work(&dev->tx_work);
> + if (unlikely(skb))
> + dev_kfree_skb(skb);
> + return 0;
> +}
> +
> +static void gprs_tx(struct work_struct *work)
> +{
> + struct gprs_dev *dev = container_of(work, struct gprs_dev, tx_work);
> + struct sock *sk = dev->sk;
> + struct sk_buff *skb;
> +
> + while ((skb = skb_dequeue(&dev->tx_queue)) != NULL) {
> + int err;
> +
> + dev->stats.tx_bytes += skb->len;
> + dev->stats.tx_packets++;
> +
> + skb_orphan(skb);
> + skb_set_owner_w(skb, sk);
> +
> + lock_sock(sk);
> + err = pep_write(sk, skb);
> + if (err) {
> + if (net_ratelimit())
> + printk(KERN_WARNING"%s: TX error (%d)\n",
> + dev->net->name, err);
LIMIT_NETDEBUG()
> + dev->stats.tx_aborted_errors++;
> + dev->stats.tx_errors++;
> + }
> + release_sock(sk);
> + }
> +
> + lock_sock(sk);
> + gprs_write_space(sk);
> + release_sock(sk);
> +}
> +
> +static int gprs_set_mtu(struct net_device *net, int new_mtu)
> +{
> + if ((new_mtu < 576) || (new_mtu > (PHONET_MAX_MTU - 11)))
> + return -EINVAL;
> +
> + net->mtu = new_mtu;
> + return 0;
> +}
> +
> +static struct net_device_stats *gprs_get_stats(struct net_device *net)
> +{
> + struct gprs_dev *dev = netdev_priv(net);
> +
> + return &dev->stats;
> +}
> +
> +static void gprs_setup(struct net_device *net)
> +{
> + net->features = NETIF_F_FRAGLIST;
> + net->type = ARPHRD_NONE;
> + net->flags = IFF_POINTOPOINT | IFF_NOARP;
> + net->mtu = GPRS_DEFAULT_MTU;
> + net->hard_header_len = 0;
> + net->addr_len = 0;
> + net->tx_queue_len = 10;
> +
> + net->destructor = free_netdev;
> + net->hard_start_xmit = gprs_xmit; /* mandatory */
> + net->change_mtu = gprs_set_mtu;
> + net->get_stats = gprs_get_stats;
> +}
> +
> +/*
> + * External interface
> + */
> +
> +/*
> + * Attach a GPRS interface to a datagram socket.
> + * Returns the interface index on success, negative error code on error.
> + */
> +int gprs_attach(struct sock *sk)
> +{
> + static const char ifname[] = "gprs%d";
> + struct gprs_dev *dev;
> + struct net_device *net;
> + int err;
> +
> + if (unlikely(sk->sk_type == SOCK_STREAM))
> + return -EINVAL; /* need packet boundaries */
> +
> + /* Create net device */
> + net = alloc_netdev(sizeof(*dev), ifname, gprs_setup);
> + if (!net)
> + return -ENOMEM;
> + dev = netdev_priv(net);
> + dev->net = net;
> + dev->tx_max = 0;
> + spin_lock_init(&dev->tx_lock);
> + skb_queue_head_init(&dev->tx_queue);
> + INIT_WORK(&dev->tx_work, gprs_tx);
> +
> + netif_stop_queue(net);
> + err = register_netdev(net);
> + if (err) {
> + free_netdev(net);
> + return err;
> + }
> +
> + lock_sock(sk);
> + if (unlikely(sk->sk_user_data)) {
> + err = -EBUSY;
> + goto out_rel;
> + }
> + if (unlikely((1 << sk->sk_state & (TCPF_CLOSE|TCPF_LISTEN)) ||
> + sock_flag(sk, SOCK_DEAD))) {
> + err = -EINVAL;
> + goto out_rel;
> + }
> + sk->sk_user_data = dev;
> + dev->old_state_change = sk->sk_state_change;
> + dev->old_data_ready = sk->sk_data_ready;
> + dev->old_write_space = sk->sk_write_space;
> + sk->sk_state_change = gprs_state_change;
> + sk->sk_data_ready = gprs_data_ready;
> + sk->sk_write_space = gprs_write_space;
> + release_sock(sk);
> +
> + sock_hold(sk);
> + dev->sk = sk;
> +
> + printk(KERN_DEBUG"%s: attached\n", net->name);
> + gprs_write_space(sk); /* kick off TX */
> + return net->ifindex;
> +
> +out_rel:
> + release_sock(sk);
> + unregister_netdev(net);
> + return err;
> +}
> +
> +void gprs_detach(struct sock *sk)
> +{
> + struct gprs_dev *dev = sk->sk_user_data;
> + struct net_device *net = dev->net;
> +
> + lock_sock(sk);
> + sk->sk_user_data = NULL;
> + sk->sk_state_change = dev->old_state_change;
> + sk->sk_data_ready = dev->old_data_ready;
> + sk->sk_write_space = dev->old_write_space;
> + release_sock(sk);
> +
> + printk(KERN_DEBUG"%s: detached\n", net->name);
> + unregister_netdev(net);
> + flush_scheduled_work();
> + sock_put(sk);
> + skb_queue_purge(&dev->tx_queue);
> +}
> diff --git a/net/phonet/pep.c b/net/phonet/pep.c
> index 9a2ed45..f0c212f 100644
> --- a/net/phonet/pep.c
> +++ b/net/phonet/pep.c
> @@ -31,6 +31,7 @@
> #include <linux/phonet.h>
> #include <net/phonet/phonet.h>
> #include <net/phonet/pep.h>
> +#include <net/phonet/gprs.h>
>
> /* sk_state values:
> * TCP_CLOSE sock not in use yet
> @@ -610,6 +611,7 @@ drop:
> static void pep_sock_close(struct sock *sk, long timeout)
> {
> struct pep_sock *pn = pep_sk(sk);
> + int ifindex = 0;
>
> sk_common_release(sk);
>
> @@ -623,7 +625,12 @@ static void pep_sock_close(struct sock *sk, long timeout)
> sk_del_node_init(sknode);
> sk->sk_state = TCP_CLOSE;
> }
> + ifindex = pn->ifindex;
> + pn->ifindex = 0;
> release_sock(sk);
> +
> + if (ifindex)
> + gprs_detach(sk);
> }
>
> static int pep_wait_connreq(struct sock *sk, int noblock)
> @@ -728,12 +735,105 @@ static int pep_init(struct sock *sk)
> return 0;
> }
>
> +static int pep_setsockopt(struct sock *sk, int level, int optname,
> + char __user *optval, int optlen)
> +{
> + struct pep_sock *pn = pep_sk(sk);
> + int val = 0, err = 0;
> +
> + if (level != SOL_PNPIPE)
> + return -ENOPROTOOPT;
> + if (optlen >= sizeof(int)) {
> + if (get_user(val, (int __user *) optval))
> + return -EFAULT;
> + }
> +
> + lock_sock(sk);
> + switch (optname) {
> + case PNPIPE_ENCAP:
> + if (val && val != PNPIPE_ENCAP_IP) {
> + err = -EINVAL;
> + break;
> + }
> + if (!pn->ifindex == !val)
> + break; /* Nothing to do! */
> + if (!capable(CAP_NET_ADMIN)) {
> + err = -EPERM;
> + break;
> + }
> + if (val) {
> + release_sock(sk);
> + err = gprs_attach(sk);
> + if (err > 0) {
> + pn->ifindex = err;
> + err = 0;
> + }
> + } else {
> + pn->ifindex = 0;
> + release_sock(sk);
> + gprs_detach(sk);
> + err = 0;
> + }
> + goto out_norel;
> + default:
> + err = -ENOPROTOOPT;
> + }
> + release_sock(sk);
> +
> +out_norel:
> + return err;
> +}
> +
> +static int pep_getsockopt(struct sock *sk, int level, int optname,
> + char __user *optval, int __user *optlen)
> +{
> + struct pep_sock *pn = pep_sk(sk);
> + int len, val;
> +
> + if (level != SOL_PNPIPE)
> + return -ENOPROTOOPT;
> + if (get_user(len, optlen))
> + return -EFAULT;
> +
> + switch (optname) {
> + case PNPIPE_ENCAP:
> + val = pn->ifindex ? PNPIPE_ENCAP_IP : PNPIPE_ENCAP_NONE;
> + break;
> + case PNPIPE_IFINDEX:
> + val = pn->ifindex;
> + break;
> + default:
> + return -ENOPROTOOPT;
> + }
> +
> + len = min_t(unsigned int, sizeof(int), len);
> + if (put_user(len, optlen))
> + return -EFAULT;
> + if (put_user(val, (int __user *) optval))
> + return -EFAULT;
> + return 0;
> +}
> +
> +static int pipe_skb_send(struct sock *sk, struct sk_buff *skb)
> +{
> + struct pep_sock *pn = pep_sk(sk);
> + struct pnpipehdr *ph;
> +
> + ph = (struct pnpipehdr *)skb_push(skb, 3);
skb_reset_transport_header + pnp_hdr()?
> + ph->utid = 0;
> + ph->message_id = PNS_PIPE_DATA;
> + ph->pipe_handle = pn->pipe_handle;
> + if (pn_flow_safe(pn->tx_fc) && pn->tx_credits)
> + pn->tx_credits--;
> +
> + return pn_skb_send(sk, skb, &pipe_srv);
> +}
> +
> static int pep_sendmsg(struct kiocb *iocb, struct sock *sk,
> struct msghdr *msg, size_t len)
> {
> struct pep_sock *pn = pep_sk(sk);
> struct sk_buff *skb = NULL;
> - struct pnpipehdr *ph;
> long timeo;
> int flags = msg->msg_flags;
> int err, done;
> @@ -799,14 +899,7 @@ disabled:
> if (err < 0)
> goto out;
>
> - ph = (struct pnpipehdr *)skb_push(skb, 3);
> - ph->utid = 0;
> - ph->message_id = PNS_PIPE_DATA;
> - ph->pipe_handle = pn->pipe_handle;
> - if (pn_flow_safe(pn->tx_fc)) /* credit-based flow control */
> - pn->tx_credits--;
> -
> - err = pn_skb_send(sk, skb, &pipe_srv);
> + err = pipe_skb_send(sk, skb);
> if (err >= 0)
> err = len; /* success! */
> skb = NULL;
> @@ -817,6 +910,50 @@ out:
> return err;
> }
>
> +int pep_writeable(struct sock *sk)
> +{
> + struct pep_sock *pn = pep_sk(sk);
> +
> + return (sk->sk_state == TCP_ESTABLISHED) ? pn->tx_credits : 0;
> +}
> +
> +int pep_write(struct sock *sk, struct sk_buff *skb)
> +{
> + struct sk_buff *rskb, *fs;
> + int flen = 0;
> +
> + rskb = alloc_skb(MAX_PNPIPE_HEADER, GFP_ATOMIC);
> + if (!rskb) {
> + kfree_skb(skb);
> + return -ENOMEM;
> + }
> + skb_shinfo(rskb)->frag_list = skb;
> + rskb->len += skb->len;
> + rskb->data_len += rskb->len;
> + rskb->truesize += rskb->len;
> +
> + /* Avoid nested fragments */
> + for (fs = skb_shinfo(skb)->frag_list; fs; fs = fs->next)
> + flen += fs->len;
> + skb->next = skb_shinfo(skb)->frag_list;
> + skb_shinfo(skb)->frag_list = NULL;
> + skb->len -= flen;
> + skb->data_len -= flen;
> + skb->truesize -= flen;
> +
> + skb_reserve(rskb, MAX_PHONET_HEADER + 3);
> + return pipe_skb_send(sk, rskb);
> +}
> +
> +struct sk_buff *pep_read(struct sock *sk)
> +{
> + struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue);
> +
> + if (sk->sk_state == TCP_ESTABLISHED)
> + pipe_grant_credits(sk);
> + return skb;
> +}
> +
> static int pep_recvmsg(struct kiocb *iocb, struct sock *sk,
> struct msghdr *msg, size_t len, int noblock,
> int flags, int *addr_len)
> @@ -899,6 +1036,8 @@ static struct proto pep_proto = {
> .accept = pep_sock_accept,
> .ioctl = pep_ioctl,
> .init = pep_init,
> + .setsockopt = pep_setsockopt,
> + .getsockopt = pep_getsockopt,
> .sendmsg = pep_sendmsg,
> .recvmsg = pep_recvmsg,
> .backlog_rcv = pep_do_rcv,
> diff --git a/net/phonet/socket.c b/net/phonet/socket.c
> index a9c3d1f..d817401 100644
> --- a/net/phonet/socket.c
> +++ b/net/phonet/socket.c
> @@ -342,11 +342,11 @@ const struct proto_ops phonet_stream_ops = {
> .ioctl = pn_socket_ioctl,
> .listen = pn_socket_listen,
> .shutdown = sock_no_shutdown,
> - .setsockopt = sock_no_setsockopt,
> - .getsockopt = sock_no_getsockopt,
> + .setsockopt = sock_common_setsockopt,
> + .getsockopt = sock_common_getsockopt,
> #ifdef CONFIG_COMPAT
> - .compat_setsockopt = sock_no_setsockopt,
> - .compat_getsockopt = compat_sock_no_getsockopt,
> + .compat_setsockopt = compat_sock_common_setsockopt,
> + .compat_getsockopt = compat_sock_common_getsockopt,
> #endif
> .sendmsg = pn_socket_sendmsg,
> .recvmsg = sock_common_recvmsg,
> --
> 1.5.4.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@...r.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists