Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1429 commits) net: Allow dependancies of FDDI & Tokenring to be modular. igb: Fix build warning when DCA is disabled. net: Fix warning fallout from recent NAPI interface changes. gro: Fix potential use after free sfc: If AN is enabled, always read speed/duplex from the AN advertising bits sfc: When disabling the NIC, close the device rather than unregistering it sfc: SFT9001: Add cable diagnostics sfc: Add support for multiple PHY self-tests sfc: Merge top-level functions for self-tests sfc: Clean up PHY mode management in loopback self-test sfc: Fix unreliable link detection in some loopback modes sfc: Generate unique names for per-NIC workqueues 802.3ad: use standard ethhdr instead of ad_header 802.3ad: generalize out mac address initializer 802.3ad: initialize ports LACPDU from const initializer 802.3ad: remove typedef around ad_system 802.3ad: turn ports is_individual into a bool 802.3ad: turn ports is_enabled into a bool 802.3ad: make ntt bool ixgbe: Fix set_ringparam in ixgbe to use the same memory pools. ... Fixed trivial IPv4/6 address printing conflicts in fs/cifs/connect.c due to the conversion to %pI (in this networking merge) and the addition of doing IPv6 addresses (from the earlier merge of CIFS).
This commit is contained in:
@@ -167,23 +167,27 @@ __be16 fddi_type_trans(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
EXPORT_SYMBOL(fddi_type_trans);
|
||||
|
||||
static int fddi_change_mtu(struct net_device *dev, int new_mtu)
|
||||
int fddi_change_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
if ((new_mtu < FDDI_K_SNAP_HLEN) || (new_mtu > FDDI_K_SNAP_DLEN))
|
||||
return(-EINVAL);
|
||||
dev->mtu = new_mtu;
|
||||
return(0);
|
||||
}
|
||||
EXPORT_SYMBOL(fddi_change_mtu);
|
||||
|
||||
static const struct header_ops fddi_header_ops = {
|
||||
.create = fddi_header,
|
||||
.rebuild = fddi_rebuild_header,
|
||||
};
|
||||
|
||||
|
||||
static void fddi_setup(struct net_device *dev)
|
||||
{
|
||||
dev->change_mtu = fddi_change_mtu;
|
||||
dev->header_ops = &fddi_header_ops;
|
||||
#ifdef CONFIG_COMPAT_NET_DEV_OPS
|
||||
dev->change_mtu = fddi_change_mtu,
|
||||
#endif
|
||||
|
||||
dev->type = ARPHRD_FDDI;
|
||||
dev->hard_header_len = FDDI_K_SNAP_HLEN+3; /* Assume 802.2 SNAP hdr len + 3 pad bytes */
|
||||
|
@@ -144,7 +144,7 @@ __be16 hippi_type_trans(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
EXPORT_SYMBOL(hippi_type_trans);
|
||||
|
||||
static int hippi_change_mtu(struct net_device *dev, int new_mtu)
|
||||
int hippi_change_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
/*
|
||||
* HIPPI's got these nice large MTUs.
|
||||
@@ -154,12 +154,13 @@ static int hippi_change_mtu(struct net_device *dev, int new_mtu)
|
||||
dev->mtu = new_mtu;
|
||||
return(0);
|
||||
}
|
||||
EXPORT_SYMBOL(hippi_change_mtu);
|
||||
|
||||
/*
|
||||
* For HIPPI we will actually use the lower 4 bytes of the hardware
|
||||
* address as the I-FIELD rather than the actual hardware address.
|
||||
*/
|
||||
static int hippi_mac_addr(struct net_device *dev, void *p)
|
||||
int hippi_mac_addr(struct net_device *dev, void *p)
|
||||
{
|
||||
struct sockaddr *addr = p;
|
||||
if (netif_running(dev))
|
||||
@@ -167,8 +168,9 @@ static int hippi_mac_addr(struct net_device *dev, void *p)
|
||||
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(hippi_mac_addr);
|
||||
|
||||
static int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p)
|
||||
int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p)
|
||||
{
|
||||
/* Never send broadcast/multicast ARP messages */
|
||||
p->mcast_probes = 0;
|
||||
@@ -181,6 +183,7 @@ static int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p)
|
||||
p->ucast_probes = 0;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(hippi_neigh_setup_dev);
|
||||
|
||||
static const struct header_ops hippi_header_ops = {
|
||||
.create = hippi_header,
|
||||
@@ -190,11 +193,12 @@ static const struct header_ops hippi_header_ops = {
|
||||
|
||||
static void hippi_setup(struct net_device *dev)
|
||||
{
|
||||
dev->set_multicast_list = NULL;
|
||||
#ifdef CONFIG_COMPAT_NET_DEV_OPS
|
||||
dev->change_mtu = hippi_change_mtu;
|
||||
dev->header_ops = &hippi_header_ops;
|
||||
dev->set_mac_address = hippi_mac_addr;
|
||||
dev->neigh_setup = hippi_neigh_setup_dev;
|
||||
#endif
|
||||
dev->header_ops = &hippi_header_ops;
|
||||
|
||||
/*
|
||||
* We don't support HIPPI `ARP' for the time being, and probably
|
||||
|
24
net/802/tr.c
24
net/802/tr.c
@@ -285,10 +285,7 @@ void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,
|
||||
if(entry)
|
||||
{
|
||||
#if TR_SR_DEBUG
|
||||
{
|
||||
DECLARE_MAC_BUF(mac);
|
||||
printk("source routing for %s\n",print_mac(mac, trh->daddr));
|
||||
}
|
||||
printk("source routing for %pM\n", trh->daddr);
|
||||
#endif
|
||||
if(!entry->local_ring && (ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8)
|
||||
{
|
||||
@@ -370,9 +367,8 @@ static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev)
|
||||
if(entry==NULL)
|
||||
{
|
||||
#if TR_SR_DEBUG
|
||||
DECLARE_MAC_BUF(mac);
|
||||
printk("adding rif_entry: addr:%s rcf:%04X\n",
|
||||
print_mac(mac, trh->saddr), ntohs(trh->rcf));
|
||||
printk("adding rif_entry: addr:%pM rcf:%04X\n",
|
||||
trh->saddr, ntohs(trh->rcf));
|
||||
#endif
|
||||
/*
|
||||
* Allocate our new entry. A failure to allocate loses
|
||||
@@ -417,11 +413,8 @@ static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev)
|
||||
!(trh->rcf & htons(TR_RCF_BROADCAST_MASK)))
|
||||
{
|
||||
#if TR_SR_DEBUG
|
||||
{
|
||||
DECLARE_MAC_BUF(mac);
|
||||
printk("updating rif_entry: addr:%s rcf:%04X\n",
|
||||
print_mac(mac, trh->saddr), ntohs(trh->rcf));
|
||||
}
|
||||
printk("updating rif_entry: addr:%pM rcf:%04X\n",
|
||||
trh->saddr, ntohs(trh->rcf));
|
||||
#endif
|
||||
entry->rcf = trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK);
|
||||
memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
|
||||
@@ -532,7 +525,6 @@ static int rif_seq_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
int j, rcf_len, segment, brdgnmb;
|
||||
struct rif_cache *entry = v;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
if (v == SEQ_START_TOKEN)
|
||||
seq_puts(seq,
|
||||
@@ -542,9 +534,9 @@ static int rif_seq_show(struct seq_file *seq, void *v)
|
||||
long ttl = (long) (entry->last_used + sysctl_tr_rif_timeout)
|
||||
- (long) jiffies;
|
||||
|
||||
seq_printf(seq, "%s %s %7li ",
|
||||
seq_printf(seq, "%s %pM %7li ",
|
||||
dev?dev->name:"?",
|
||||
print_mac(mac, entry->addr),
|
||||
entry->addr,
|
||||
ttl/HZ);
|
||||
|
||||
if (entry->local_ring)
|
||||
@@ -643,7 +635,7 @@ static struct ctl_table tr_table[] = {
|
||||
.data = &sysctl_tr_rif_timeout,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
.proc_handler = proc_dointvec
|
||||
},
|
||||
{ 0 },
|
||||
};
|
||||
|
@@ -46,10 +46,10 @@ int vlan_net_id;
|
||||
/* Our listing of VLAN group(s) */
|
||||
static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
|
||||
|
||||
static char vlan_fullname[] = "802.1Q VLAN Support";
|
||||
static char vlan_version[] = DRV_VERSION;
|
||||
static char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
|
||||
static char vlan_buggyright[] = "David S. Miller <davem@redhat.com>";
|
||||
const char vlan_fullname[] = "802.1Q VLAN Support";
|
||||
const char vlan_version[] = DRV_VERSION;
|
||||
static const char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
|
||||
static const char vlan_buggyright[] = "David S. Miller <davem@redhat.com>";
|
||||
|
||||
static struct packet_type vlan_packet_type = {
|
||||
.type = __constant_htons(ETH_P_8021Q),
|
||||
@@ -144,6 +144,7 @@ void unregister_vlan_dev(struct net_device *dev)
|
||||
{
|
||||
struct vlan_dev_info *vlan = vlan_dev_info(dev);
|
||||
struct net_device *real_dev = vlan->real_dev;
|
||||
const struct net_device_ops *ops = real_dev->netdev_ops;
|
||||
struct vlan_group *grp;
|
||||
u16 vlan_id = vlan->vlan_id;
|
||||
|
||||
@@ -156,7 +157,7 @@ void unregister_vlan_dev(struct net_device *dev)
|
||||
* HW accelerating devices or SW vlan input packet processing.
|
||||
*/
|
||||
if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
|
||||
real_dev->vlan_rx_kill_vid(real_dev, vlan_id);
|
||||
ops->ndo_vlan_rx_kill_vid(real_dev, vlan_id);
|
||||
|
||||
vlan_group_set_device(grp, vlan_id, NULL);
|
||||
grp->nr_vlans--;
|
||||
@@ -170,7 +171,7 @@ void unregister_vlan_dev(struct net_device *dev)
|
||||
vlan_gvrp_uninit_applicant(real_dev);
|
||||
|
||||
if (real_dev->features & NETIF_F_HW_VLAN_RX)
|
||||
real_dev->vlan_rx_register(real_dev, NULL);
|
||||
ops->ndo_vlan_rx_register(real_dev, NULL);
|
||||
|
||||
hlist_del_rcu(&grp->hlist);
|
||||
|
||||
@@ -205,21 +206,21 @@ static void vlan_transfer_operstate(const struct net_device *dev,
|
||||
|
||||
int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id)
|
||||
{
|
||||
char *name = real_dev->name;
|
||||
const char *name = real_dev->name;
|
||||
const struct net_device_ops *ops = real_dev->netdev_ops;
|
||||
|
||||
if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
|
||||
pr_info("8021q: VLANs not supported on %s\n", name);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if ((real_dev->features & NETIF_F_HW_VLAN_RX) &&
|
||||
!real_dev->vlan_rx_register) {
|
||||
if ((real_dev->features & NETIF_F_HW_VLAN_RX) && !ops->ndo_vlan_rx_register) {
|
||||
pr_info("8021q: device %s has buggy VLAN hw accel\n", name);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
|
||||
(!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) {
|
||||
(!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) {
|
||||
pr_info("8021q: Device %s has buggy VLAN hw accel\n", name);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@@ -240,6 +241,7 @@ int register_vlan_dev(struct net_device *dev)
|
||||
{
|
||||
struct vlan_dev_info *vlan = vlan_dev_info(dev);
|
||||
struct net_device *real_dev = vlan->real_dev;
|
||||
const struct net_device_ops *ops = real_dev->netdev_ops;
|
||||
u16 vlan_id = vlan->vlan_id;
|
||||
struct vlan_group *grp, *ngrp = NULL;
|
||||
int err;
|
||||
@@ -275,9 +277,9 @@ int register_vlan_dev(struct net_device *dev)
|
||||
grp->nr_vlans++;
|
||||
|
||||
if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
|
||||
real_dev->vlan_rx_register(real_dev, ngrp);
|
||||
ops->ndo_vlan_rx_register(real_dev, ngrp);
|
||||
if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
|
||||
real_dev->vlan_rx_add_vid(real_dev, vlan_id);
|
||||
ops->ndo_vlan_rx_add_vid(real_dev, vlan_id);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@@ -108,8 +108,10 @@ static inline int vlan_gvrp_init(void) { return 0; }
|
||||
static inline void vlan_gvrp_uninit(void) {}
|
||||
#endif
|
||||
|
||||
int vlan_netlink_init(void);
|
||||
void vlan_netlink_fini(void);
|
||||
extern const char vlan_fullname[];
|
||||
extern const char vlan_version[];
|
||||
extern int vlan_netlink_init(void);
|
||||
extern void vlan_netlink_fini(void);
|
||||
|
||||
extern struct rtnl_link_ops vlan_link_ops;
|
||||
|
||||
|
@@ -47,8 +47,6 @@ int vlan_hwaccel_do_receive(struct sk_buff *skb)
|
||||
skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
|
||||
skb->vlan_tci = 0;
|
||||
|
||||
dev->last_rx = jiffies;
|
||||
|
||||
stats = &dev->stats;
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += skb->len;
|
||||
|
@@ -163,8 +163,6 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
skb->dev->last_rx = jiffies;
|
||||
|
||||
stats = &skb->dev->stats;
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += skb->len;
|
||||
@@ -526,6 +524,7 @@ out:
|
||||
static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
struct net_device *real_dev = vlan_dev_info(dev)->real_dev;
|
||||
const struct net_device_ops *ops = real_dev->netdev_ops;
|
||||
struct ifreq ifrr;
|
||||
int err = -EOPNOTSUPP;
|
||||
|
||||
@@ -536,8 +535,8 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
case SIOCGMIIPHY:
|
||||
case SIOCGMIIREG:
|
||||
case SIOCSMIIREG:
|
||||
if (real_dev->do_ioctl && netif_device_present(real_dev))
|
||||
err = real_dev->do_ioctl(real_dev, &ifrr, cmd);
|
||||
if (netif_device_present(real_dev) && ops->ndo_do_ioctl)
|
||||
err = ops->ndo_do_ioctl(real_dev, &ifrr, cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -594,6 +593,8 @@ static const struct header_ops vlan_header_ops = {
|
||||
.parse = eth_header_parse,
|
||||
};
|
||||
|
||||
static const struct net_device_ops vlan_netdev_ops, vlan_netdev_accel_ops;
|
||||
|
||||
static int vlan_dev_init(struct net_device *dev)
|
||||
{
|
||||
struct net_device *real_dev = vlan_dev_info(dev)->real_dev;
|
||||
@@ -620,11 +621,11 @@ static int vlan_dev_init(struct net_device *dev)
|
||||
if (real_dev->features & NETIF_F_HW_VLAN_TX) {
|
||||
dev->header_ops = real_dev->header_ops;
|
||||
dev->hard_header_len = real_dev->hard_header_len;
|
||||
dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
|
||||
dev->netdev_ops = &vlan_netdev_accel_ops;
|
||||
} else {
|
||||
dev->header_ops = &vlan_header_ops;
|
||||
dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
|
||||
dev->hard_start_xmit = vlan_dev_hard_start_xmit;
|
||||
dev->netdev_ops = &vlan_netdev_ops;
|
||||
}
|
||||
|
||||
if (is_vlan_dev(real_dev))
|
||||
@@ -648,6 +649,26 @@ static void vlan_dev_uninit(struct net_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static int vlan_ethtool_get_settings(struct net_device *dev,
|
||||
struct ethtool_cmd *cmd)
|
||||
{
|
||||
const struct vlan_dev_info *vlan = vlan_dev_info(dev);
|
||||
struct net_device *real_dev = vlan->real_dev;
|
||||
|
||||
if (!real_dev->ethtool_ops->get_settings)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return real_dev->ethtool_ops->get_settings(real_dev, cmd);
|
||||
}
|
||||
|
||||
static void vlan_ethtool_get_drvinfo(struct net_device *dev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
strcpy(info->driver, vlan_fullname);
|
||||
strcpy(info->version, vlan_version);
|
||||
strcpy(info->fw_version, "N/A");
|
||||
}
|
||||
|
||||
static u32 vlan_ethtool_get_rx_csum(struct net_device *dev)
|
||||
{
|
||||
const struct vlan_dev_info *vlan = vlan_dev_info(dev);
|
||||
@@ -672,11 +693,43 @@ static u32 vlan_ethtool_get_flags(struct net_device *dev)
|
||||
}
|
||||
|
||||
static const struct ethtool_ops vlan_ethtool_ops = {
|
||||
.get_settings = vlan_ethtool_get_settings,
|
||||
.get_drvinfo = vlan_ethtool_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_rx_csum = vlan_ethtool_get_rx_csum,
|
||||
.get_flags = vlan_ethtool_get_flags,
|
||||
};
|
||||
|
||||
static const struct net_device_ops vlan_netdev_ops = {
|
||||
.ndo_change_mtu = vlan_dev_change_mtu,
|
||||
.ndo_init = vlan_dev_init,
|
||||
.ndo_uninit = vlan_dev_uninit,
|
||||
.ndo_open = vlan_dev_open,
|
||||
.ndo_stop = vlan_dev_stop,
|
||||
.ndo_start_xmit = vlan_dev_hard_start_xmit,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_set_mac_address = vlan_dev_set_mac_address,
|
||||
.ndo_set_rx_mode = vlan_dev_set_rx_mode,
|
||||
.ndo_set_multicast_list = vlan_dev_set_rx_mode,
|
||||
.ndo_change_rx_flags = vlan_dev_change_rx_flags,
|
||||
.ndo_do_ioctl = vlan_dev_ioctl,
|
||||
};
|
||||
|
||||
static const struct net_device_ops vlan_netdev_accel_ops = {
|
||||
.ndo_change_mtu = vlan_dev_change_mtu,
|
||||
.ndo_init = vlan_dev_init,
|
||||
.ndo_uninit = vlan_dev_uninit,
|
||||
.ndo_open = vlan_dev_open,
|
||||
.ndo_stop = vlan_dev_stop,
|
||||
.ndo_start_xmit = vlan_dev_hwaccel_hard_start_xmit,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_set_mac_address = vlan_dev_set_mac_address,
|
||||
.ndo_set_rx_mode = vlan_dev_set_rx_mode,
|
||||
.ndo_set_multicast_list = vlan_dev_set_rx_mode,
|
||||
.ndo_change_rx_flags = vlan_dev_change_rx_flags,
|
||||
.ndo_do_ioctl = vlan_dev_ioctl,
|
||||
};
|
||||
|
||||
void vlan_setup(struct net_device *dev)
|
||||
{
|
||||
ether_setup(dev);
|
||||
@@ -684,16 +737,7 @@ void vlan_setup(struct net_device *dev)
|
||||
dev->priv_flags |= IFF_802_1Q_VLAN;
|
||||
dev->tx_queue_len = 0;
|
||||
|
||||
dev->change_mtu = vlan_dev_change_mtu;
|
||||
dev->init = vlan_dev_init;
|
||||
dev->uninit = vlan_dev_uninit;
|
||||
dev->open = vlan_dev_open;
|
||||
dev->stop = vlan_dev_stop;
|
||||
dev->set_mac_address = vlan_dev_set_mac_address;
|
||||
dev->set_rx_mode = vlan_dev_set_rx_mode;
|
||||
dev->set_multicast_list = vlan_dev_set_rx_mode;
|
||||
dev->change_rx_flags = vlan_dev_change_rx_flags;
|
||||
dev->do_ioctl = vlan_dev_ioctl;
|
||||
dev->netdev_ops = &vlan_netdev_ops;
|
||||
dev->destructor = free_netdev;
|
||||
dev->ethtool_ops = &vlan_ethtool_ops;
|
||||
|
||||
|
@@ -528,8 +528,6 @@ static void rdma_close(struct p9_client *client)
|
||||
|
||||
/**
|
||||
* alloc_rdma - Allocate and initialize the rdma transport structure
|
||||
* @msize: MTU
|
||||
* @dotu: Extension attribute
|
||||
* @opts: Mount options structure
|
||||
*/
|
||||
static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts)
|
||||
|
@@ -27,11 +27,14 @@ menu "Networking options"
|
||||
config NET_NS
|
||||
bool "Network namespace support"
|
||||
default n
|
||||
depends on EXPERIMENTAL && !SYSFS && NAMESPACES
|
||||
depends on EXPERIMENTAL && NAMESPACES
|
||||
help
|
||||
Allow user space to create what appear to be multiple instances
|
||||
of the network stack.
|
||||
|
||||
config COMPAT_NET_DEV_OPS
|
||||
def_bool y
|
||||
|
||||
source "net/packet/Kconfig"
|
||||
source "net/unix/Kconfig"
|
||||
source "net/xfrm/Kconfig"
|
||||
@@ -191,6 +194,7 @@ source "net/lapb/Kconfig"
|
||||
source "net/econet/Kconfig"
|
||||
source "net/wanrouter/Kconfig"
|
||||
source "net/sched/Kconfig"
|
||||
source "net/dcb/Kconfig"
|
||||
|
||||
menu "Network testing"
|
||||
|
||||
@@ -247,7 +251,6 @@ if WIRELESS
|
||||
|
||||
source "net/wireless/Kconfig"
|
||||
source "net/mac80211/Kconfig"
|
||||
source "net/ieee80211/Kconfig"
|
||||
|
||||
endif # WIRELESS
|
||||
|
||||
|
@@ -51,12 +51,14 @@ obj-$(CONFIG_IP_DCCP) += dccp/
|
||||
obj-$(CONFIG_IP_SCTP) += sctp/
|
||||
obj-y += wireless/
|
||||
obj-$(CONFIG_MAC80211) += mac80211/
|
||||
obj-$(CONFIG_IEEE80211) += ieee80211/
|
||||
obj-$(CONFIG_TIPC) += tipc/
|
||||
obj-$(CONFIG_NETLABEL) += netlabel/
|
||||
obj-$(CONFIG_IUCV) += iucv/
|
||||
obj-$(CONFIG_RFKILL) += rfkill/
|
||||
obj-$(CONFIG_NET_9P) += 9p/
|
||||
ifneq ($(CONFIG_DCB),)
|
||||
obj-y += dcb/
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET),y)
|
||||
obj-$(CONFIG_SYSCTL) += sysctl_net.o
|
||||
|
@@ -995,7 +995,6 @@ static int aarp_seq_show(struct seq_file *seq, void *v)
|
||||
struct aarp_iter_state *iter = seq->private;
|
||||
struct aarp_entry *entry = v;
|
||||
unsigned long now = jiffies;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
if (v == SEQ_START_TOKEN)
|
||||
seq_puts(seq,
|
||||
@@ -1006,7 +1005,7 @@ static int aarp_seq_show(struct seq_file *seq, void *v)
|
||||
ntohs(entry->target_addr.s_net),
|
||||
(unsigned int) entry->target_addr.s_node,
|
||||
entry->dev ? entry->dev->name : "????");
|
||||
seq_printf(seq, "%s", print_mac(mac, entry->hwaddr));
|
||||
seq_printf(seq, "%pM", entry->hwaddr);
|
||||
seq_printf(seq, " %8s",
|
||||
dt2str((long)entry->expires_at - (long)now));
|
||||
if (iter->table == unresolved)
|
||||
|
@@ -815,9 +815,6 @@ static int atif_ioctl(int cmd, void __user *arg)
|
||||
return -EPERM;
|
||||
if (sa->sat_family != AF_APPLETALK)
|
||||
return -EINVAL;
|
||||
if (!atif)
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
/*
|
||||
* for now, we only support proxy AARP on ELAP;
|
||||
* we should be able to do it for LocalTalk, too.
|
||||
@@ -1284,7 +1281,7 @@ static int handle_ip_over_ddp(struct sk_buff *skb)
|
||||
skb->dev = dev;
|
||||
skb_reset_transport_header(skb);
|
||||
|
||||
stats = dev->priv;
|
||||
stats = netdev_priv(dev);
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += skb->len + 13;
|
||||
netif_rx(skb); /* Send the SKB up to a higher place. */
|
||||
|
@@ -17,8 +17,8 @@ static struct ctl_table atalk_table[] = {
|
||||
.data = &sysctl_aarp_expiry_time,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_jiffies,
|
||||
.strategy = &sysctl_jiffies,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
.strategy = sysctl_jiffies,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_ATALK_AARP_TICK_TIME,
|
||||
@@ -26,8 +26,8 @@ static struct ctl_table atalk_table[] = {
|
||||
.data = &sysctl_aarp_tick_time,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_jiffies,
|
||||
.strategy = &sysctl_jiffies,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
.strategy = sysctl_jiffies,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_ATALK_AARP_RETRANSMIT_LIMIT,
|
||||
@@ -35,7 +35,7 @@ static struct ctl_table atalk_table[] = {
|
||||
.data = &sysctl_aarp_retransmit_limit,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_ATALK_AARP_RESOLVE_TIME,
|
||||
@@ -43,8 +43,8 @@ static struct ctl_table atalk_table[] = {
|
||||
.data = &sysctl_aarp_resolve_time,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_jiffies,
|
||||
.strategy = &sysctl_jiffies,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
.strategy = sysctl_jiffies,
|
||||
},
|
||||
{ 0 },
|
||||
};
|
||||
|
@@ -149,7 +149,7 @@ int atm_register_sysfs(struct atm_dev *adev)
|
||||
cdev->class = &atm_class;
|
||||
dev_set_drvdata(cdev, adev);
|
||||
|
||||
snprintf(cdev->bus_id, BUS_ID_SIZE, "%s%d", adev->type, adev->number);
|
||||
dev_set_name(cdev, "%s%d", adev->type, adev->number);
|
||||
err = device_register(cdev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@@ -101,7 +101,7 @@ static LIST_HEAD(br2684_devs);
|
||||
|
||||
static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev)
|
||||
{
|
||||
return (struct br2684_dev *)net_dev->priv;
|
||||
return (struct br2684_dev *)netdev_priv(net_dev);
|
||||
}
|
||||
|
||||
static inline struct net_device *list_entry_brdev(const struct list_head *le)
|
||||
@@ -698,12 +698,11 @@ static int br2684_seq_show(struct seq_file *seq, void *v)
|
||||
br2684_devs);
|
||||
const struct net_device *net_dev = brdev->net_dev;
|
||||
const struct br2684_vcc *brvcc;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
seq_printf(seq, "dev %.16s: num=%d, mac=%s (%s)\n",
|
||||
seq_printf(seq, "dev %.16s: num=%d, mac=%pM (%s)\n",
|
||||
net_dev->name,
|
||||
brdev->number,
|
||||
print_mac(mac, net_dev->dev_addr),
|
||||
net_dev->dev_addr,
|
||||
brdev->mac_was_set ? "set" : "auto");
|
||||
|
||||
list_for_each_entry(brvcc, &brdev->brvccs, brvccs) {
|
||||
|
@@ -822,8 +822,8 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev,
|
||||
seq_printf(seq, "%-6s%-4s%-4s%5ld ",
|
||||
dev->name, svc ? "SVC" : "PVC", llc ? "LLC" : "NULL", exp);
|
||||
|
||||
off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d",
|
||||
NIPQUAD(entry->ip));
|
||||
off = scnprintf(buf, sizeof(buf) - 1, "%pI4",
|
||||
&entry->ip);
|
||||
while (off < 16)
|
||||
buf[off++] = ' ';
|
||||
buf[off] = '\0';
|
||||
|
@@ -19,6 +19,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
|
||||
size_t total_len);
|
||||
unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait);
|
||||
int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
|
||||
int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
|
||||
int vcc_setsockopt(struct socket *sock, int level, int optname,
|
||||
char __user *optval, int optlen);
|
||||
int vcc_getsockopt(struct socket *sock, int level, int optname,
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#include <linux/atmlec.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/ioctls.h>
|
||||
#include <net/compat.h>
|
||||
|
||||
#include "resources.h"
|
||||
#include "signaling.h" /* for WAITING and sigd_attach */
|
||||
@@ -46,7 +47,7 @@ void deregister_atm_ioctl(struct atm_ioctl *ioctl)
|
||||
EXPORT_SYMBOL(register_atm_ioctl);
|
||||
EXPORT_SYMBOL(deregister_atm_ioctl);
|
||||
|
||||
int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||
static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg, int compat)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
struct atm_vcc *vcc;
|
||||
@@ -80,13 +81,25 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||
goto done;
|
||||
}
|
||||
case SIOCGSTAMP: /* borrowed from IP */
|
||||
error = sock_get_timestamp(sk, argp);
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (compat)
|
||||
error = compat_sock_get_timestamp(sk, argp);
|
||||
else
|
||||
#endif
|
||||
error = sock_get_timestamp(sk, argp);
|
||||
goto done;
|
||||
case SIOCGSTAMPNS: /* borrowed from IP */
|
||||
error = sock_get_timestampns(sk, argp);
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (compat)
|
||||
error = compat_sock_get_timestampns(sk, argp);
|
||||
else
|
||||
#endif
|
||||
error = sock_get_timestampns(sk, argp);
|
||||
goto done;
|
||||
case ATM_SETSC:
|
||||
printk(KERN_WARNING "ATM_SETSC is obsolete\n");
|
||||
if (net_ratelimit())
|
||||
printk(KERN_WARNING "ATM_SETSC is obsolete; used by %s:%d\n",
|
||||
current->comm, task_pid_nr(current));
|
||||
error = 0;
|
||||
goto done;
|
||||
case ATMSIGD_CTRL:
|
||||
@@ -99,12 +112,23 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||
* info uses kernel pointers as opaque references,
|
||||
* so the holder of the file descriptor can scribble
|
||||
* on the kernel... so we should make sure that we
|
||||
* have the same privledges that /proc/kcore needs
|
||||
* have the same privileges that /proc/kcore needs
|
||||
*/
|
||||
if (!capable(CAP_SYS_RAWIO)) {
|
||||
error = -EPERM;
|
||||
goto done;
|
||||
}
|
||||
#ifdef CONFIG_COMPAT
|
||||
/* WTF? I don't even want to _think_ about making this
|
||||
work for 32-bit userspace. TBH I don't really want
|
||||
to think about it at all. dwmw2. */
|
||||
if (compat) {
|
||||
if (net_ratelimit())
|
||||
printk(KERN_WARNING "32-bit task cannot be atmsigd\n");
|
||||
error = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
error = sigd_attach(vcc);
|
||||
if (!error)
|
||||
sock->state = SS_CONNECTED;
|
||||
@@ -155,8 +179,21 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||
if (error != -ENOIOCTLCMD)
|
||||
goto done;
|
||||
|
||||
error = atm_dev_ioctl(cmd, argp);
|
||||
error = atm_dev_ioctl(cmd, argp, compat);
|
||||
|
||||
done:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return do_vcc_ioctl(sock, cmd, arg, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return do_vcc_ioctl(sock, cmd, arg, 1);
|
||||
}
|
||||
#endif
|
||||
|
@@ -152,7 +152,7 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
|
||||
buff += 4;
|
||||
mesg->content.normal.flag = *buff & 0x01; /* 0x01 is topology change */
|
||||
|
||||
priv = (struct lec_priv *)dev->priv;
|
||||
priv = netdev_priv(dev);
|
||||
atm_force_charge(priv->lecd, skb2->truesize);
|
||||
sk = sk_atm(priv->lecd);
|
||||
skb_queue_tail(&sk->sk_receive_queue, skb2);
|
||||
@@ -218,7 +218,7 @@ static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc)
|
||||
|
||||
static int lec_open(struct net_device *dev)
|
||||
{
|
||||
struct lec_priv *priv = (struct lec_priv *)dev->priv;
|
||||
struct lec_priv *priv = netdev_priv(dev);
|
||||
|
||||
netif_start_queue(dev);
|
||||
memset(&priv->stats, 0, sizeof(struct net_device_stats));
|
||||
@@ -252,7 +252,7 @@ static void lec_tx_timeout(struct net_device *dev)
|
||||
static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct sk_buff *skb2;
|
||||
struct lec_priv *priv = (struct lec_priv *)dev->priv;
|
||||
struct lec_priv *priv = netdev_priv(dev);
|
||||
struct lecdatahdr_8023 *lec_h;
|
||||
struct atm_vcc *vcc;
|
||||
struct lec_arp_table *entry;
|
||||
@@ -373,19 +373,13 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) {
|
||||
pr_debug("%s:lec_start_xmit: queuing packet, ",
|
||||
dev->name);
|
||||
pr_debug("MAC address " MAC_FMT "\n",
|
||||
lec_h->h_dest[0], lec_h->h_dest[1],
|
||||
lec_h->h_dest[2], lec_h->h_dest[3],
|
||||
lec_h->h_dest[4], lec_h->h_dest[5]);
|
||||
pr_debug("MAC address %pM\n", lec_h->h_dest);
|
||||
skb_queue_tail(&entry->tx_wait, skb);
|
||||
} else {
|
||||
pr_debug
|
||||
("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ",
|
||||
dev->name);
|
||||
pr_debug("MAC address " MAC_FMT "\n",
|
||||
lec_h->h_dest[0], lec_h->h_dest[1],
|
||||
lec_h->h_dest[2], lec_h->h_dest[3],
|
||||
lec_h->h_dest[4], lec_h->h_dest[5]);
|
||||
pr_debug("MAC address %pM\n", lec_h->h_dest);
|
||||
priv->stats.tx_dropped++;
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
@@ -397,10 +391,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
|
||||
pr_debug("lec.c: emptying tx queue, ");
|
||||
pr_debug("MAC address " MAC_FMT "\n",
|
||||
lec_h->h_dest[0], lec_h->h_dest[1],
|
||||
lec_h->h_dest[2], lec_h->h_dest[3],
|
||||
lec_h->h_dest[4], lec_h->h_dest[5]);
|
||||
pr_debug("MAC address %pM\n", lec_h->h_dest);
|
||||
lec_send(vcc, skb2, priv);
|
||||
}
|
||||
|
||||
@@ -442,14 +433,14 @@ static int lec_close(struct net_device *dev)
|
||||
*/
|
||||
static struct net_device_stats *lec_get_stats(struct net_device *dev)
|
||||
{
|
||||
return &((struct lec_priv *)dev->priv)->stats;
|
||||
return &((struct lec_priv *)netdev_priv(dev))->stats;
|
||||
}
|
||||
|
||||
static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct net_device *dev = (struct net_device *)vcc->proto_data;
|
||||
struct lec_priv *priv = (struct lec_priv *)dev->priv;
|
||||
struct lec_priv *priv = netdev_priv(dev);
|
||||
struct atmlec_msg *mesg;
|
||||
struct lec_arp_table *entry;
|
||||
int i;
|
||||
@@ -539,15 +530,8 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
|
||||
{
|
||||
struct net_bridge_fdb_entry *f;
|
||||
|
||||
pr_debug
|
||||
("%s: bridge zeppelin asks about " MAC_FMT "\n",
|
||||
dev->name,
|
||||
mesg->content.proxy.mac_addr[0],
|
||||
mesg->content.proxy.mac_addr[1],
|
||||
mesg->content.proxy.mac_addr[2],
|
||||
mesg->content.proxy.mac_addr[3],
|
||||
mesg->content.proxy.mac_addr[4],
|
||||
mesg->content.proxy.mac_addr[5]);
|
||||
pr_debug("%s: bridge zeppelin asks about %pM\n",
|
||||
dev->name, mesg->content.proxy.mac_addr);
|
||||
|
||||
if (br_fdb_get_hook == NULL || dev->br_port == NULL)
|
||||
break;
|
||||
@@ -596,7 +580,7 @@ static void lec_atm_close(struct atm_vcc *vcc)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct net_device *dev = (struct net_device *)vcc->proto_data;
|
||||
struct lec_priv *priv = (struct lec_priv *)dev->priv;
|
||||
struct lec_priv *priv = netdev_priv(dev);
|
||||
|
||||
priv->lecd = NULL;
|
||||
/* Do something needful? */
|
||||
@@ -727,7 +711,7 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct net_device *dev = (struct net_device *)vcc->proto_data;
|
||||
struct lec_priv *priv = (struct lec_priv *)dev->priv;
|
||||
struct lec_priv *priv = netdev_priv(dev);
|
||||
|
||||
#if DUMP_PACKETS >0
|
||||
int i = 0;
|
||||
@@ -874,7 +858,7 @@ static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
|
||||
vpriv->old_pop = vcc->pop;
|
||||
vcc->user_back = vpriv;
|
||||
vcc->pop = lec_pop;
|
||||
lec_vcc_added(dev_lec[ioc_data.dev_num]->priv,
|
||||
lec_vcc_added(netdev_priv(dev_lec[ioc_data.dev_num]),
|
||||
&ioc_data, vcc, vcc->push);
|
||||
vcc->proto_data = dev_lec[ioc_data.dev_num];
|
||||
vcc->push = lec_push;
|
||||
@@ -886,7 +870,8 @@ static int lec_mcast_attach(struct atm_vcc *vcc, int arg)
|
||||
if (arg < 0 || arg >= MAX_LEC_ITF || !dev_lec[arg])
|
||||
return -EINVAL;
|
||||
vcc->proto_data = dev_lec[arg];
|
||||
return (lec_mcast_make((struct lec_priv *)dev_lec[arg]->priv, vcc));
|
||||
return lec_mcast_make((struct lec_priv *)netdev_priv(dev_lec[arg]),
|
||||
vcc);
|
||||
}
|
||||
|
||||
/* Initialize device. */
|
||||
@@ -928,11 +913,11 @@ static int lecd_attach(struct atm_vcc *vcc, int arg)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv = dev_lec[i]->priv;
|
||||
priv = netdev_priv(dev_lec[i]);
|
||||
priv->is_trdev = is_trdev;
|
||||
lec_init(dev_lec[i]);
|
||||
} else {
|
||||
priv = dev_lec[i]->priv;
|
||||
priv = netdev_priv(dev_lec[i]);
|
||||
if (priv->lecd)
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
@@ -1093,7 +1078,8 @@ static void *lec_itf_walk(struct lec_state *state, loff_t *l)
|
||||
void *v;
|
||||
|
||||
dev = state->dev ? state->dev : dev_lec[state->itf];
|
||||
v = (dev && dev->priv) ? lec_priv_walk(state, l, dev->priv) : NULL;
|
||||
v = (dev && netdev_priv(dev)) ?
|
||||
lec_priv_walk(state, l, netdev_priv(dev)) : NULL;
|
||||
if (!v && dev) {
|
||||
dev_put(dev);
|
||||
/* Partial state reset for the next time we get called */
|
||||
@@ -1255,7 +1241,7 @@ static void __exit lane_module_cleanup(void)
|
||||
|
||||
for (i = 0; i < MAX_LEC_ITF; i++) {
|
||||
if (dev_lec[i] != NULL) {
|
||||
priv = (struct lec_priv *)dev_lec[i]->priv;
|
||||
priv = netdev_priv(dev_lec[i]);
|
||||
unregister_netdev(dev_lec[i]);
|
||||
free_netdev(dev_lec[i]);
|
||||
dev_lec[i] = NULL;
|
||||
@@ -1279,7 +1265,7 @@ static int lane2_resolve(struct net_device *dev, const u8 *dst_mac, int force,
|
||||
u8 **tlvs, u32 *sizeoftlvs)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct lec_priv *priv = (struct lec_priv *)dev->priv;
|
||||
struct lec_priv *priv = netdev_priv(dev);
|
||||
struct lec_arp_table *table;
|
||||
struct sk_buff *skb;
|
||||
int retval;
|
||||
@@ -1326,7 +1312,7 @@ static int lane2_associate_req(struct net_device *dev, const u8 *lan_dst,
|
||||
{
|
||||
int retval;
|
||||
struct sk_buff *skb;
|
||||
struct lec_priv *priv = (struct lec_priv *)dev->priv;
|
||||
struct lec_priv *priv = netdev_priv(dev);
|
||||
|
||||
if (compare_ether_addr(lan_dst, dev->dev_addr))
|
||||
return (0); /* not our mac address */
|
||||
@@ -1363,7 +1349,7 @@ static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr,
|
||||
#if 0
|
||||
int i = 0;
|
||||
#endif
|
||||
struct lec_priv *priv = (struct lec_priv *)dev->priv;
|
||||
struct lec_priv *priv = netdev_priv(dev);
|
||||
#if 0 /*
|
||||
* Why have the TLVs in LE_ARP entries
|
||||
* since we do not use them? When you
|
||||
|
@@ -232,8 +232,8 @@ void atm_mpoa_disp_qos(struct seq_file *m)
|
||||
seq_printf(m, "IP address\n TX:max_pcr pcr min_pcr max_cdv max_sdu\n RX:max_pcr pcr min_pcr max_cdv max_sdu\n");
|
||||
|
||||
while (qos != NULL) {
|
||||
seq_printf(m, "%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n",
|
||||
NIPQUAD(qos->ipaddr),
|
||||
seq_printf(m, "%pI4\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n",
|
||||
&qos->ipaddr,
|
||||
qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu,
|
||||
qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu);
|
||||
qos = qos->next;
|
||||
@@ -341,8 +341,8 @@ static const char *mpoa_device_type_string(char type)
|
||||
}
|
||||
|
||||
/*
|
||||
* lec device calls this via its dev->priv->lane2_ops->associate_indicator()
|
||||
* when it sees a TLV in LE_ARP packet.
|
||||
* lec device calls this via its netdev_priv(dev)->lane2_ops
|
||||
* ->associate_indicator() when it sees a TLV in LE_ARP packet.
|
||||
* We fill in the pointer above when we see a LANE2 lec initializing
|
||||
* See LANE2 spec 3.1.5
|
||||
*
|
||||
@@ -595,8 +595,8 @@ static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg)
|
||||
if (in_entry != NULL) mpc->in_ops->put(in_entry);
|
||||
return -EINVAL;
|
||||
}
|
||||
printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n",
|
||||
mpc->dev->name, NIPQUAD(in_entry->ctrl_info.in_dst_ip));
|
||||
printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %pI4\n",
|
||||
mpc->dev->name, &in_entry->ctrl_info.in_dst_ip);
|
||||
in_entry->shortcut = vcc;
|
||||
mpc->in_ops->put(in_entry);
|
||||
} else {
|
||||
@@ -627,8 +627,8 @@ static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev)
|
||||
dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name);
|
||||
in_entry = mpc->in_ops->get_by_vcc(vcc, mpc);
|
||||
if (in_entry) {
|
||||
dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n",
|
||||
mpc->dev->name, NIPQUAD(in_entry->ctrl_info.in_dst_ip));
|
||||
dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %pI4\n",
|
||||
mpc->dev->name, &in_entry->ctrl_info.in_dst_ip);
|
||||
in_entry->shortcut = NULL;
|
||||
mpc->in_ops->put(in_entry);
|
||||
}
|
||||
@@ -785,7 +785,7 @@ static int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
|
||||
}
|
||||
|
||||
if (mpc->dev) { /* check if the lec is LANE2 capable */
|
||||
priv = (struct lec_priv *)mpc->dev->priv;
|
||||
priv = netdev_priv(mpc->dev);
|
||||
if (priv->lane_version < 2) {
|
||||
dev_put(mpc->dev);
|
||||
mpc->dev = NULL;
|
||||
@@ -845,7 +845,7 @@ static void mpoad_close(struct atm_vcc *vcc)
|
||||
|
||||
mpc->mpoad_vcc = NULL;
|
||||
if (mpc->dev) {
|
||||
struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv;
|
||||
struct lec_priv *priv = netdev_priv(mpc->dev);
|
||||
priv->lane2_ops->associate_indicator = NULL;
|
||||
stop_mpc(mpc);
|
||||
dev_put(mpc->dev);
|
||||
@@ -976,7 +976,7 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_REGISTER: /* a new lec device was allocated */
|
||||
priv = (struct lec_priv *)dev->priv;
|
||||
priv = netdev_priv(dev);
|
||||
if (priv->lane_version < 2)
|
||||
break;
|
||||
priv->lane2_ops->associate_indicator = lane2_assoc_ind;
|
||||
@@ -1098,7 +1098,8 @@ static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_clien
|
||||
entry->shortcut = eg_entry->shortcut;
|
||||
}
|
||||
if(entry->shortcut){
|
||||
dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(dst_ip));
|
||||
dprintk("mpoa: (%s) using egress SVC to reach %pI4\n",
|
||||
client->dev->name, &dst_ip);
|
||||
client->eg_ops->put(eg_entry);
|
||||
return;
|
||||
}
|
||||
@@ -1123,7 +1124,8 @@ static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc)
|
||||
__be32 dst_ip = msg->content.in_info.in_dst_ip;
|
||||
in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc);
|
||||
|
||||
dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(dst_ip));
|
||||
dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %pI4\n",
|
||||
mpc->dev->name, &dst_ip);
|
||||
ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc->dev->name, entry);
|
||||
if(entry == NULL){
|
||||
printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc->dev->name);
|
||||
@@ -1171,14 +1173,14 @@ static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
|
||||
in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
|
||||
|
||||
if(entry == NULL){
|
||||
printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ", mpc->dev->name);
|
||||
printk("ip = %u.%u.%u.%u\n", NIPQUAD(dst_ip));
|
||||
printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ip = %pI4\n",
|
||||
mpc->dev->name, &dst_ip);
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" ,
|
||||
mpc->dev->name, NIPQUAD(dst_ip));
|
||||
dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %pI4\n",
|
||||
mpc->dev->name, &dst_ip);
|
||||
write_lock_bh(&mpc->ingress_lock);
|
||||
mpc->in_ops->remove_entry(entry, mpc);
|
||||
write_unlock_bh(&mpc->ingress_lock);
|
||||
@@ -1322,7 +1324,7 @@ static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *m
|
||||
dprintk("\n");
|
||||
|
||||
if (mpc->dev) {
|
||||
priv = (struct lec_priv *)mpc->dev->priv;
|
||||
priv = netdev_priv(mpc->dev);
|
||||
retval = priv->lane2_ops->associate_req(mpc->dev, mpc->dev->dev_addr, tlv, sizeof(tlv));
|
||||
if (retval == 0)
|
||||
printk("mpoa: (%s) MPOA device type TLV association failed\n", mpc->dev->name);
|
||||
@@ -1472,7 +1474,7 @@ static void __exit atm_mpoa_cleanup(void)
|
||||
tmp = mpc->next;
|
||||
if (mpc->dev != NULL) {
|
||||
stop_mpc(mpc);
|
||||
priv = (struct lec_priv *)mpc->dev->priv;
|
||||
priv = netdev_priv(mpc->dev);
|
||||
if (priv->lane2_ops != NULL)
|
||||
priv->lane2_ops->associate_indicator = NULL;
|
||||
}
|
||||
|
@@ -94,7 +94,7 @@ static in_cache_entry *in_cache_add_entry(__be32 dst_ip,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", NIPQUAD(dst_ip));
|
||||
dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %pI4\n", &dst_ip);
|
||||
|
||||
atomic_set(&entry->use, 1);
|
||||
dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n");
|
||||
@@ -150,7 +150,8 @@ static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc)
|
||||
|
||||
if( entry->count > mpc->parameters.mpc_p1 &&
|
||||
entry->entry_state == INGRESS_INVALID){
|
||||
dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %u.%u.%u.%u, sending MPOA res req\n", mpc->dev->name, NIPQUAD(entry->ctrl_info.in_dst_ip));
|
||||
dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %pI4, sending MPOA res req\n",
|
||||
mpc->dev->name, &entry->ctrl_info.in_dst_ip);
|
||||
entry->entry_state = INGRESS_RESOLVING;
|
||||
msg.type = SND_MPOA_RES_RQST;
|
||||
memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN );
|
||||
@@ -184,7 +185,8 @@ static void in_cache_remove_entry(in_cache_entry *entry,
|
||||
struct k_message msg;
|
||||
|
||||
vcc = entry->shortcut;
|
||||
dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",NIPQUAD(entry->ctrl_info.in_dst_ip));
|
||||
dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %pI4\n",
|
||||
&entry->ctrl_info.in_dst_ip);
|
||||
|
||||
if (entry->prev != NULL)
|
||||
entry->prev->next = entry->next;
|
||||
@@ -228,7 +230,8 @@ static void clear_count_and_expired(struct mpoa_client *client)
|
||||
next_entry = entry->next;
|
||||
if((now.tv_sec - entry->tv.tv_sec)
|
||||
> entry->ctrl_info.holding_time){
|
||||
dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %u.%u.%u.%u\n", NIPQUAD(entry->ctrl_info.in_dst_ip));
|
||||
dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %pI4\n",
|
||||
&entry->ctrl_info.in_dst_ip);
|
||||
client->in_ops->remove_entry(entry, client);
|
||||
}
|
||||
entry = next_entry;
|
||||
@@ -453,7 +456,8 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_cli
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %u.%u.%u.%u, this should be our IP\n", NIPQUAD(msg->content.eg_info.eg_dst_ip));
|
||||
dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %pI4, this should be our IP\n",
|
||||
&msg->content.eg_info.eg_dst_ip);
|
||||
|
||||
atomic_set(&entry->use, 1);
|
||||
dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n");
|
||||
@@ -469,8 +473,8 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_cli
|
||||
do_gettimeofday(&(entry->tv));
|
||||
entry->entry_state = EGRESS_RESOLVED;
|
||||
dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id));
|
||||
dprintk("mpoa: mpoa_caches.c: mps_ip = %u.%u.%u.%u\n",
|
||||
NIPQUAD(entry->ctrl_info.mps_ip));
|
||||
dprintk("mpoa: mpoa_caches.c: mps_ip = %pI4\n",
|
||||
&entry->ctrl_info.mps_ip);
|
||||
atomic_inc(&entry->use);
|
||||
|
||||
write_unlock_irq(&client->egress_lock);
|
||||
|
@@ -113,6 +113,9 @@ static const struct proto_ops pvc_proto_ops = {
|
||||
.getname = pvc_getname,
|
||||
.poll = vcc_poll,
|
||||
.ioctl = vcc_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = vcc_compat_ioctl,
|
||||
#endif
|
||||
.listen = sock_no_listen,
|
||||
.shutdown = pvc_shutdown,
|
||||
.setsockopt = pvc_setsockopt,
|
||||
|
@@ -195,20 +195,39 @@ static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, in
|
||||
}
|
||||
|
||||
|
||||
int atm_dev_ioctl(unsigned int cmd, void __user *arg)
|
||||
int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
|
||||
{
|
||||
void __user *buf;
|
||||
int error, len, number, size = 0;
|
||||
struct atm_dev *dev;
|
||||
struct list_head *p;
|
||||
int *tmp_buf, *tmp_p;
|
||||
struct atm_iobuf __user *iobuf = arg;
|
||||
struct atmif_sioc __user *sioc = arg;
|
||||
int __user *sioc_len;
|
||||
int __user *iobuf_len;
|
||||
|
||||
#ifndef CONFIG_COMPAT
|
||||
compat = 0; /* Just so the compiler _knows_ */
|
||||
#endif
|
||||
|
||||
switch (cmd) {
|
||||
case ATM_GETNAMES:
|
||||
if (get_user(buf, &iobuf->buffer))
|
||||
return -EFAULT;
|
||||
if (get_user(len, &iobuf->length))
|
||||
|
||||
if (compat) {
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct compat_atm_iobuf __user *ciobuf = arg;
|
||||
compat_uptr_t cbuf;
|
||||
iobuf_len = &ciobuf->length;
|
||||
if (get_user(cbuf, &ciobuf->buffer))
|
||||
return -EFAULT;
|
||||
buf = compat_ptr(cbuf);
|
||||
#endif
|
||||
} else {
|
||||
struct atm_iobuf __user *iobuf = arg;
|
||||
iobuf_len = &iobuf->length;
|
||||
if (get_user(buf, &iobuf->buffer))
|
||||
return -EFAULT;
|
||||
}
|
||||
if (get_user(len, iobuf_len))
|
||||
return -EFAULT;
|
||||
mutex_lock(&atm_dev_mutex);
|
||||
list_for_each(p, &atm_devs)
|
||||
@@ -229,7 +248,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
|
||||
}
|
||||
mutex_unlock(&atm_dev_mutex);
|
||||
error = ((copy_to_user(buf, tmp_buf, size)) ||
|
||||
put_user(size, &iobuf->length))
|
||||
put_user(size, iobuf_len))
|
||||
? -EFAULT : 0;
|
||||
kfree(tmp_buf);
|
||||
return error;
|
||||
@@ -237,13 +256,32 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (get_user(buf, &sioc->arg))
|
||||
return -EFAULT;
|
||||
if (get_user(len, &sioc->length))
|
||||
return -EFAULT;
|
||||
if (get_user(number, &sioc->number))
|
||||
return -EFAULT;
|
||||
if (compat) {
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct compat_atmif_sioc __user *csioc = arg;
|
||||
compat_uptr_t carg;
|
||||
|
||||
sioc_len = &csioc->length;
|
||||
if (get_user(carg, &csioc->arg))
|
||||
return -EFAULT;
|
||||
buf = compat_ptr(carg);
|
||||
|
||||
if (get_user(len, &csioc->length))
|
||||
return -EFAULT;
|
||||
if (get_user(number, &csioc->number))
|
||||
return -EFAULT;
|
||||
#endif
|
||||
} else {
|
||||
struct atmif_sioc __user *sioc = arg;
|
||||
|
||||
sioc_len = &sioc->length;
|
||||
if (get_user(buf, &sioc->arg))
|
||||
return -EFAULT;
|
||||
if (get_user(len, &sioc->length))
|
||||
return -EFAULT;
|
||||
if (get_user(number, &sioc->number))
|
||||
return -EFAULT;
|
||||
}
|
||||
if (!(dev = try_then_request_module(atm_dev_lookup(number),
|
||||
"atm-device-%d", number)))
|
||||
return -ENODEV;
|
||||
@@ -358,7 +396,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
|
||||
size = error;
|
||||
/* may return 0, but later on size == 0 means "don't
|
||||
write the length" */
|
||||
error = put_user(size, &sioc->length)
|
||||
error = put_user(size, sioc_len)
|
||||
? -EFAULT : 0;
|
||||
goto done;
|
||||
case ATM_SETLOOP:
|
||||
@@ -380,11 +418,21 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
if (!dev->ops->ioctl) {
|
||||
error = -EINVAL;
|
||||
goto done;
|
||||
if (compat) {
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (!dev->ops->compat_ioctl) {
|
||||
error = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
size = dev->ops->compat_ioctl(dev, cmd, buf);
|
||||
#endif
|
||||
} else {
|
||||
if (!dev->ops->ioctl) {
|
||||
error = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
size = dev->ops->ioctl(dev, cmd, buf);
|
||||
}
|
||||
size = dev->ops->ioctl(dev, cmd, buf);
|
||||
if (size < 0) {
|
||||
error = (size == -ENOIOCTLCMD ? -EINVAL : size);
|
||||
goto done;
|
||||
@@ -392,7 +440,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
|
||||
}
|
||||
|
||||
if (size)
|
||||
error = put_user(size, &sioc->length)
|
||||
error = put_user(size, sioc_len)
|
||||
? -EFAULT : 0;
|
||||
else
|
||||
error = 0;
|
||||
|
@@ -13,7 +13,7 @@
|
||||
extern struct list_head atm_devs;
|
||||
extern struct mutex atm_dev_mutex;
|
||||
|
||||
int atm_dev_ioctl(unsigned int cmd, void __user *arg);
|
||||
int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat);
|
||||
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
@@ -608,6 +608,22 @@ static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static int svc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
/* The definition of ATM_ADDPARTY uses the size of struct atm_iobuf.
|
||||
But actually it takes a struct sockaddr_atmsvc, which doesn't need
|
||||
compat handling. So all we have to do is fix up cmd... */
|
||||
if (cmd == COMPAT_ATM_ADDPARTY)
|
||||
cmd = ATM_ADDPARTY;
|
||||
|
||||
if (cmd == ATM_ADDPARTY || cmd == ATM_DROPPARTY)
|
||||
return svc_ioctl(sock, cmd, arg);
|
||||
else
|
||||
return vcc_compat_ioctl(sock, cmd, arg);
|
||||
}
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
static const struct proto_ops svc_proto_ops = {
|
||||
.family = PF_ATMSVC,
|
||||
.owner = THIS_MODULE,
|
||||
@@ -620,6 +636,9 @@ static const struct proto_ops svc_proto_ops = {
|
||||
.getname = svc_getname,
|
||||
.poll = vcc_poll,
|
||||
.ioctl = svc_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = svc_compat_ioctl,
|
||||
#endif
|
||||
.listen = svc_listen,
|
||||
.shutdown = svc_shutdown,
|
||||
.setsockopt = svc_setsockopt,
|
||||
|
@@ -200,19 +200,15 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
skb_reset_transport_header(skb);
|
||||
|
||||
if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
|
||||
goto free;
|
||||
|
||||
/*
|
||||
* Parse the address header.
|
||||
*/
|
||||
|
||||
if (ax25_addr_parse(skb->data, skb->len, &src, &dest, &dp, &type, &dama) == NULL) {
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
if (ax25_addr_parse(skb->data, skb->len, &src, &dest, &dp, &type, &dama) == NULL)
|
||||
goto free;
|
||||
|
||||
/*
|
||||
* Ours perhaps ?
|
||||
@@ -239,10 +235,8 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
ax25_send_to_raw(&dest, skb, skb->data[1]);
|
||||
|
||||
if (!mine && ax25cmp(&dest, (ax25_address *)dev->broadcast) != 0) {
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
if (!mine && ax25cmp(&dest, (ax25_address *)dev->broadcast) != 0)
|
||||
goto free;
|
||||
|
||||
/* Now we are pointing at the pid byte */
|
||||
switch (skb->data[1]) {
|
||||
@@ -301,10 +295,8 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
* If not, should we DM the incoming frame (except DMs) or
|
||||
* silently ignore them. For now we stay quiet.
|
||||
*/
|
||||
if (ax25_dev->values[AX25_VALUES_CONMODE] == 0) {
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
if (ax25_dev->values[AX25_VALUES_CONMODE] == 0)
|
||||
goto free;
|
||||
|
||||
/* LAPB */
|
||||
|
||||
@@ -339,8 +331,7 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
if ((*skb->data & ~AX25_PF) != AX25_DM && mine)
|
||||
ax25_return_dm(dev, &src, &dest, &dp);
|
||||
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
goto free;
|
||||
}
|
||||
|
||||
/* b) received SABM(E) */
|
||||
@@ -372,15 +363,12 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
sk->sk_ack_backlog++;
|
||||
bh_unlock_sock(sk);
|
||||
} else {
|
||||
if (!mine) {
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
if (!mine)
|
||||
goto free;
|
||||
|
||||
if ((ax25 = ax25_create_cb()) == NULL) {
|
||||
ax25_return_dm(dev, &src, &dest, &dp);
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
goto free;
|
||||
}
|
||||
|
||||
ax25_fillin_cb(ax25, ax25_dev);
|
||||
@@ -436,9 +424,10 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
if (!sock_flag(sk, SOCK_DEAD))
|
||||
sk->sk_data_ready(sk, skb->len);
|
||||
sock_put(sk);
|
||||
} else
|
||||
} else {
|
||||
free:
|
||||
kfree_skb(skb);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -24,7 +24,9 @@ static int min_idle[1], max_idle[] = {65535000};
|
||||
static int min_n2[] = {1}, max_n2[] = {31};
|
||||
static int min_paclen[] = {1}, max_paclen[] = {512};
|
||||
static int min_proto[1], max_proto[] = { AX25_PROTO_MAX };
|
||||
#ifdef CONFIG_AX25_DAMA_SLAVE
|
||||
static int min_ds_timeout[1], max_ds_timeout[] = {65535000};
|
||||
#endif
|
||||
|
||||
static struct ctl_table_header *ax25_table_header;
|
||||
|
||||
@@ -43,8 +45,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "ip_default_mode",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_ipdefmode,
|
||||
.extra2 = &max_ipdefmode
|
||||
},
|
||||
@@ -53,8 +55,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "ax25_default_mode",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_axdefmode,
|
||||
.extra2 = &max_axdefmode
|
||||
},
|
||||
@@ -63,8 +65,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "backoff_type",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_backoff,
|
||||
.extra2 = &max_backoff
|
||||
},
|
||||
@@ -73,8 +75,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "connect_mode",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_conmode,
|
||||
.extra2 = &max_conmode
|
||||
},
|
||||
@@ -83,8 +85,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "standard_window_size",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_window,
|
||||
.extra2 = &max_window
|
||||
},
|
||||
@@ -93,8 +95,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "extended_window_size",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_ewindow,
|
||||
.extra2 = &max_ewindow
|
||||
},
|
||||
@@ -103,8 +105,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "t1_timeout",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_t1,
|
||||
.extra2 = &max_t1
|
||||
},
|
||||
@@ -113,8 +115,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "t2_timeout",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_t2,
|
||||
.extra2 = &max_t2
|
||||
},
|
||||
@@ -123,8 +125,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "t3_timeout",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_t3,
|
||||
.extra2 = &max_t3
|
||||
},
|
||||
@@ -133,8 +135,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "idle_timeout",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_idle,
|
||||
.extra2 = &max_idle
|
||||
},
|
||||
@@ -143,8 +145,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "maximum_retry_count",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_n2,
|
||||
.extra2 = &max_n2
|
||||
},
|
||||
@@ -153,8 +155,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "maximum_packet_length",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_paclen,
|
||||
.extra2 = &max_paclen
|
||||
},
|
||||
@@ -163,8 +165,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "protocol",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_proto,
|
||||
.extra2 = &max_proto
|
||||
},
|
||||
@@ -174,8 +176,8 @@ static const ctl_table ax25_param_table[] = {
|
||||
.procname = "dama_slave_timeout",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.strategy = sysctl_intvec,
|
||||
.extra1 = &min_ds_timeout,
|
||||
.extra2 = &max_ds_timeout
|
||||
},
|
||||
|
@@ -41,18 +41,14 @@
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
|
||||
#ifndef CONFIG_BT_SOCK_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "2.13"
|
||||
#define VERSION "2.14"
|
||||
|
||||
/* Bluetooth sockets */
|
||||
#define BT_MAX_PROTO 8
|
||||
static struct net_proto_family *bt_proto[BT_MAX_PROTO];
|
||||
static DEFINE_RWLOCK(bt_proto_lock);
|
||||
|
||||
static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
|
||||
static const char *bt_key_strings[BT_MAX_PROTO] = {
|
||||
"sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
|
||||
@@ -65,6 +61,7 @@ static const char *bt_key_strings[BT_MAX_PROTO] = {
|
||||
"sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
|
||||
};
|
||||
|
||||
static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
|
||||
static const char *bt_slock_key_strings[BT_MAX_PROTO] = {
|
||||
"slock-AF_BLUETOOTH-BTPROTO_L2CAP",
|
||||
"slock-AF_BLUETOOTH-BTPROTO_HCI",
|
||||
@@ -75,7 +72,25 @@ static const char *bt_slock_key_strings[BT_MAX_PROTO] = {
|
||||
"slock-AF_BLUETOOTH-BTPROTO_HIDP",
|
||||
"slock-AF_BLUETOOTH-BTPROTO_AVDTP",
|
||||
};
|
||||
static DEFINE_RWLOCK(bt_proto_lock);
|
||||
|
||||
static inline void bt_sock_reclassify_lock(struct socket *sock, int proto)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
|
||||
if (!sk)
|
||||
return;
|
||||
|
||||
BUG_ON(sock_owned_by_user(sk));
|
||||
|
||||
sock_lock_init_class_and_name(sk,
|
||||
bt_slock_key_strings[proto], &bt_slock_key[proto],
|
||||
bt_key_strings[proto], &bt_lock_key[proto]);
|
||||
}
|
||||
#else
|
||||
static inline void bt_sock_reclassify_lock(struct socket *sock, int proto)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
int bt_sock_register(int proto, struct net_proto_family *ops)
|
||||
{
|
||||
@@ -117,21 +132,6 @@ int bt_sock_unregister(int proto)
|
||||
}
|
||||
EXPORT_SYMBOL(bt_sock_unregister);
|
||||
|
||||
static void bt_reclassify_sock_lock(struct socket *sock, int proto)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
|
||||
if (!sk)
|
||||
return;
|
||||
BUG_ON(sock_owned_by_user(sk));
|
||||
|
||||
sock_lock_init_class_and_name(sk,
|
||||
bt_slock_key_strings[proto],
|
||||
&bt_slock_key[proto],
|
||||
bt_key_strings[proto],
|
||||
&bt_lock_key[proto]);
|
||||
}
|
||||
|
||||
static int bt_sock_create(struct net *net, struct socket *sock, int proto)
|
||||
{
|
||||
int err;
|
||||
@@ -151,7 +151,7 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto)
|
||||
|
||||
if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
|
||||
err = bt_proto[proto]->create(net, sock, proto);
|
||||
bt_reclassify_sock_lock(sock, proto);
|
||||
bt_sock_reclassify_lock(sock, proto);
|
||||
module_put(bt_proto[proto]->owner);
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
size_t copied;
|
||||
int err;
|
||||
|
||||
BT_DBG("sock %p sk %p len %d", sock, sk, len);
|
||||
BT_DBG("sock %p sk %p len %zu", sock, sk, len);
|
||||
|
||||
if (flags & (MSG_OOB))
|
||||
return -EOPNOTSUPP;
|
||||
|
@@ -161,7 +161,7 @@ struct bnep_session {
|
||||
struct msghdr msg;
|
||||
|
||||
struct bnep_proto_filter proto_filter[BNEP_MAX_PROTO_FILTERS];
|
||||
u64 mc_filter;
|
||||
unsigned long long mc_filter;
|
||||
|
||||
struct socket *sock;
|
||||
struct net_device *dev;
|
||||
|
@@ -52,11 +52,6 @@
|
||||
|
||||
#include "bnep.h"
|
||||
|
||||
#ifndef CONFIG_BT_BNEP_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "1.3"
|
||||
|
||||
static int compress_src = 1;
|
||||
@@ -311,7 +306,6 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
|
||||
struct sk_buff *nskb;
|
||||
u8 type;
|
||||
|
||||
dev->last_rx = jiffies;
|
||||
s->stats.rx_bytes += skb->len;
|
||||
|
||||
type = *(u8 *) skb->data; skb_pull(skb, 1);
|
||||
@@ -566,7 +560,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
s = dev->priv;
|
||||
s = netdev_priv(dev);
|
||||
|
||||
/* This is rx header therefore addresses are swapped.
|
||||
* ie eh.h_dest is our local address. */
|
||||
|
@@ -41,11 +41,6 @@
|
||||
|
||||
#include "bnep.h"
|
||||
|
||||
#ifndef CONFIG_BT_BNEP_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG( A... )
|
||||
#endif
|
||||
|
||||
#define BNEP_TX_QUEUE_LEN 20
|
||||
|
||||
static int bnep_net_open(struct net_device *dev)
|
||||
@@ -62,14 +57,14 @@ static int bnep_net_close(struct net_device *dev)
|
||||
|
||||
static struct net_device_stats *bnep_net_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct bnep_session *s = dev->priv;
|
||||
struct bnep_session *s = netdev_priv(dev);
|
||||
return &s->stats;
|
||||
}
|
||||
|
||||
static void bnep_net_set_mc_list(struct net_device *dev)
|
||||
{
|
||||
#ifdef CONFIG_BT_BNEP_MC_FILTER
|
||||
struct bnep_session *s = dev->priv;
|
||||
struct bnep_session *s = netdev_priv(dev);
|
||||
struct sock *sk = s->sock->sk;
|
||||
struct bnep_set_filter_req *r;
|
||||
struct sk_buff *skb;
|
||||
@@ -183,7 +178,7 @@ static inline int bnep_net_proto_filter(struct sk_buff *skb, struct bnep_session
|
||||
|
||||
static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct bnep_session *s = dev->priv;
|
||||
struct bnep_session *s = netdev_priv(dev);
|
||||
struct sock *sk = s->sock->sk;
|
||||
|
||||
BT_DBG("skb %p, dev %p", skb, dev);
|
||||
|
@@ -46,11 +46,6 @@
|
||||
|
||||
#include "bnep.h"
|
||||
|
||||
#ifndef CONFIG_BT_BNEP_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG( A... )
|
||||
#endif
|
||||
|
||||
static int bnep_sock_release(struct socket *sock)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
|
@@ -42,11 +42,6 @@
|
||||
|
||||
#include "cmtp.h"
|
||||
|
||||
#ifndef CONFIG_BT_CMTP_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define CAPI_INTEROPERABILITY 0x20
|
||||
|
||||
#define CAPI_INTEROPERABILITY_REQ CAPICMD(CAPI_INTEROPERABILITY, CAPI_REQ)
|
||||
|
@@ -44,11 +44,6 @@
|
||||
|
||||
#include "cmtp.h"
|
||||
|
||||
#ifndef CONFIG_BT_CMTP_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "1.0"
|
||||
|
||||
static DECLARE_RWSEM(cmtp_session_sem);
|
||||
|
@@ -43,11 +43,6 @@
|
||||
|
||||
#include "cmtp.h"
|
||||
|
||||
#ifndef CONFIG_BT_CMTP_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
static int cmtp_sock_release(struct socket *sock)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
|
@@ -45,11 +45,6 @@
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#ifndef CONFIG_BT_HCI_CORE_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
void hci_acl_connect(struct hci_conn *conn)
|
||||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
|
@@ -48,11 +48,6 @@
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#ifndef CONFIG_BT_HCI_CORE_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
static void hci_cmd_task(unsigned long arg);
|
||||
static void hci_rx_task(unsigned long arg);
|
||||
static void hci_tx_task(unsigned long arg);
|
||||
@@ -205,7 +200,7 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
|
||||
/* Mandatory initialization */
|
||||
|
||||
/* Reset */
|
||||
if (test_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks))
|
||||
if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks))
|
||||
hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
|
||||
|
||||
/* Read Local Supported Features */
|
||||
@@ -290,7 +285,7 @@ static void hci_linkpol_req(struct hci_dev *hdev, unsigned long opt)
|
||||
{
|
||||
__le16 policy = cpu_to_le16(opt);
|
||||
|
||||
BT_DBG("%s %x", hdev->name, opt);
|
||||
BT_DBG("%s %x", hdev->name, policy);
|
||||
|
||||
/* Default link policy */
|
||||
hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy);
|
||||
@@ -756,7 +751,7 @@ int hci_get_dev_list(void __user *arg)
|
||||
|
||||
size = sizeof(*dl) + dev_num * sizeof(*dr);
|
||||
|
||||
if (!(dl = kmalloc(size, GFP_KERNEL)))
|
||||
if (!(dl = kzalloc(size, GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
|
||||
dr = dl->dev_req;
|
||||
|
@@ -45,11 +45,6 @@
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#ifndef CONFIG_BT_HCI_CORE_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
/* Handle HCI Event packets */
|
||||
|
||||
static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
@@ -49,11 +49,6 @@
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#ifndef CONFIG_BT_HCI_SOCK_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
/* ----- HCI socket interface ----- */
|
||||
|
||||
static inline int hci_test_bit(int nr, void *addr)
|
||||
|
@@ -6,11 +6,6 @@
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#ifndef CONFIG_BT_HCI_CORE_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
struct class *bt_class = NULL;
|
||||
EXPORT_SYMBOL_GPL(bt_class);
|
||||
|
||||
@@ -113,8 +108,7 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
|
||||
conn->dev.class = bt_class;
|
||||
conn->dev.parent = &hdev->dev;
|
||||
|
||||
snprintf(conn->dev.bus_id, BUS_ID_SIZE, "%s:%d",
|
||||
hdev->name, conn->handle);
|
||||
dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
|
||||
|
||||
dev_set_drvdata(&conn->dev, conn);
|
||||
|
||||
@@ -132,7 +126,7 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
|
||||
*/
|
||||
static int __match_tty(struct device *dev, void *data)
|
||||
{
|
||||
return !strncmp(dev->bus_id, "rfcomm", 6);
|
||||
return !strncmp(dev_name(dev), "rfcomm", 6);
|
||||
}
|
||||
|
||||
static void del_conn(struct work_struct *work)
|
||||
@@ -421,7 +415,7 @@ int hci_register_sysfs(struct hci_dev *hdev)
|
||||
dev->class = bt_class;
|
||||
dev->parent = hdev->parent;
|
||||
|
||||
strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE);
|
||||
dev_set_name(dev, "%s", hdev->name);
|
||||
|
||||
dev_set_drvdata(dev, hdev);
|
||||
|
||||
|
@@ -47,11 +47,6 @@
|
||||
|
||||
#include "hidp.h"
|
||||
|
||||
#ifndef CONFIG_BT_HIDP_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "1.2"
|
||||
|
||||
static DECLARE_RWSEM(hidp_session_sem);
|
||||
|
@@ -39,11 +39,6 @@
|
||||
|
||||
#include "hidp.h"
|
||||
|
||||
#ifndef CONFIG_BT_HIDP_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
static int hidp_sock_release(struct socket *sock)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
|
@@ -50,11 +50,6 @@
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
#include <net/bluetooth/l2cap.h>
|
||||
|
||||
#ifndef CONFIG_BT_L2CAP_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "2.11"
|
||||
|
||||
static u32 l2cap_feat_mask = 0x0000;
|
||||
|
@@ -46,11 +46,6 @@
|
||||
#include <net/bluetooth/l2cap.h>
|
||||
#include <net/bluetooth/rfcomm.h>
|
||||
|
||||
#ifndef CONFIG_BT_RFCOMM_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "1.10"
|
||||
|
||||
static int disable_cfc = 0;
|
||||
|
@@ -50,11 +50,6 @@
|
||||
#include <net/bluetooth/l2cap.h>
|
||||
#include <net/bluetooth/rfcomm.h>
|
||||
|
||||
#ifndef CONFIG_BT_RFCOMM_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
static const struct proto_ops rfcomm_sock_ops;
|
||||
|
||||
static struct bt_sock_list rfcomm_sk_list = {
|
||||
@@ -644,7 +639,7 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
|
||||
msg->msg_namelen = 0;
|
||||
|
||||
BT_DBG("sk %p size %d", sk, size);
|
||||
BT_DBG("sk %p size %zu", sk, size);
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
@@ -792,7 +787,7 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
|
||||
|
||||
static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
struct sock *sk __maybe_unused = sock->sk;
|
||||
int err;
|
||||
|
||||
BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
|
||||
|
@@ -39,11 +39,6 @@
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
#include <net/bluetooth/rfcomm.h>
|
||||
|
||||
#ifndef CONFIG_BT_RFCOMM_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define RFCOMM_TTY_MAGIC 0x6d02 /* magic number for rfcomm struct */
|
||||
#define RFCOMM_TTY_PORTS RFCOMM_MAX_DEV /* whole lotta rfcomm devices */
|
||||
#define RFCOMM_TTY_MAJOR 216 /* device node major id of the usb/bluetooth.c driver */
|
||||
@@ -58,7 +53,7 @@ struct rfcomm_dev {
|
||||
char name[12];
|
||||
int id;
|
||||
unsigned long flags;
|
||||
int opened;
|
||||
atomic_t opened;
|
||||
int err;
|
||||
|
||||
bdaddr_t src;
|
||||
@@ -261,6 +256,8 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
|
||||
dev->flags = req->flags &
|
||||
((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
|
||||
|
||||
atomic_set(&dev->opened, 0);
|
||||
|
||||
init_waitqueue_head(&dev->wait);
|
||||
tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev);
|
||||
|
||||
@@ -301,18 +298,15 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
|
||||
out:
|
||||
write_unlock_bh(&rfcomm_dev_lock);
|
||||
|
||||
if (err < 0) {
|
||||
kfree(dev);
|
||||
return err;
|
||||
}
|
||||
if (err < 0)
|
||||
goto free;
|
||||
|
||||
dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL);
|
||||
|
||||
if (IS_ERR(dev->tty_dev)) {
|
||||
err = PTR_ERR(dev->tty_dev);
|
||||
list_del(&dev->list);
|
||||
kfree(dev);
|
||||
return err;
|
||||
goto free;
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev->tty_dev, dev);
|
||||
@@ -324,16 +318,20 @@ out:
|
||||
BT_ERR("Failed to create channel attribute");
|
||||
|
||||
return dev->id;
|
||||
|
||||
free:
|
||||
kfree(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void rfcomm_dev_del(struct rfcomm_dev *dev)
|
||||
{
|
||||
BT_DBG("dev %p", dev);
|
||||
|
||||
if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
|
||||
BUG_ON(1);
|
||||
else
|
||||
set_bit(RFCOMM_TTY_RELEASED, &dev->flags);
|
||||
BUG_ON(test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags));
|
||||
|
||||
if (atomic_read(&dev->opened) > 0)
|
||||
return;
|
||||
|
||||
write_lock_bh(&rfcomm_dev_lock);
|
||||
list_del_init(&dev->list);
|
||||
@@ -689,9 +687,10 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst), dev->channel, dev->opened);
|
||||
BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst),
|
||||
dev->channel, atomic_read(&dev->opened));
|
||||
|
||||
if (dev->opened++ != 0)
|
||||
if (atomic_inc_return(&dev->opened) > 1)
|
||||
return 0;
|
||||
|
||||
dlc = dev->dlc;
|
||||
@@ -747,9 +746,10 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, dev->opened);
|
||||
BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc,
|
||||
atomic_read(&dev->opened));
|
||||
|
||||
if (--dev->opened == 0) {
|
||||
if (atomic_dec_and_test(&dev->opened)) {
|
||||
if (dev->tty_dev->parent)
|
||||
device_move(dev->tty_dev, NULL);
|
||||
|
||||
@@ -763,6 +763,14 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
|
||||
tty->driver_data = NULL;
|
||||
dev->tty = NULL;
|
||||
rfcomm_dlc_unlock(dev->dlc);
|
||||
|
||||
if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
|
||||
write_lock_bh(&rfcomm_dev_lock);
|
||||
list_del_init(&dev->list);
|
||||
write_unlock_bh(&rfcomm_dev_lock);
|
||||
|
||||
rfcomm_dev_put(dev);
|
||||
}
|
||||
}
|
||||
|
||||
rfcomm_dev_put(dev);
|
||||
|
@@ -48,11 +48,6 @@
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
#include <net/bluetooth/sco.h>
|
||||
|
||||
#ifndef CONFIG_BT_SCO_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "0.6"
|
||||
|
||||
static int disable_esco = 0;
|
||||
|
@@ -147,7 +147,7 @@ static int br_set_tx_csum(struct net_device *dev, u32 data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ethtool_ops br_ethtool_ops = {
|
||||
static const struct ethtool_ops br_ethtool_ops = {
|
||||
.get_drvinfo = br_getinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_tx_csum = ethtool_op_get_tx_csum,
|
||||
@@ -160,21 +160,25 @@ static struct ethtool_ops br_ethtool_ops = {
|
||||
.get_flags = ethtool_op_get_flags,
|
||||
};
|
||||
|
||||
static const struct net_device_ops br_netdev_ops = {
|
||||
.ndo_open = br_dev_open,
|
||||
.ndo_stop = br_dev_stop,
|
||||
.ndo_start_xmit = br_dev_xmit,
|
||||
.ndo_set_mac_address = br_set_mac_address,
|
||||
.ndo_set_multicast_list = br_dev_set_multicast_list,
|
||||
.ndo_change_mtu = br_change_mtu,
|
||||
.ndo_do_ioctl = br_dev_ioctl,
|
||||
};
|
||||
|
||||
void br_dev_setup(struct net_device *dev)
|
||||
{
|
||||
random_ether_addr(dev->dev_addr);
|
||||
ether_setup(dev);
|
||||
|
||||
dev->do_ioctl = br_dev_ioctl;
|
||||
dev->hard_start_xmit = br_dev_xmit;
|
||||
dev->open = br_dev_open;
|
||||
dev->set_multicast_list = br_dev_set_multicast_list;
|
||||
dev->change_mtu = br_change_mtu;
|
||||
dev->netdev_ops = &br_netdev_ops;
|
||||
dev->destructor = free_netdev;
|
||||
SET_ETHTOOL_OPS(dev, &br_ethtool_ops);
|
||||
dev->stop = br_dev_stop;
|
||||
dev->tx_queue_len = 0;
|
||||
dev->set_mac_address = br_set_mac_address;
|
||||
dev->priv_flags = IFF_EBRIDGE;
|
||||
|
||||
dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
|
||||
|
@@ -373,7 +373,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
|
||||
if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
|
||||
return -EINVAL;
|
||||
|
||||
if (dev->hard_start_xmit == br_dev_xmit)
|
||||
if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit)
|
||||
return -ELOOP;
|
||||
|
||||
if (dev->br_port != NULL)
|
||||
@@ -460,7 +460,7 @@ void br_net_exit(struct net *net)
|
||||
restart:
|
||||
for_each_netdev(net, dev) {
|
||||
if (dev->priv_flags & IFF_EBRIDGE) {
|
||||
del_br(dev->priv);
|
||||
del_br(netdev_priv(dev));
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
@@ -109,7 +109,6 @@ static struct dst_ops fake_dst_ops = {
|
||||
.family = AF_INET,
|
||||
.protocol = __constant_htons(ETH_P_IP),
|
||||
.update_pmtu = fake_update_pmtu,
|
||||
.entry_size = sizeof(struct rtable),
|
||||
.entries = ATOMIC_INIT(0),
|
||||
};
|
||||
|
||||
@@ -370,7 +369,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
|
||||
if (err != -EHOSTUNREACH || !in_dev || IN_DEV_FORWARD(in_dev))
|
||||
goto free_skb;
|
||||
|
||||
if (!ip_route_output_key(&init_net, &rt, &fl)) {
|
||||
if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
|
||||
/* - Bridged-and-DNAT'ed traffic doesn't
|
||||
* require ip_forwarding. */
|
||||
if (((struct dst_entry *)rt)->dev == dev) {
|
||||
@@ -951,35 +950,35 @@ static ctl_table brnf_table[] = {
|
||||
.data = &brnf_call_arptables,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &brnf_sysctl_call_tables,
|
||||
.proc_handler = brnf_sysctl_call_tables,
|
||||
},
|
||||
{
|
||||
.procname = "bridge-nf-call-iptables",
|
||||
.data = &brnf_call_iptables,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &brnf_sysctl_call_tables,
|
||||
.proc_handler = brnf_sysctl_call_tables,
|
||||
},
|
||||
{
|
||||
.procname = "bridge-nf-call-ip6tables",
|
||||
.data = &brnf_call_ip6tables,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &brnf_sysctl_call_tables,
|
||||
.proc_handler = brnf_sysctl_call_tables,
|
||||
},
|
||||
{
|
||||
.procname = "bridge-nf-filter-vlan-tagged",
|
||||
.data = &brnf_filter_vlan_tagged,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &brnf_sysctl_call_tables,
|
||||
.proc_handler = brnf_sysctl_call_tables,
|
||||
},
|
||||
{
|
||||
.procname = "bridge-nf-filter-pppoe-tagged",
|
||||
.data = &brnf_filter_pppoe_tagged,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &brnf_sysctl_call_tables,
|
||||
.proc_handler = brnf_sysctl_call_tables,
|
||||
},
|
||||
{ .ctl_name = 0 }
|
||||
};
|
||||
|
@@ -22,7 +22,7 @@
|
||||
#include "br_private.h"
|
||||
|
||||
#define to_dev(obj) container_of(obj, struct device, kobj)
|
||||
#define to_bridge(cd) ((struct net_bridge *)(to_net_dev(cd)->priv))
|
||||
#define to_bridge(cd) ((struct net_bridge *)netdev_priv(to_net_dev(cd)))
|
||||
|
||||
/*
|
||||
* Common code for storing bridge parameters.
|
||||
|
@@ -79,7 +79,6 @@ print_ports(const struct sk_buff *skb, uint8_t protocol, int offset)
|
||||
}
|
||||
}
|
||||
|
||||
#define myNIPQUAD(a) a[0], a[1], a[2], a[3]
|
||||
static void
|
||||
ebt_log_packet(u_int8_t pf, unsigned int hooknum,
|
||||
const struct sk_buff *skb, const struct net_device *in,
|
||||
@@ -113,9 +112,8 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,
|
||||
printk(" INCOMPLETE IP header");
|
||||
goto out;
|
||||
}
|
||||
printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u, IP "
|
||||
"tos=0x%02X, IP proto=%d", NIPQUAD(ih->saddr),
|
||||
NIPQUAD(ih->daddr), ih->tos, ih->protocol);
|
||||
printk(" IP SRC=%pI4 IP DST=%pI4, IP tos=0x%02X, IP proto=%d",
|
||||
&ih->saddr, &ih->daddr, ih->tos, ih->protocol);
|
||||
print_ports(skb, ih->protocol, ih->ihl*4);
|
||||
goto out;
|
||||
}
|
||||
@@ -133,10 +131,8 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,
|
||||
printk(" INCOMPLETE IPv6 header");
|
||||
goto out;
|
||||
}
|
||||
printk(" IPv6 SRC=%x:%x:%x:%x:%x:%x:%x:%x "
|
||||
"IPv6 DST=%x:%x:%x:%x:%x:%x:%x:%x, IPv6 "
|
||||
"priority=0x%01X, Next Header=%d", NIP6(ih->saddr),
|
||||
NIP6(ih->daddr), ih->priority, ih->nexthdr);
|
||||
printk(" IPv6 SRC=%pI6 IPv6 DST=%pI6, IPv6 priority=0x%01X, Next Header=%d",
|
||||
&ih->saddr, &ih->daddr, ih->priority, ih->nexthdr);
|
||||
nexthdr = ih->nexthdr;
|
||||
offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr);
|
||||
if (offset_ph == -1)
|
||||
@@ -177,12 +173,10 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,
|
||||
}
|
||||
printk(" ARP MAC SRC=");
|
||||
print_MAC(ap->mac_src);
|
||||
printk(" ARP IP SRC=%u.%u.%u.%u",
|
||||
myNIPQUAD(ap->ip_src));
|
||||
printk(" ARP IP SRC=%pI4", ap->ip_src);
|
||||
printk(" ARP MAC DST=");
|
||||
print_MAC(ap->mac_dst);
|
||||
printk(" ARP IP DST=%u.%u.%u.%u",
|
||||
myNIPQUAD(ap->ip_dst));
|
||||
printk(" ARP IP DST=%pI4", ap->ip_dst);
|
||||
}
|
||||
}
|
||||
out:
|
||||
|
@@ -56,29 +56,47 @@ static int ebt_broute(struct sk_buff *skb)
|
||||
int ret;
|
||||
|
||||
ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL,
|
||||
&broute_table);
|
||||
dev_net(skb->dev)->xt.broute_table);
|
||||
if (ret == NF_DROP)
|
||||
return 1; /* route it */
|
||||
return 0; /* bridge it */
|
||||
}
|
||||
|
||||
static int __net_init broute_net_init(struct net *net)
|
||||
{
|
||||
net->xt.broute_table = ebt_register_table(net, &broute_table);
|
||||
if (IS_ERR(net->xt.broute_table))
|
||||
return PTR_ERR(net->xt.broute_table);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __net_exit broute_net_exit(struct net *net)
|
||||
{
|
||||
ebt_unregister_table(net->xt.broute_table);
|
||||
}
|
||||
|
||||
static struct pernet_operations broute_net_ops = {
|
||||
.init = broute_net_init,
|
||||
.exit = broute_net_exit,
|
||||
};
|
||||
|
||||
static int __init ebtable_broute_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ebt_register_table(&broute_table);
|
||||
ret = register_pernet_subsys(&broute_net_ops);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* see br_input.c */
|
||||
rcu_assign_pointer(br_should_route_hook, ebt_broute);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ebtable_broute_fini(void)
|
||||
{
|
||||
rcu_assign_pointer(br_should_route_hook, NULL);
|
||||
synchronize_net();
|
||||
ebt_unregister_table(&broute_table);
|
||||
unregister_pernet_subsys(&broute_net_ops);
|
||||
}
|
||||
|
||||
module_init(ebtable_broute_init);
|
||||
|
@@ -61,29 +61,36 @@ static struct ebt_table frame_filter =
|
||||
};
|
||||
|
||||
static unsigned int
|
||||
ebt_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in,
|
||||
ebt_in_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
return ebt_do_table(hook, skb, in, out, &frame_filter);
|
||||
return ebt_do_table(hook, skb, in, out, dev_net(in)->xt.frame_filter);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
ebt_out_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
return ebt_do_table(hook, skb, in, out, dev_net(out)->xt.frame_filter);
|
||||
}
|
||||
|
||||
static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
|
||||
{
|
||||
.hook = ebt_hook,
|
||||
.hook = ebt_in_hook,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = PF_BRIDGE,
|
||||
.hooknum = NF_BR_LOCAL_IN,
|
||||
.priority = NF_BR_PRI_FILTER_BRIDGED,
|
||||
},
|
||||
{
|
||||
.hook = ebt_hook,
|
||||
.hook = ebt_in_hook,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = PF_BRIDGE,
|
||||
.hooknum = NF_BR_FORWARD,
|
||||
.priority = NF_BR_PRI_FILTER_BRIDGED,
|
||||
},
|
||||
{
|
||||
.hook = ebt_hook,
|
||||
.hook = ebt_out_hook,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = PF_BRIDGE,
|
||||
.hooknum = NF_BR_LOCAL_OUT,
|
||||
@@ -91,23 +98,41 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __net_init frame_filter_net_init(struct net *net)
|
||||
{
|
||||
net->xt.frame_filter = ebt_register_table(net, &frame_filter);
|
||||
if (IS_ERR(net->xt.frame_filter))
|
||||
return PTR_ERR(net->xt.frame_filter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __net_exit frame_filter_net_exit(struct net *net)
|
||||
{
|
||||
ebt_unregister_table(net->xt.frame_filter);
|
||||
}
|
||||
|
||||
static struct pernet_operations frame_filter_net_ops = {
|
||||
.init = frame_filter_net_init,
|
||||
.exit = frame_filter_net_exit,
|
||||
};
|
||||
|
||||
static int __init ebtable_filter_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ebt_register_table(&frame_filter);
|
||||
ret = register_pernet_subsys(&frame_filter_net_ops);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = nf_register_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
|
||||
if (ret < 0)
|
||||
ebt_unregister_table(&frame_filter);
|
||||
unregister_pernet_subsys(&frame_filter_net_ops);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit ebtable_filter_fini(void)
|
||||
{
|
||||
nf_unregister_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
|
||||
ebt_unregister_table(&frame_filter);
|
||||
unregister_pernet_subsys(&frame_filter_net_ops);
|
||||
}
|
||||
|
||||
module_init(ebtable_filter_init);
|
||||
|
@@ -61,36 +61,36 @@ static struct ebt_table frame_nat =
|
||||
};
|
||||
|
||||
static unsigned int
|
||||
ebt_nat_dst(unsigned int hook, struct sk_buff *skb, const struct net_device *in
|
||||
ebt_nat_in(unsigned int hook, struct sk_buff *skb, const struct net_device *in
|
||||
, const struct net_device *out, int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
return ebt_do_table(hook, skb, in, out, &frame_nat);
|
||||
return ebt_do_table(hook, skb, in, out, dev_net(in)->xt.frame_nat);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
ebt_nat_src(unsigned int hook, struct sk_buff *skb, const struct net_device *in
|
||||
ebt_nat_out(unsigned int hook, struct sk_buff *skb, const struct net_device *in
|
||||
, const struct net_device *out, int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
return ebt_do_table(hook, skb, in, out, &frame_nat);
|
||||
return ebt_do_table(hook, skb, in, out, dev_net(out)->xt.frame_nat);
|
||||
}
|
||||
|
||||
static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
|
||||
{
|
||||
.hook = ebt_nat_dst,
|
||||
.hook = ebt_nat_out,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = PF_BRIDGE,
|
||||
.hooknum = NF_BR_LOCAL_OUT,
|
||||
.priority = NF_BR_PRI_NAT_DST_OTHER,
|
||||
},
|
||||
{
|
||||
.hook = ebt_nat_src,
|
||||
.hook = ebt_nat_out,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = PF_BRIDGE,
|
||||
.hooknum = NF_BR_POST_ROUTING,
|
||||
.priority = NF_BR_PRI_NAT_SRC,
|
||||
},
|
||||
{
|
||||
.hook = ebt_nat_dst,
|
||||
.hook = ebt_nat_in,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = PF_BRIDGE,
|
||||
.hooknum = NF_BR_PRE_ROUTING,
|
||||
@@ -98,23 +98,41 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __net_init frame_nat_net_init(struct net *net)
|
||||
{
|
||||
net->xt.frame_nat = ebt_register_table(net, &frame_nat);
|
||||
if (IS_ERR(net->xt.frame_nat))
|
||||
return PTR_ERR(net->xt.frame_nat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __net_exit frame_nat_net_exit(struct net *net)
|
||||
{
|
||||
ebt_unregister_table(net->xt.frame_nat);
|
||||
}
|
||||
|
||||
static struct pernet_operations frame_nat_net_ops = {
|
||||
.init = frame_nat_net_init,
|
||||
.exit = frame_nat_net_exit,
|
||||
};
|
||||
|
||||
static int __init ebtable_nat_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ebt_register_table(&frame_nat);
|
||||
ret = register_pernet_subsys(&frame_nat_net_ops);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = nf_register_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat));
|
||||
if (ret < 0)
|
||||
ebt_unregister_table(&frame_nat);
|
||||
unregister_pernet_subsys(&frame_nat_net_ops);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit ebtable_nat_fini(void)
|
||||
{
|
||||
nf_unregister_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat));
|
||||
ebt_unregister_table(&frame_nat);
|
||||
unregister_pernet_subsys(&frame_nat_net_ops);
|
||||
}
|
||||
|
||||
module_init(ebtable_nat_init);
|
||||
|
@@ -55,7 +55,6 @@
|
||||
|
||||
|
||||
static DEFINE_MUTEX(ebt_mutex);
|
||||
static LIST_HEAD(ebt_tables);
|
||||
|
||||
static struct xt_target ebt_standard_target = {
|
||||
.name = "standard",
|
||||
@@ -315,9 +314,11 @@ find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
|
||||
}
|
||||
|
||||
static inline struct ebt_table *
|
||||
find_table_lock(const char *name, int *error, struct mutex *mutex)
|
||||
find_table_lock(struct net *net, const char *name, int *error,
|
||||
struct mutex *mutex)
|
||||
{
|
||||
return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex);
|
||||
return find_inlist_lock(&net->xt.tables[NFPROTO_BRIDGE], name,
|
||||
"ebtable_", error, mutex);
|
||||
}
|
||||
|
||||
static inline int
|
||||
@@ -944,7 +945,7 @@ static void get_counters(struct ebt_counter *oldcounters,
|
||||
}
|
||||
|
||||
/* replace the table */
|
||||
static int do_replace(void __user *user, unsigned int len)
|
||||
static int do_replace(struct net *net, void __user *user, unsigned int len)
|
||||
{
|
||||
int ret, i, countersize;
|
||||
struct ebt_table_info *newinfo;
|
||||
@@ -1016,7 +1017,7 @@ static int do_replace(void __user *user, unsigned int len)
|
||||
if (ret != 0)
|
||||
goto free_counterstmp;
|
||||
|
||||
t = find_table_lock(tmp.name, &ret, &ebt_mutex);
|
||||
t = find_table_lock(net, tmp.name, &ret, &ebt_mutex);
|
||||
if (!t) {
|
||||
ret = -ENOENT;
|
||||
goto free_iterate;
|
||||
@@ -1097,7 +1098,7 @@ free_newinfo:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ebt_register_table(struct ebt_table *table)
|
||||
struct ebt_table *ebt_register_table(struct net *net, struct ebt_table *table)
|
||||
{
|
||||
struct ebt_table_info *newinfo;
|
||||
struct ebt_table *t;
|
||||
@@ -1109,14 +1110,21 @@ int ebt_register_table(struct ebt_table *table)
|
||||
repl->entries_size == 0 ||
|
||||
repl->counters || table->private) {
|
||||
BUGPRINT("Bad table data for ebt_register_table!!!\n");
|
||||
return -EINVAL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
/* Don't add one table to multiple lists. */
|
||||
table = kmemdup(table, sizeof(struct ebt_table), GFP_KERNEL);
|
||||
if (!table) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;
|
||||
newinfo = vmalloc(sizeof(*newinfo) + countersize);
|
||||
ret = -ENOMEM;
|
||||
if (!newinfo)
|
||||
return -ENOMEM;
|
||||
goto free_table;
|
||||
|
||||
p = vmalloc(repl->entries_size);
|
||||
if (!p)
|
||||
@@ -1148,7 +1156,7 @@ int ebt_register_table(struct ebt_table *table)
|
||||
|
||||
if (table->check && table->check(newinfo, table->valid_hooks)) {
|
||||
BUGPRINT("The table doesn't like its own initial data, lol\n");
|
||||
return -EINVAL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
table->private = newinfo;
|
||||
@@ -1157,7 +1165,7 @@ int ebt_register_table(struct ebt_table *table)
|
||||
if (ret != 0)
|
||||
goto free_chainstack;
|
||||
|
||||
list_for_each_entry(t, &ebt_tables, list) {
|
||||
list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) {
|
||||
if (strcmp(t->name, table->name) == 0) {
|
||||
ret = -EEXIST;
|
||||
BUGPRINT("Table name already exists\n");
|
||||
@@ -1170,9 +1178,9 @@ int ebt_register_table(struct ebt_table *table)
|
||||
ret = -ENOENT;
|
||||
goto free_unlock;
|
||||
}
|
||||
list_add(&table->list, &ebt_tables);
|
||||
list_add(&table->list, &net->xt.tables[NFPROTO_BRIDGE]);
|
||||
mutex_unlock(&ebt_mutex);
|
||||
return 0;
|
||||
return table;
|
||||
free_unlock:
|
||||
mutex_unlock(&ebt_mutex);
|
||||
free_chainstack:
|
||||
@@ -1184,7 +1192,10 @@ free_chainstack:
|
||||
vfree(newinfo->entries);
|
||||
free_newinfo:
|
||||
vfree(newinfo);
|
||||
return ret;
|
||||
free_table:
|
||||
kfree(table);
|
||||
out:
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
void ebt_unregister_table(struct ebt_table *table)
|
||||
@@ -1198,6 +1209,10 @@ void ebt_unregister_table(struct ebt_table *table)
|
||||
mutex_lock(&ebt_mutex);
|
||||
list_del(&table->list);
|
||||
mutex_unlock(&ebt_mutex);
|
||||
EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size,
|
||||
ebt_cleanup_entry, NULL);
|
||||
if (table->private->nentries)
|
||||
module_put(table->me);
|
||||
vfree(table->private->entries);
|
||||
if (table->private->chainstack) {
|
||||
for_each_possible_cpu(i)
|
||||
@@ -1205,10 +1220,11 @@ void ebt_unregister_table(struct ebt_table *table)
|
||||
vfree(table->private->chainstack);
|
||||
}
|
||||
vfree(table->private);
|
||||
kfree(table);
|
||||
}
|
||||
|
||||
/* userspace just supplied us with counters */
|
||||
static int update_counters(void __user *user, unsigned int len)
|
||||
static int update_counters(struct net *net, void __user *user, unsigned int len)
|
||||
{
|
||||
int i, ret;
|
||||
struct ebt_counter *tmp;
|
||||
@@ -1228,7 +1244,7 @@ static int update_counters(void __user *user, unsigned int len)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
t = find_table_lock(hlp.name, &ret, &ebt_mutex);
|
||||
t = find_table_lock(net, hlp.name, &ret, &ebt_mutex);
|
||||
if (!t)
|
||||
goto free_tmp;
|
||||
|
||||
@@ -1386,10 +1402,10 @@ static int do_ebt_set_ctl(struct sock *sk,
|
||||
|
||||
switch(cmd) {
|
||||
case EBT_SO_SET_ENTRIES:
|
||||
ret = do_replace(user, len);
|
||||
ret = do_replace(sock_net(sk), user, len);
|
||||
break;
|
||||
case EBT_SO_SET_COUNTERS:
|
||||
ret = update_counters(user, len);
|
||||
ret = update_counters(sock_net(sk), user, len);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
@@ -1406,7 +1422,7 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
|
||||
if (copy_from_user(&tmp, user, sizeof(tmp)))
|
||||
return -EFAULT;
|
||||
|
||||
t = find_table_lock(tmp.name, &ret, &ebt_mutex);
|
||||
t = find_table_lock(sock_net(sk), tmp.name, &ret, &ebt_mutex);
|
||||
if (!t)
|
||||
return ret;
|
||||
|
||||
|
@@ -641,17 +641,12 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||
|
||||
skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT,
|
||||
&err);
|
||||
if (!skb) {
|
||||
dev_put(dev);
|
||||
return err;
|
||||
}
|
||||
if (!skb)
|
||||
goto put_dev;
|
||||
|
||||
err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
|
||||
if (err < 0) {
|
||||
kfree_skb(skb);
|
||||
dev_put(dev);
|
||||
return err;
|
||||
}
|
||||
if (err < 0)
|
||||
goto free_skb;
|
||||
skb->dev = dev;
|
||||
skb->sk = sk;
|
||||
|
||||
@@ -660,9 +655,16 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||
dev_put(dev);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
goto send_failed;
|
||||
|
||||
return size;
|
||||
|
||||
free_skb:
|
||||
kfree_skb(skb);
|
||||
put_dev:
|
||||
dev_put(dev);
|
||||
send_failed:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
|
@@ -209,7 +209,7 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags,
|
||||
void skb_free_datagram(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
kfree_skb(skb);
|
||||
sk_mem_reclaim(sk);
|
||||
sk_mem_reclaim_partial(sk);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,8 +248,7 @@ int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
|
||||
spin_unlock_bh(&sk->sk_receive_queue.lock);
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
sk_mem_reclaim(sk);
|
||||
skb_free_datagram(sk, skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
458
net/core/dev.c
458
net/core/dev.c
@@ -108,7 +108,6 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/netpoll.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/delay.h>
|
||||
@@ -130,6 +129,9 @@
|
||||
|
||||
#include "net-sysfs.h"
|
||||
|
||||
/* Instead of increasing this, you should create a hash table. */
|
||||
#define MAX_GRO_SKBS 8
|
||||
|
||||
/*
|
||||
* The list of packet types we will receive (as opposed to discard)
|
||||
* and the routines to invoke.
|
||||
@@ -281,8 +283,8 @@ static const unsigned short netdev_lock_type[] =
|
||||
ARPHRD_PIMREG, ARPHRD_HIPPI, ARPHRD_ASH, ARPHRD_ECONET,
|
||||
ARPHRD_IRDA, ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL,
|
||||
ARPHRD_FCFABRIC, ARPHRD_IEEE802_TR, ARPHRD_IEEE80211,
|
||||
ARPHRD_IEEE80211_PRISM, ARPHRD_IEEE80211_RADIOTAP, ARPHRD_VOID,
|
||||
ARPHRD_NONE};
|
||||
ARPHRD_IEEE80211_PRISM, ARPHRD_IEEE80211_RADIOTAP, ARPHRD_PHONET,
|
||||
ARPHRD_PHONET_PIPE, ARPHRD_VOID, ARPHRD_NONE};
|
||||
|
||||
static const char *netdev_lock_name[] =
|
||||
{"_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25",
|
||||
@@ -298,8 +300,8 @@ static const char *netdev_lock_name[] =
|
||||
"_xmit_PIMREG", "_xmit_HIPPI", "_xmit_ASH", "_xmit_ECONET",
|
||||
"_xmit_IRDA", "_xmit_FCPP", "_xmit_FCAL", "_xmit_FCPL",
|
||||
"_xmit_FCFABRIC", "_xmit_IEEE802_TR", "_xmit_IEEE80211",
|
||||
"_xmit_IEEE80211_PRISM", "_xmit_IEEE80211_RADIOTAP", "_xmit_VOID",
|
||||
"_xmit_NONE"};
|
||||
"_xmit_IEEE80211_PRISM", "_xmit_IEEE80211_RADIOTAP", "_xmit_PHONET",
|
||||
"_xmit_PHONET_PIPE", "_xmit_VOID", "_xmit_NONE"};
|
||||
|
||||
static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)];
|
||||
static struct lock_class_key netdev_addr_lock_key[ARRAY_SIZE(netdev_lock_type)];
|
||||
@@ -924,10 +926,15 @@ int dev_change_name(struct net_device *dev, const char *newname)
|
||||
strlcpy(dev->name, newname, IFNAMSIZ);
|
||||
|
||||
rollback:
|
||||
ret = device_rename(&dev->dev, dev->name);
|
||||
if (ret) {
|
||||
memcpy(dev->name, oldname, IFNAMSIZ);
|
||||
return ret;
|
||||
/* For now only devices in the initial network namespace
|
||||
* are in sysfs.
|
||||
*/
|
||||
if (net == &init_net) {
|
||||
ret = device_rename(&dev->dev, dev->name);
|
||||
if (ret) {
|
||||
memcpy(dev->name, oldname, IFNAMSIZ);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
write_lock_bh(&dev_base_lock);
|
||||
@@ -1055,6 +1062,7 @@ void dev_load(struct net *net, const char *name)
|
||||
*/
|
||||
int dev_open(struct net_device *dev)
|
||||
{
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
int ret = 0;
|
||||
|
||||
ASSERT_RTNL();
|
||||
@@ -1077,11 +1085,11 @@ int dev_open(struct net_device *dev)
|
||||
*/
|
||||
set_bit(__LINK_STATE_START, &dev->state);
|
||||
|
||||
if (dev->validate_addr)
|
||||
ret = dev->validate_addr(dev);
|
||||
if (ops->ndo_validate_addr)
|
||||
ret = ops->ndo_validate_addr(dev);
|
||||
|
||||
if (!ret && dev->open)
|
||||
ret = dev->open(dev);
|
||||
if (!ret && ops->ndo_open)
|
||||
ret = ops->ndo_open(dev);
|
||||
|
||||
/*
|
||||
* If it went open OK then:
|
||||
@@ -1125,6 +1133,7 @@ int dev_open(struct net_device *dev)
|
||||
*/
|
||||
int dev_close(struct net_device *dev)
|
||||
{
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
ASSERT_RTNL();
|
||||
|
||||
might_sleep();
|
||||
@@ -1157,8 +1166,8 @@ int dev_close(struct net_device *dev)
|
||||
* We allow it to be called even after a DETACH hot-plug
|
||||
* event.
|
||||
*/
|
||||
if (dev->stop)
|
||||
dev->stop(dev);
|
||||
if (ops->ndo_stop)
|
||||
ops->ndo_stop(dev);
|
||||
|
||||
/*
|
||||
* Device is now down.
|
||||
@@ -1527,8 +1536,6 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
|
||||
__be16 type = skb->protocol;
|
||||
int err;
|
||||
|
||||
BUG_ON(skb_shinfo(skb)->frag_list);
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
skb->mac_len = skb->network_header - skb->mac_header;
|
||||
__skb_pull(skb, skb->mac_len);
|
||||
@@ -1654,6 +1661,9 @@ static int dev_gso_segment(struct sk_buff *skb)
|
||||
int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||
struct netdev_queue *txq)
|
||||
{
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
|
||||
prefetch(&dev->netdev_ops->ndo_start_xmit);
|
||||
if (likely(!skb->next)) {
|
||||
if (!list_empty(&ptype_all))
|
||||
dev_queue_xmit_nit(skb, dev);
|
||||
@@ -1665,7 +1675,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||
goto gso;
|
||||
}
|
||||
|
||||
return dev->hard_start_xmit(skb, dev);
|
||||
return ops->ndo_start_xmit(skb, dev);
|
||||
}
|
||||
|
||||
gso:
|
||||
@@ -1675,7 +1685,7 @@ gso:
|
||||
|
||||
skb->next = nskb->next;
|
||||
nskb->next = NULL;
|
||||
rc = dev->hard_start_xmit(nskb, dev);
|
||||
rc = ops->ndo_start_xmit(nskb, dev);
|
||||
if (unlikely(rc)) {
|
||||
nskb->next = skb->next;
|
||||
skb->next = nskb;
|
||||
@@ -1749,10 +1759,11 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb)
|
||||
static struct netdev_queue *dev_pick_tx(struct net_device *dev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
u16 queue_index = 0;
|
||||
|
||||
if (dev->select_queue)
|
||||
queue_index = dev->select_queue(dev, skb);
|
||||
if (ops->ndo_select_queue)
|
||||
queue_index = ops->ndo_select_queue(dev, skb);
|
||||
else if (dev->real_num_tx_queues > 1)
|
||||
queue_index = simple_tx_hash(dev, skb);
|
||||
|
||||
@@ -2251,8 +2262,10 @@ int netif_receive_skb(struct sk_buff *skb)
|
||||
rcu_read_lock();
|
||||
|
||||
/* Don't receive packets in an exiting network namespace */
|
||||
if (!net_alive(dev_net(skb->dev)))
|
||||
if (!net_alive(dev_net(skb->dev))) {
|
||||
kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_CLS_ACT
|
||||
if (skb->tc_verd & TC_NCLS) {
|
||||
@@ -2325,6 +2338,125 @@ static void flush_backlog(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
static int napi_gro_complete(struct sk_buff *skb)
|
||||
{
|
||||
struct packet_type *ptype;
|
||||
__be16 type = skb->protocol;
|
||||
struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
|
||||
int err = -ENOENT;
|
||||
|
||||
if (!skb_shinfo(skb)->frag_list)
|
||||
goto out;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(ptype, head, list) {
|
||||
if (ptype->type != type || ptype->dev || !ptype->gro_complete)
|
||||
continue;
|
||||
|
||||
err = ptype->gro_complete(skb);
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (err) {
|
||||
WARN_ON(&ptype->list == head);
|
||||
kfree_skb(skb);
|
||||
return NET_RX_SUCCESS;
|
||||
}
|
||||
|
||||
out:
|
||||
__skb_push(skb, -skb_network_offset(skb));
|
||||
return netif_receive_skb(skb);
|
||||
}
|
||||
|
||||
void napi_gro_flush(struct napi_struct *napi)
|
||||
{
|
||||
struct sk_buff *skb, *next;
|
||||
|
||||
for (skb = napi->gro_list; skb; skb = next) {
|
||||
next = skb->next;
|
||||
skb->next = NULL;
|
||||
napi_gro_complete(skb);
|
||||
}
|
||||
|
||||
napi->gro_list = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(napi_gro_flush);
|
||||
|
||||
int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff **pp = NULL;
|
||||
struct packet_type *ptype;
|
||||
__be16 type = skb->protocol;
|
||||
struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
|
||||
int count = 0;
|
||||
int same_flow;
|
||||
int mac_len;
|
||||
|
||||
if (!(skb->dev->features & NETIF_F_GRO))
|
||||
goto normal;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(ptype, head, list) {
|
||||
struct sk_buff *p;
|
||||
|
||||
if (ptype->type != type || ptype->dev || !ptype->gro_receive)
|
||||
continue;
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
mac_len = skb->network_header - skb->mac_header;
|
||||
skb->mac_len = mac_len;
|
||||
NAPI_GRO_CB(skb)->same_flow = 0;
|
||||
NAPI_GRO_CB(skb)->flush = 0;
|
||||
|
||||
for (p = napi->gro_list; p; p = p->next) {
|
||||
count++;
|
||||
NAPI_GRO_CB(p)->same_flow =
|
||||
p->mac_len == mac_len &&
|
||||
!memcmp(skb_mac_header(p), skb_mac_header(skb),
|
||||
mac_len);
|
||||
NAPI_GRO_CB(p)->flush = 0;
|
||||
}
|
||||
|
||||
pp = ptype->gro_receive(&napi->gro_list, skb);
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (&ptype->list == head)
|
||||
goto normal;
|
||||
|
||||
same_flow = NAPI_GRO_CB(skb)->same_flow;
|
||||
|
||||
if (pp) {
|
||||
struct sk_buff *nskb = *pp;
|
||||
|
||||
*pp = nskb->next;
|
||||
nskb->next = NULL;
|
||||
napi_gro_complete(nskb);
|
||||
count--;
|
||||
}
|
||||
|
||||
if (same_flow)
|
||||
goto ok;
|
||||
|
||||
if (NAPI_GRO_CB(skb)->flush || count >= MAX_GRO_SKBS) {
|
||||
__skb_push(skb, -skb_network_offset(skb));
|
||||
goto normal;
|
||||
}
|
||||
|
||||
NAPI_GRO_CB(skb)->count = 1;
|
||||
skb->next = napi->gro_list;
|
||||
napi->gro_list = skb;
|
||||
|
||||
ok:
|
||||
return NET_RX_SUCCESS;
|
||||
|
||||
normal:
|
||||
return netif_receive_skb(skb);
|
||||
}
|
||||
EXPORT_SYMBOL(napi_gro_receive);
|
||||
|
||||
static int process_backlog(struct napi_struct *napi, int quota)
|
||||
{
|
||||
int work = 0;
|
||||
@@ -2344,9 +2476,11 @@ static int process_backlog(struct napi_struct *napi, int quota)
|
||||
}
|
||||
local_irq_enable();
|
||||
|
||||
netif_receive_skb(skb);
|
||||
napi_gro_receive(napi, skb);
|
||||
} while (++work < quota && jiffies == start_time);
|
||||
|
||||
napi_gro_flush(napi);
|
||||
|
||||
return work;
|
||||
}
|
||||
|
||||
@@ -2367,11 +2501,73 @@ void __napi_schedule(struct napi_struct *n)
|
||||
}
|
||||
EXPORT_SYMBOL(__napi_schedule);
|
||||
|
||||
void __napi_complete(struct napi_struct *n)
|
||||
{
|
||||
BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state));
|
||||
BUG_ON(n->gro_list);
|
||||
|
||||
list_del(&n->poll_list);
|
||||
smp_mb__before_clear_bit();
|
||||
clear_bit(NAPI_STATE_SCHED, &n->state);
|
||||
}
|
||||
EXPORT_SYMBOL(__napi_complete);
|
||||
|
||||
void napi_complete(struct napi_struct *n)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* don't let napi dequeue from the cpu poll list
|
||||
* just in case its running on a different cpu
|
||||
*/
|
||||
if (unlikely(test_bit(NAPI_STATE_NPSVC, &n->state)))
|
||||
return;
|
||||
|
||||
napi_gro_flush(n);
|
||||
local_irq_save(flags);
|
||||
__napi_complete(n);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
EXPORT_SYMBOL(napi_complete);
|
||||
|
||||
void netif_napi_add(struct net_device *dev, struct napi_struct *napi,
|
||||
int (*poll)(struct napi_struct *, int), int weight)
|
||||
{
|
||||
INIT_LIST_HEAD(&napi->poll_list);
|
||||
napi->gro_list = NULL;
|
||||
napi->poll = poll;
|
||||
napi->weight = weight;
|
||||
list_add(&napi->dev_list, &dev->napi_list);
|
||||
#ifdef CONFIG_NETPOLL
|
||||
napi->dev = dev;
|
||||
spin_lock_init(&napi->poll_lock);
|
||||
napi->poll_owner = -1;
|
||||
#endif
|
||||
set_bit(NAPI_STATE_SCHED, &napi->state);
|
||||
}
|
||||
EXPORT_SYMBOL(netif_napi_add);
|
||||
|
||||
void netif_napi_del(struct napi_struct *napi)
|
||||
{
|
||||
struct sk_buff *skb, *next;
|
||||
|
||||
list_del_init(&napi->dev_list);
|
||||
|
||||
for (skb = napi->gro_list; skb; skb = next) {
|
||||
next = skb->next;
|
||||
skb->next = NULL;
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
napi->gro_list = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(netif_napi_del);
|
||||
|
||||
|
||||
static void net_rx_action(struct softirq_action *h)
|
||||
{
|
||||
struct list_head *list = &__get_cpu_var(softnet_data).poll_list;
|
||||
unsigned long start_time = jiffies;
|
||||
unsigned long time_limit = jiffies + 2;
|
||||
int budget = netdev_budget;
|
||||
void *have;
|
||||
|
||||
@@ -2382,13 +2578,10 @@ static void net_rx_action(struct softirq_action *h)
|
||||
int work, weight;
|
||||
|
||||
/* If softirq window is exhuasted then punt.
|
||||
*
|
||||
* Note that this is a slight policy change from the
|
||||
* previous NAPI code, which would allow up to 2
|
||||
* jiffies to pass before breaking out. The test
|
||||
* used to be "jiffies - start_time > 1".
|
||||
* Allow this to run for 2 jiffies since which will allow
|
||||
* an average latency of 1.5/HZ.
|
||||
*/
|
||||
if (unlikely(budget <= 0 || jiffies != start_time))
|
||||
if (unlikely(budget <= 0 || time_after(jiffies, time_limit)))
|
||||
goto softnet_break;
|
||||
|
||||
local_irq_enable();
|
||||
@@ -2615,7 +2808,7 @@ void dev_seq_stop(struct seq_file *seq, void *v)
|
||||
|
||||
static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev)
|
||||
{
|
||||
struct net_device_stats *stats = dev->get_stats(dev);
|
||||
const struct net_device_stats *stats = dev_get_stats(dev);
|
||||
|
||||
seq_printf(seq, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu "
|
||||
"%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
|
||||
@@ -2797,31 +2990,6 @@ static void ptype_seq_stop(struct seq_file *seq, void *v)
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void ptype_seq_decode(struct seq_file *seq, void *sym)
|
||||
{
|
||||
#ifdef CONFIG_KALLSYMS
|
||||
unsigned long offset = 0, symsize;
|
||||
const char *symname;
|
||||
char *modname;
|
||||
char namebuf[128];
|
||||
|
||||
symname = kallsyms_lookup((unsigned long)sym, &symsize, &offset,
|
||||
&modname, namebuf);
|
||||
|
||||
if (symname) {
|
||||
char *delim = ":";
|
||||
|
||||
if (!modname)
|
||||
modname = delim = "";
|
||||
seq_printf(seq, "%s%s%s%s+0x%lx", delim, modname, delim,
|
||||
symname, offset);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
seq_printf(seq, "[%p]", sym);
|
||||
}
|
||||
|
||||
static int ptype_seq_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct packet_type *pt = v;
|
||||
@@ -2834,10 +3002,8 @@ static int ptype_seq_show(struct seq_file *seq, void *v)
|
||||
else
|
||||
seq_printf(seq, "%04x", ntohs(pt->type));
|
||||
|
||||
seq_printf(seq, " %-8s ",
|
||||
pt->dev ? pt->dev->name : "");
|
||||
ptype_seq_decode(seq, pt->func);
|
||||
seq_putc(seq, '\n');
|
||||
seq_printf(seq, " %-8s %pF\n",
|
||||
pt->dev ? pt->dev->name : "", pt->func);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2954,8 +3120,10 @@ int netdev_set_master(struct net_device *slave, struct net_device *master)
|
||||
|
||||
static void dev_change_rx_flags(struct net_device *dev, int flags)
|
||||
{
|
||||
if (dev->flags & IFF_UP && dev->change_rx_flags)
|
||||
dev->change_rx_flags(dev, flags);
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
|
||||
if ((dev->flags & IFF_UP) && ops->ndo_change_rx_flags)
|
||||
ops->ndo_change_rx_flags(dev, flags);
|
||||
}
|
||||
|
||||
static int __dev_set_promiscuity(struct net_device *dev, int inc)
|
||||
@@ -3079,6 +3247,8 @@ int dev_set_allmulti(struct net_device *dev, int inc)
|
||||
*/
|
||||
void __dev_set_rx_mode(struct net_device *dev)
|
||||
{
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
|
||||
/* dev_open will call this function so the list will stay sane. */
|
||||
if (!(dev->flags&IFF_UP))
|
||||
return;
|
||||
@@ -3086,8 +3256,8 @@ void __dev_set_rx_mode(struct net_device *dev)
|
||||
if (!netif_device_present(dev))
|
||||
return;
|
||||
|
||||
if (dev->set_rx_mode)
|
||||
dev->set_rx_mode(dev);
|
||||
if (ops->ndo_set_rx_mode)
|
||||
ops->ndo_set_rx_mode(dev);
|
||||
else {
|
||||
/* Unicast addresses changes may only happen under the rtnl,
|
||||
* therefore calling __dev_set_promiscuity here is safe.
|
||||
@@ -3100,8 +3270,8 @@ void __dev_set_rx_mode(struct net_device *dev)
|
||||
dev->uc_promisc = 0;
|
||||
}
|
||||
|
||||
if (dev->set_multicast_list)
|
||||
dev->set_multicast_list(dev);
|
||||
if (ops->ndo_set_multicast_list)
|
||||
ops->ndo_set_multicast_list(dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3460,6 +3630,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
|
||||
*/
|
||||
int dev_set_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
int err;
|
||||
|
||||
if (new_mtu == dev->mtu)
|
||||
@@ -3473,10 +3644,11 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
|
||||
return -ENODEV;
|
||||
|
||||
err = 0;
|
||||
if (dev->change_mtu)
|
||||
err = dev->change_mtu(dev, new_mtu);
|
||||
if (ops->ndo_change_mtu)
|
||||
err = ops->ndo_change_mtu(dev, new_mtu);
|
||||
else
|
||||
dev->mtu = new_mtu;
|
||||
|
||||
if (!err && dev->flags & IFF_UP)
|
||||
call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
|
||||
return err;
|
||||
@@ -3491,15 +3663,16 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
|
||||
*/
|
||||
int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
|
||||
{
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
int err;
|
||||
|
||||
if (!dev->set_mac_address)
|
||||
if (!ops->ndo_set_mac_address)
|
||||
return -EOPNOTSUPP;
|
||||
if (sa->sa_family != dev->type)
|
||||
return -EINVAL;
|
||||
if (!netif_device_present(dev))
|
||||
return -ENODEV;
|
||||
err = dev->set_mac_address(dev, sa);
|
||||
err = ops->ndo_set_mac_address(dev, sa);
|
||||
if (!err)
|
||||
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
|
||||
return err;
|
||||
@@ -3579,10 +3752,13 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
|
||||
{
|
||||
int err;
|
||||
struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
|
||||
const struct net_device_ops *ops;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
ops = dev->netdev_ops;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS: /* Set interface flags */
|
||||
return dev_change_flags(dev, ifr->ifr_flags);
|
||||
@@ -3606,15 +3782,15 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
|
||||
return 0;
|
||||
|
||||
case SIOCSIFMAP:
|
||||
if (dev->set_config) {
|
||||
if (ops->ndo_set_config) {
|
||||
if (!netif_device_present(dev))
|
||||
return -ENODEV;
|
||||
return dev->set_config(dev, &ifr->ifr_map);
|
||||
return ops->ndo_set_config(dev, &ifr->ifr_map);
|
||||
}
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
case SIOCADDMULTI:
|
||||
if ((!dev->set_multicast_list && !dev->set_rx_mode) ||
|
||||
if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) ||
|
||||
ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
|
||||
return -EINVAL;
|
||||
if (!netif_device_present(dev))
|
||||
@@ -3623,7 +3799,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
|
||||
dev->addr_len, 1);
|
||||
|
||||
case SIOCDELMULTI:
|
||||
if ((!dev->set_multicast_list && !dev->set_rx_mode) ||
|
||||
if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) ||
|
||||
ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
|
||||
return -EINVAL;
|
||||
if (!netif_device_present(dev))
|
||||
@@ -3661,10 +3837,9 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
|
||||
cmd == SIOCBRDELIF ||
|
||||
cmd == SIOCWANDEV) {
|
||||
err = -EOPNOTSUPP;
|
||||
if (dev->do_ioctl) {
|
||||
if (ops->ndo_do_ioctl) {
|
||||
if (netif_device_present(dev))
|
||||
err = dev->do_ioctl(dev, ifr,
|
||||
cmd);
|
||||
err = ops->ndo_do_ioctl(dev, ifr, cmd);
|
||||
else
|
||||
err = -ENODEV;
|
||||
}
|
||||
@@ -3925,8 +4100,8 @@ static void rollback_registered(struct net_device *dev)
|
||||
*/
|
||||
dev_addr_discard(dev);
|
||||
|
||||
if (dev->uninit)
|
||||
dev->uninit(dev);
|
||||
if (dev->netdev_ops->ndo_uninit)
|
||||
dev->netdev_ops->ndo_uninit(dev);
|
||||
|
||||
/* Notifier chain MUST detach us from master device. */
|
||||
WARN_ON(dev->master);
|
||||
@@ -4016,7 +4191,7 @@ int register_netdevice(struct net_device *dev)
|
||||
struct hlist_head *head;
|
||||
struct hlist_node *p;
|
||||
int ret;
|
||||
struct net *net;
|
||||
struct net *net = dev_net(dev);
|
||||
|
||||
BUG_ON(dev_boot_phase);
|
||||
ASSERT_RTNL();
|
||||
@@ -4025,8 +4200,7 @@ int register_netdevice(struct net_device *dev)
|
||||
|
||||
/* When net_device's are persistent, this will be fatal. */
|
||||
BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
|
||||
BUG_ON(!dev_net(dev));
|
||||
net = dev_net(dev);
|
||||
BUG_ON(!net);
|
||||
|
||||
spin_lock_init(&dev->addr_list_lock);
|
||||
netdev_set_addr_lockdep_class(dev);
|
||||
@@ -4034,9 +4208,46 @@ int register_netdevice(struct net_device *dev)
|
||||
|
||||
dev->iflink = -1;
|
||||
|
||||
#ifdef CONFIG_COMPAT_NET_DEV_OPS
|
||||
/* Netdevice_ops API compatiability support.
|
||||
* This is temporary until all network devices are converted.
|
||||
*/
|
||||
if (dev->netdev_ops) {
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
|
||||
dev->init = ops->ndo_init;
|
||||
dev->uninit = ops->ndo_uninit;
|
||||
dev->open = ops->ndo_open;
|
||||
dev->change_rx_flags = ops->ndo_change_rx_flags;
|
||||
dev->set_rx_mode = ops->ndo_set_rx_mode;
|
||||
dev->set_multicast_list = ops->ndo_set_multicast_list;
|
||||
dev->set_mac_address = ops->ndo_set_mac_address;
|
||||
dev->validate_addr = ops->ndo_validate_addr;
|
||||
dev->do_ioctl = ops->ndo_do_ioctl;
|
||||
dev->set_config = ops->ndo_set_config;
|
||||
dev->change_mtu = ops->ndo_change_mtu;
|
||||
dev->tx_timeout = ops->ndo_tx_timeout;
|
||||
dev->get_stats = ops->ndo_get_stats;
|
||||
dev->vlan_rx_register = ops->ndo_vlan_rx_register;
|
||||
dev->vlan_rx_add_vid = ops->ndo_vlan_rx_add_vid;
|
||||
dev->vlan_rx_kill_vid = ops->ndo_vlan_rx_kill_vid;
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
dev->poll_controller = ops->ndo_poll_controller;
|
||||
#endif
|
||||
} else {
|
||||
char drivername[64];
|
||||
pr_info("%s (%s): not using net_device_ops yet\n",
|
||||
dev->name, netdev_drivername(dev, drivername, 64));
|
||||
|
||||
/* This works only because net_device_ops and the
|
||||
compatiablity structure are the same. */
|
||||
dev->netdev_ops = (void *) &(dev->init);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Init, if this function is available */
|
||||
if (dev->init) {
|
||||
ret = dev->init(dev);
|
||||
if (dev->netdev_ops->ndo_init) {
|
||||
ret = dev->netdev_ops->ndo_init(dev);
|
||||
if (ret) {
|
||||
if (ret > 0)
|
||||
ret = -EIO;
|
||||
@@ -4114,8 +4325,8 @@ out:
|
||||
return ret;
|
||||
|
||||
err_uninit:
|
||||
if (dev->uninit)
|
||||
dev->uninit(dev);
|
||||
if (dev->netdev_ops->ndo_uninit)
|
||||
dev->netdev_ops->ndo_uninit(dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -4271,10 +4482,24 @@ void netdev_run_todo(void)
|
||||
}
|
||||
}
|
||||
|
||||
static struct net_device_stats *internal_stats(struct net_device *dev)
|
||||
{
|
||||
return &dev->stats;
|
||||
/**
|
||||
* dev_get_stats - get network device statistics
|
||||
* @dev: device to get statistics from
|
||||
*
|
||||
* Get network statistics from device. The device driver may provide
|
||||
* its own method by setting dev->netdev_ops->get_stats; otherwise
|
||||
* the internal statistics structure is used.
|
||||
*/
|
||||
const struct net_device_stats *dev_get_stats(struct net_device *dev)
|
||||
{
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
|
||||
if (ops->ndo_get_stats)
|
||||
return ops->ndo_get_stats(dev);
|
||||
else
|
||||
return &dev->stats;
|
||||
}
|
||||
EXPORT_SYMBOL(dev_get_stats);
|
||||
|
||||
static void netdev_init_one_queue(struct net_device *dev,
|
||||
struct netdev_queue *queue,
|
||||
@@ -4343,18 +4568,11 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
|
||||
dev->num_tx_queues = queue_count;
|
||||
dev->real_num_tx_queues = queue_count;
|
||||
|
||||
if (sizeof_priv) {
|
||||
dev->priv = ((char *)dev +
|
||||
((sizeof(struct net_device) + NETDEV_ALIGN_CONST)
|
||||
& ~NETDEV_ALIGN_CONST));
|
||||
}
|
||||
|
||||
dev->gso_max_size = GSO_MAX_SIZE;
|
||||
|
||||
netdev_init_queues(dev);
|
||||
|
||||
dev->get_stats = internal_stats;
|
||||
netpoll_netdev_init(dev);
|
||||
INIT_LIST_HEAD(&dev->napi_list);
|
||||
setup(dev);
|
||||
strcpy(dev->name, name);
|
||||
return dev;
|
||||
@@ -4371,10 +4589,15 @@ EXPORT_SYMBOL(alloc_netdev_mq);
|
||||
*/
|
||||
void free_netdev(struct net_device *dev)
|
||||
{
|
||||
struct napi_struct *p, *n;
|
||||
|
||||
release_net(dev_net(dev));
|
||||
|
||||
kfree(dev->_tx);
|
||||
|
||||
list_for_each_entry_safe(p, n, &dev->napi_list, dev_list)
|
||||
netif_napi_del(p);
|
||||
|
||||
/* Compatibility with error handling in drivers */
|
||||
if (dev->reg_state == NETREG_UNINITIALIZED) {
|
||||
kfree((char *)dev - dev->padded);
|
||||
@@ -4467,6 +4690,15 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
|
||||
if (dev->features & NETIF_F_NETNS_LOCAL)
|
||||
goto out;
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
/* Don't allow real devices to be moved when sysfs
|
||||
* is enabled.
|
||||
*/
|
||||
err = -EINVAL;
|
||||
if (dev->dev.parent)
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
/* Ensure the device has been registrered */
|
||||
err = -EINVAL;
|
||||
if (dev->reg_state != NETREG_REGISTERED)
|
||||
@@ -4524,6 +4756,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
|
||||
*/
|
||||
dev_addr_discard(dev);
|
||||
|
||||
netdev_unregister_kobject(dev);
|
||||
|
||||
/* Actually switch the network namespace */
|
||||
dev_net_set(dev, net);
|
||||
|
||||
@@ -4540,7 +4774,6 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
|
||||
}
|
||||
|
||||
/* Fixup kobjects */
|
||||
netdev_unregister_kobject(dev);
|
||||
err = netdev_register_kobject(dev);
|
||||
WARN_ON(err);
|
||||
|
||||
@@ -4847,6 +5080,12 @@ static void __net_exit default_device_exit(struct net *net)
|
||||
if (dev->features & NETIF_F_NETNS_LOCAL)
|
||||
continue;
|
||||
|
||||
/* Delete virtual devices */
|
||||
if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink) {
|
||||
dev->rtnl_link_ops->dellink(dev);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Push remaing network devices to init_net */
|
||||
snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex);
|
||||
err = dev_change_net_namespace(dev, &init_net, fb_name);
|
||||
@@ -4893,9 +5132,6 @@ static int __init net_dev_init(void)
|
||||
if (register_pernet_subsys(&netdev_net_ops))
|
||||
goto out;
|
||||
|
||||
if (register_pernet_device(&default_device_ops))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Initialise the packet receive queues.
|
||||
*/
|
||||
@@ -4910,12 +5146,28 @@ static int __init net_dev_init(void)
|
||||
|
||||
queue->backlog.poll = process_backlog;
|
||||
queue->backlog.weight = weight_p;
|
||||
queue->backlog.gro_list = NULL;
|
||||
}
|
||||
|
||||
netdev_dma_register();
|
||||
|
||||
dev_boot_phase = 0;
|
||||
|
||||
/* The loopback device is special if any other network devices
|
||||
* is present in a network namespace the loopback device must
|
||||
* be present. Since we now dynamically allocate and free the
|
||||
* loopback device ensure this invariant is maintained by
|
||||
* keeping the loopback device as the first device on the
|
||||
* list of network devices. Ensuring the loopback devices
|
||||
* is the first device that appears and the last network device
|
||||
* that disappears.
|
||||
*/
|
||||
if (register_pernet_device(&loopback_net_ops))
|
||||
goto out;
|
||||
|
||||
if (register_pernet_device(&default_device_ops))
|
||||
goto out;
|
||||
|
||||
netdev_dma_register();
|
||||
|
||||
open_softirq(NET_TX_SOFTIRQ, net_tx_action);
|
||||
open_softirq(NET_RX_SOFTIRQ, net_rx_action);
|
||||
|
||||
|
@@ -263,9 +263,11 @@ again:
|
||||
void dst_release(struct dst_entry *dst)
|
||||
{
|
||||
if (dst) {
|
||||
WARN_ON(atomic_read(&dst->__refcnt) < 1);
|
||||
int newrefcnt;
|
||||
|
||||
smp_mb__before_atomic_dec();
|
||||
atomic_dec(&dst->__refcnt);
|
||||
newrefcnt = atomic_dec_return(&dst->__refcnt);
|
||||
WARN_ON(newrefcnt < 0);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(dst_release);
|
||||
|
@@ -528,6 +528,22 @@ static int ethtool_set_tx_csum(struct net_device *dev, char __user *useraddr)
|
||||
return dev->ethtool_ops->set_tx_csum(dev, edata.data);
|
||||
}
|
||||
|
||||
static int ethtool_set_rx_csum(struct net_device *dev, char __user *useraddr)
|
||||
{
|
||||
struct ethtool_value edata;
|
||||
|
||||
if (!dev->ethtool_ops->set_rx_csum)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (copy_from_user(&edata, useraddr, sizeof(edata)))
|
||||
return -EFAULT;
|
||||
|
||||
if (!edata.data && dev->ethtool_ops->set_sg)
|
||||
dev->features &= ~NETIF_F_GRO;
|
||||
|
||||
return dev->ethtool_ops->set_rx_csum(dev, edata.data);
|
||||
}
|
||||
|
||||
static int ethtool_set_sg(struct net_device *dev, char __user *useraddr)
|
||||
{
|
||||
struct ethtool_value edata;
|
||||
@@ -599,6 +615,34 @@ static int ethtool_set_gso(struct net_device *dev, char __user *useraddr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ethtool_get_gro(struct net_device *dev, char __user *useraddr)
|
||||
{
|
||||
struct ethtool_value edata = { ETHTOOL_GGRO };
|
||||
|
||||
edata.data = dev->features & NETIF_F_GRO;
|
||||
if (copy_to_user(useraddr, &edata, sizeof(edata)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ethtool_set_gro(struct net_device *dev, char __user *useraddr)
|
||||
{
|
||||
struct ethtool_value edata;
|
||||
|
||||
if (copy_from_user(&edata, useraddr, sizeof(edata)))
|
||||
return -EFAULT;
|
||||
|
||||
if (edata.data) {
|
||||
if (!dev->ethtool_ops->get_rx_csum ||
|
||||
!dev->ethtool_ops->get_rx_csum(dev))
|
||||
return -EINVAL;
|
||||
dev->features |= NETIF_F_GRO;
|
||||
} else
|
||||
dev->features &= ~NETIF_F_GRO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
|
||||
{
|
||||
struct ethtool_test test;
|
||||
@@ -932,8 +976,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
|
||||
dev->ethtool_ops->get_rx_csum);
|
||||
break;
|
||||
case ETHTOOL_SRXCSUM:
|
||||
rc = ethtool_set_value(dev, useraddr,
|
||||
dev->ethtool_ops->set_rx_csum);
|
||||
rc = ethtool_set_rx_csum(dev, useraddr);
|
||||
break;
|
||||
case ETHTOOL_GTXCSUM:
|
||||
rc = ethtool_get_value(dev, useraddr, ethcmd,
|
||||
@@ -1014,6 +1057,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
|
||||
case ETHTOOL_SRXFH:
|
||||
rc = ethtool_set_rxhash(dev, useraddr);
|
||||
break;
|
||||
case ETHTOOL_GGRO:
|
||||
rc = ethtool_get_gro(dev, useraddr);
|
||||
break;
|
||||
case ETHTOOL_SGRO:
|
||||
rc = ethtool_set_gro(dev, useraddr);
|
||||
break;
|
||||
default:
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
|
@@ -664,17 +664,18 @@ static int __init fib_rules_init(void)
|
||||
rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL);
|
||||
rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule);
|
||||
|
||||
err = register_netdevice_notifier(&fib_rules_notifier);
|
||||
err = register_pernet_subsys(&fib_rules_net_ops);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
err = register_pernet_subsys(&fib_rules_net_ops);
|
||||
err = register_netdevice_notifier(&fib_rules_notifier);
|
||||
if (err < 0)
|
||||
goto fail_unregister;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_unregister:
|
||||
unregister_netdevice_notifier(&fib_rules_notifier);
|
||||
unregister_pernet_subsys(&fib_rules_net_ops);
|
||||
fail:
|
||||
rtnl_unregister(PF_UNSPEC, RTM_NEWRULE);
|
||||
rtnl_unregister(PF_UNSPEC, RTM_DELRULE);
|
||||
|
@@ -319,6 +319,25 @@ load_b:
|
||||
A = 0;
|
||||
continue;
|
||||
}
|
||||
case SKF_AD_NLATTR_NEST: {
|
||||
struct nlattr *nla;
|
||||
|
||||
if (skb_is_nonlinear(skb))
|
||||
return 0;
|
||||
if (A > skb->len - sizeof(struct nlattr))
|
||||
return 0;
|
||||
|
||||
nla = (struct nlattr *)&skb->data[A];
|
||||
if (nla->nla_len > A - skb->len)
|
||||
return 0;
|
||||
|
||||
nla = nla_find_nested(nla, X);
|
||||
if (nla)
|
||||
A = (void *)nla - (void *)skb->data;
|
||||
else
|
||||
A = 0;
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@@ -165,7 +165,7 @@ static int flow_key_compare(struct flowi *key1, struct flowi *key2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
|
||||
void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir,
|
||||
flow_resolve_t resolver)
|
||||
{
|
||||
struct flow_cache_entry *fle, **head;
|
||||
@@ -225,7 +225,7 @@ nocache:
|
||||
void *obj;
|
||||
atomic_t *obj_ref;
|
||||
|
||||
err = resolver(key, family, dir, &obj, &obj_ref);
|
||||
err = resolver(net, key, family, dir, &obj, &obj_ref);
|
||||
|
||||
if (fle && !err) {
|
||||
fle->genid = atomic_read(&flow_cache_genid);
|
||||
@@ -307,7 +307,7 @@ void flow_cache_flush(void)
|
||||
put_online_cpus();
|
||||
}
|
||||
|
||||
static void __devinit flow_cache_cpu_prepare(int cpu)
|
||||
static void __init flow_cache_cpu_prepare(int cpu)
|
||||
{
|
||||
struct tasklet_struct *tasklet;
|
||||
unsigned long order;
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/gen_stats.h>
|
||||
|
||||
@@ -89,6 +90,7 @@ struct gen_estimator
|
||||
u32 avpps;
|
||||
u32 avbps;
|
||||
struct rcu_head e_rcu;
|
||||
struct rb_node node;
|
||||
};
|
||||
|
||||
struct gen_estimator_head
|
||||
@@ -102,6 +104,9 @@ static struct gen_estimator_head elist[EST_MAX_INTERVAL+1];
|
||||
/* Protects against NULL dereference */
|
||||
static DEFINE_RWLOCK(est_lock);
|
||||
|
||||
/* Protects against soft lockup during large deletion */
|
||||
static struct rb_root est_root = RB_ROOT;
|
||||
|
||||
static void est_timer(unsigned long arg)
|
||||
{
|
||||
int idx = (int)arg;
|
||||
@@ -139,6 +144,46 @@ skip:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void gen_add_node(struct gen_estimator *est)
|
||||
{
|
||||
struct rb_node **p = &est_root.rb_node, *parent = NULL;
|
||||
|
||||
while (*p) {
|
||||
struct gen_estimator *e;
|
||||
|
||||
parent = *p;
|
||||
e = rb_entry(parent, struct gen_estimator, node);
|
||||
|
||||
if (est->bstats > e->bstats)
|
||||
p = &parent->rb_right;
|
||||
else
|
||||
p = &parent->rb_left;
|
||||
}
|
||||
rb_link_node(&est->node, parent, p);
|
||||
rb_insert_color(&est->node, &est_root);
|
||||
}
|
||||
|
||||
static
|
||||
struct gen_estimator *gen_find_node(const struct gnet_stats_basic *bstats,
|
||||
const struct gnet_stats_rate_est *rate_est)
|
||||
{
|
||||
struct rb_node *p = est_root.rb_node;
|
||||
|
||||
while (p) {
|
||||
struct gen_estimator *e;
|
||||
|
||||
e = rb_entry(p, struct gen_estimator, node);
|
||||
|
||||
if (bstats > e->bstats)
|
||||
p = p->rb_right;
|
||||
else if (bstats < e->bstats || rate_est != e->rate_est)
|
||||
p = p->rb_left;
|
||||
else
|
||||
return e;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gen_new_estimator - create a new rate estimator
|
||||
* @bstats: basic statistics
|
||||
@@ -194,8 +239,11 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
|
||||
mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx));
|
||||
|
||||
list_add_rcu(&est->list, &elist[idx].list);
|
||||
gen_add_node(est);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(gen_new_estimator);
|
||||
|
||||
static void __gen_kill_estimator(struct rcu_head *head)
|
||||
{
|
||||
@@ -209,36 +257,27 @@ static void __gen_kill_estimator(struct rcu_head *head)
|
||||
* @bstats: basic statistics
|
||||
* @rate_est: rate estimator statistics
|
||||
*
|
||||
* Removes the rate estimator specified by &bstats and &rate_est
|
||||
* and deletes the timer.
|
||||
* Removes the rate estimator specified by &bstats and &rate_est.
|
||||
*
|
||||
* NOTE: Called under rtnl_mutex
|
||||
*/
|
||||
void gen_kill_estimator(struct gnet_stats_basic *bstats,
|
||||
struct gnet_stats_rate_est *rate_est)
|
||||
struct gnet_stats_rate_est *rate_est)
|
||||
{
|
||||
int idx;
|
||||
struct gen_estimator *e, *n;
|
||||
struct gen_estimator *e;
|
||||
|
||||
for (idx=0; idx <= EST_MAX_INTERVAL; idx++) {
|
||||
while ((e = gen_find_node(bstats, rate_est))) {
|
||||
rb_erase(&e->node, &est_root);
|
||||
|
||||
/* Skip non initialized indexes */
|
||||
if (!elist[idx].timer.function)
|
||||
continue;
|
||||
write_lock_bh(&est_lock);
|
||||
e->bstats = NULL;
|
||||
write_unlock_bh(&est_lock);
|
||||
|
||||
list_for_each_entry_safe(e, n, &elist[idx].list, list) {
|
||||
if (e->rate_est != rate_est || e->bstats != bstats)
|
||||
continue;
|
||||
|
||||
write_lock_bh(&est_lock);
|
||||
e->bstats = NULL;
|
||||
write_unlock_bh(&est_lock);
|
||||
|
||||
list_del_rcu(&e->list);
|
||||
call_rcu(&e->e_rcu, __gen_kill_estimator);
|
||||
}
|
||||
list_del_rcu(&e->list);
|
||||
call_rcu(&e->e_rcu, __gen_kill_estimator);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(gen_kill_estimator);
|
||||
|
||||
/**
|
||||
* gen_replace_estimator - replace rate estimator configuration
|
||||
@@ -259,8 +298,20 @@ int gen_replace_estimator(struct gnet_stats_basic *bstats,
|
||||
gen_kill_estimator(bstats, rate_est);
|
||||
return gen_new_estimator(bstats, rate_est, stats_lock, opt);
|
||||
}
|
||||
|
||||
|
||||
EXPORT_SYMBOL(gen_kill_estimator);
|
||||
EXPORT_SYMBOL(gen_new_estimator);
|
||||
EXPORT_SYMBOL(gen_replace_estimator);
|
||||
|
||||
/**
|
||||
* gen_estimator_active - test if estimator is currently in use
|
||||
* @bstats: basic statistics
|
||||
* @rate_est: rate estimator statistics
|
||||
*
|
||||
* Returns true if estimator is active, and false if not.
|
||||
*/
|
||||
bool gen_estimator_active(const struct gnet_stats_basic *bstats,
|
||||
const struct gnet_stats_rate_est *rate_est)
|
||||
{
|
||||
ASSERT_RTNL();
|
||||
|
||||
return gen_find_node(bstats, rate_est) != NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(gen_estimator_active);
|
||||
|
@@ -531,9 +531,7 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
|
||||
if (!n)
|
||||
goto out;
|
||||
|
||||
#ifdef CONFIG_NET_NS
|
||||
n->net = hold_net(net);
|
||||
#endif
|
||||
write_pnet(&n->net, hold_net(net));
|
||||
memcpy(n->key, pkey, key_len);
|
||||
n->dev = dev;
|
||||
if (dev)
|
||||
@@ -1329,9 +1327,9 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
|
||||
struct neigh_table *tbl)
|
||||
{
|
||||
struct neigh_parms *p, *ref;
|
||||
struct net *net;
|
||||
struct net *net = dev_net(dev);
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
|
||||
net = dev_net(dev);
|
||||
ref = lookup_neigh_params(tbl, net, 0);
|
||||
if (!ref)
|
||||
return NULL;
|
||||
@@ -1340,20 +1338,17 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
|
||||
if (p) {
|
||||
p->tbl = tbl;
|
||||
atomic_set(&p->refcnt, 1);
|
||||
INIT_RCU_HEAD(&p->rcu_head);
|
||||
p->reachable_time =
|
||||
neigh_rand_reach_time(p->base_reachable_time);
|
||||
|
||||
if (dev->neigh_setup && dev->neigh_setup(dev, p)) {
|
||||
if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
|
||||
kfree(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev_hold(dev);
|
||||
p->dev = dev;
|
||||
#ifdef CONFIG_NET_NS
|
||||
p->net = hold_net(net);
|
||||
#endif
|
||||
write_pnet(&p->net, hold_net(net));
|
||||
p->sysctl_table = NULL;
|
||||
write_lock_bh(&tbl->lock);
|
||||
p->next = tbl->parms.next;
|
||||
@@ -1408,11 +1403,8 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
|
||||
unsigned long now = jiffies;
|
||||
unsigned long phsize;
|
||||
|
||||
#ifdef CONFIG_NET_NS
|
||||
tbl->parms.net = &init_net;
|
||||
#endif
|
||||
write_pnet(&tbl->parms.net, &init_net);
|
||||
atomic_set(&tbl->parms.refcnt, 1);
|
||||
INIT_RCU_HEAD(&tbl->parms.rcu_head);
|
||||
tbl->parms.reachable_time =
|
||||
neigh_rand_reach_time(tbl->parms.base_reachable_time);
|
||||
|
||||
@@ -1426,9 +1418,8 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
|
||||
panic("cannot create neighbour cache statistics");
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
tbl->pde = proc_create_data(tbl->id, 0, init_net.proc_net_stat,
|
||||
&neigh_stat_seq_fops, tbl);
|
||||
if (!tbl->pde)
|
||||
if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
|
||||
&neigh_stat_seq_fops, tbl))
|
||||
panic("cannot create neighbour proc dir entry");
|
||||
#endif
|
||||
|
||||
@@ -2568,128 +2559,128 @@ static struct neigh_sysctl_table {
|
||||
.procname = "mcast_solicit",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_NEIGH_UCAST_SOLICIT,
|
||||
.procname = "ucast_solicit",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_NEIGH_APP_SOLICIT,
|
||||
.procname = "app_solicit",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.procname = "retrans_time",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_userhz_jiffies,
|
||||
.proc_handler = proc_dointvec_userhz_jiffies,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_NEIGH_REACHABLE_TIME,
|
||||
.procname = "base_reachable_time",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_jiffies,
|
||||
.strategy = &sysctl_jiffies,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
.strategy = sysctl_jiffies,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_NEIGH_DELAY_PROBE_TIME,
|
||||
.procname = "delay_first_probe_time",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_jiffies,
|
||||
.strategy = &sysctl_jiffies,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
.strategy = sysctl_jiffies,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_NEIGH_GC_STALE_TIME,
|
||||
.procname = "gc_stale_time",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_jiffies,
|
||||
.strategy = &sysctl_jiffies,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
.strategy = sysctl_jiffies,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_NEIGH_UNRES_QLEN,
|
||||
.procname = "unres_qlen",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_NEIGH_PROXY_QLEN,
|
||||
.procname = "proxy_qlen",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.procname = "anycast_delay",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_userhz_jiffies,
|
||||
.proc_handler = proc_dointvec_userhz_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "proxy_delay",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_userhz_jiffies,
|
||||
.proc_handler = proc_dointvec_userhz_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "locktime",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_userhz_jiffies,
|
||||
.proc_handler = proc_dointvec_userhz_jiffies,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_NEIGH_RETRANS_TIME_MS,
|
||||
.procname = "retrans_time_ms",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_ms_jiffies,
|
||||
.strategy = &sysctl_ms_jiffies,
|
||||
.proc_handler = proc_dointvec_ms_jiffies,
|
||||
.strategy = sysctl_ms_jiffies,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_NEIGH_REACHABLE_TIME_MS,
|
||||
.procname = "base_reachable_time_ms",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_ms_jiffies,
|
||||
.strategy = &sysctl_ms_jiffies,
|
||||
.proc_handler = proc_dointvec_ms_jiffies,
|
||||
.strategy = sysctl_ms_jiffies,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_NEIGH_GC_INTERVAL,
|
||||
.procname = "gc_interval",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_jiffies,
|
||||
.strategy = &sysctl_jiffies,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
.strategy = sysctl_jiffies,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_NEIGH_GC_THRESH1,
|
||||
.procname = "gc_thresh1",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_NEIGH_GC_THRESH2,
|
||||
.procname = "gc_thresh2",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_NEIGH_GC_THRESH3,
|
||||
.procname = "gc_thresh3",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{},
|
||||
},
|
||||
|
@@ -270,7 +270,6 @@ static ssize_t netstat_show(const struct device *d,
|
||||
unsigned long offset)
|
||||
{
|
||||
struct net_device *dev = to_net_dev(d);
|
||||
struct net_device_stats *stats;
|
||||
ssize_t ret = -EINVAL;
|
||||
|
||||
WARN_ON(offset > sizeof(struct net_device_stats) ||
|
||||
@@ -278,7 +277,7 @@ static ssize_t netstat_show(const struct device *d,
|
||||
|
||||
read_lock(&dev_base_lock);
|
||||
if (dev_isalive(dev)) {
|
||||
stats = dev->get_stats(dev);
|
||||
const struct net_device_stats *stats = dev_get_stats(dev);
|
||||
ret = sprintf(buf, fmt_ulong,
|
||||
*(unsigned long *)(((u8 *) stats) + offset));
|
||||
}
|
||||
@@ -428,6 +427,9 @@ static int netdev_uevent(struct device *d, struct kobj_uevent_env *env)
|
||||
struct net_device *dev = to_net_dev(d);
|
||||
int retval;
|
||||
|
||||
if (!net_eq(dev_net(dev), &init_net))
|
||||
return 0;
|
||||
|
||||
/* pass interface to uevent. */
|
||||
retval = add_uevent_var(env, "INTERFACE=%s", dev->name);
|
||||
if (retval)
|
||||
@@ -476,6 +478,10 @@ void netdev_unregister_kobject(struct net_device * net)
|
||||
struct device *dev = &(net->dev);
|
||||
|
||||
kobject_get(&dev->kobj);
|
||||
|
||||
if (dev_net(net) != &init_net)
|
||||
return;
|
||||
|
||||
device_del(dev);
|
||||
}
|
||||
|
||||
@@ -490,7 +496,7 @@ int netdev_register_kobject(struct net_device *net)
|
||||
dev->groups = groups;
|
||||
|
||||
BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ);
|
||||
strlcpy(dev->bus_id, net->name, BUS_ID_SIZE);
|
||||
dev_set_name(dev, net->name);
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
*groups++ = &netstat_group;
|
||||
@@ -501,6 +507,9 @@ int netdev_register_kobject(struct net_device *net)
|
||||
#endif
|
||||
#endif /* CONFIG_SYSFS */
|
||||
|
||||
if (dev_net(net) != &init_net)
|
||||
return 0;
|
||||
|
||||
return device_add(dev);
|
||||
}
|
||||
|
||||
|
@@ -47,7 +47,6 @@ static __net_init int setup_net(struct net *net)
|
||||
goto out;
|
||||
|
||||
ng->len = INITIAL_NET_GEN_PTRS;
|
||||
INIT_RCU_HEAD(&ng->rcu);
|
||||
rcu_assign_pointer(net->gen, ng);
|
||||
|
||||
error = 0;
|
||||
@@ -478,7 +477,6 @@ int net_assign_generic(struct net *net, int id, void *data)
|
||||
*/
|
||||
|
||||
ng->len = id;
|
||||
INIT_RCU_HEAD(&ng->rcu);
|
||||
memcpy(&ng->ptr, &old_ng->ptr, old_ng->len);
|
||||
|
||||
rcu_assign_pointer(net->gen, ng);
|
||||
|
@@ -58,6 +58,7 @@ static void queue_process(struct work_struct *work)
|
||||
|
||||
while ((skb = skb_dequeue(&npinfo->txq))) {
|
||||
struct net_device *dev = skb->dev;
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
struct netdev_queue *txq;
|
||||
|
||||
if (!netif_device_present(dev) || !netif_running(dev)) {
|
||||
@@ -71,7 +72,7 @@ static void queue_process(struct work_struct *work)
|
||||
__netif_tx_lock(txq, smp_processor_id());
|
||||
if (netif_tx_queue_stopped(txq) ||
|
||||
netif_tx_queue_frozen(txq) ||
|
||||
dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
|
||||
ops->ndo_start_xmit(skb, dev) != NETDEV_TX_OK) {
|
||||
skb_queue_head(&npinfo->txq, skb);
|
||||
__netif_tx_unlock(txq);
|
||||
local_irq_restore(flags);
|
||||
@@ -174,12 +175,13 @@ static void service_arp_queue(struct netpoll_info *npi)
|
||||
void netpoll_poll(struct netpoll *np)
|
||||
{
|
||||
struct net_device *dev = np->dev;
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
|
||||
if (!dev || !netif_running(dev) || !dev->poll_controller)
|
||||
if (!dev || !netif_running(dev) || !ops->ndo_poll_controller)
|
||||
return;
|
||||
|
||||
/* Process pending work on NIC */
|
||||
dev->poll_controller(dev);
|
||||
ops->ndo_poll_controller(dev);
|
||||
|
||||
poll_napi(dev);
|
||||
|
||||
@@ -274,6 +276,7 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
|
||||
int status = NETDEV_TX_BUSY;
|
||||
unsigned long tries;
|
||||
struct net_device *dev = np->dev;
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
struct netpoll_info *npinfo = np->dev->npinfo;
|
||||
|
||||
if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) {
|
||||
@@ -294,7 +297,7 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
|
||||
tries > 0; --tries) {
|
||||
if (__netif_tx_trylock(txq)) {
|
||||
if (!netif_tx_queue_stopped(txq))
|
||||
status = dev->hard_start_xmit(skb, dev);
|
||||
status = ops->ndo_start_xmit(skb, dev);
|
||||
__netif_tx_unlock(txq);
|
||||
|
||||
if (status == NETDEV_TX_OK)
|
||||
@@ -345,7 +348,7 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
|
||||
udph->check = csum_tcpudp_magic(htonl(np->local_ip),
|
||||
htonl(np->remote_ip),
|
||||
udp_len, IPPROTO_UDP,
|
||||
csum_partial((unsigned char *)udph, udp_len, 0));
|
||||
csum_partial(udph, udp_len, 0));
|
||||
if (udph->check == 0)
|
||||
udph->check = CSUM_MANGLED_0;
|
||||
|
||||
@@ -555,7 +558,6 @@ out:
|
||||
|
||||
void netpoll_print_options(struct netpoll *np)
|
||||
{
|
||||
DECLARE_MAC_BUF(mac);
|
||||
printk(KERN_INFO "%s: local port %d\n",
|
||||
np->name, np->local_port);
|
||||
printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
|
||||
@@ -566,8 +568,8 @@ void netpoll_print_options(struct netpoll *np)
|
||||
np->name, np->remote_port);
|
||||
printk(KERN_INFO "%s: remote IP %d.%d.%d.%d\n",
|
||||
np->name, HIPQUAD(np->remote_ip));
|
||||
printk(KERN_INFO "%s: remote ethernet address %s\n",
|
||||
np->name, print_mac(mac, np->remote_mac));
|
||||
printk(KERN_INFO "%s: remote ethernet address %pM\n",
|
||||
np->name, np->remote_mac);
|
||||
}
|
||||
|
||||
int netpoll_parse_options(struct netpoll *np, char *opt)
|
||||
@@ -697,7 +699,7 @@ int netpoll_setup(struct netpoll *np)
|
||||
atomic_inc(&npinfo->refcnt);
|
||||
}
|
||||
|
||||
if (!ndev->poll_controller) {
|
||||
if (!ndev->netdev_ops->ndo_poll_controller) {
|
||||
printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
|
||||
np->name, np->dev_name);
|
||||
err = -ENOTSUPP;
|
||||
|
@@ -422,6 +422,7 @@ static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
|
||||
const char *ifname);
|
||||
static int pktgen_device_event(struct notifier_block *, unsigned long, void *);
|
||||
static void pktgen_run_all_threads(void);
|
||||
static void pktgen_reset_all_threads(void);
|
||||
static void pktgen_stop_all_threads_ifs(void);
|
||||
static int pktgen_stop_device(struct pktgen_dev *pkt_dev);
|
||||
static void pktgen_stop(struct pktgen_thread *t);
|
||||
@@ -480,6 +481,9 @@ static ssize_t pgctrl_write(struct file *file, const char __user * buf,
|
||||
else if (!strcmp(data, "start"))
|
||||
pktgen_run_all_threads();
|
||||
|
||||
else if (!strcmp(data, "reset"))
|
||||
pktgen_reset_all_threads();
|
||||
|
||||
else
|
||||
printk(KERN_WARNING "pktgen: Unknown command: %s\n", data);
|
||||
|
||||
@@ -509,7 +513,6 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
|
||||
__u64 sa;
|
||||
__u64 stopped;
|
||||
__u64 now = getCurUs();
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
seq_printf(seq,
|
||||
"Params: count %llu min_pkt_size: %u max_pkt_size: %u\n",
|
||||
@@ -554,12 +557,12 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
|
||||
|
||||
seq_puts(seq, " src_mac: ");
|
||||
|
||||
seq_printf(seq, "%s ",
|
||||
print_mac(mac, is_zero_ether_addr(pkt_dev->src_mac) ?
|
||||
pkt_dev->odev->dev_addr : pkt_dev->src_mac));
|
||||
seq_printf(seq, "%pM ",
|
||||
is_zero_ether_addr(pkt_dev->src_mac) ?
|
||||
pkt_dev->odev->dev_addr : pkt_dev->src_mac);
|
||||
|
||||
seq_printf(seq, "dst_mac: ");
|
||||
seq_printf(seq, "%s\n", print_mac(mac, pkt_dev->dst_mac));
|
||||
seq_printf(seq, "%pM\n", pkt_dev->dst_mac);
|
||||
|
||||
seq_printf(seq,
|
||||
" udp_src_min: %d udp_src_max: %d udp_dst_min: %d udp_dst_max: %d\n",
|
||||
@@ -2162,7 +2165,8 @@ static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
|
||||
struct xfrm_state *x = pkt_dev->flows[flow].x;
|
||||
if (!x) {
|
||||
/*slow path: we dont already have xfrm_state*/
|
||||
x = xfrm_stateonly_find((xfrm_address_t *)&pkt_dev->cur_daddr,
|
||||
x = xfrm_stateonly_find(&init_net,
|
||||
(xfrm_address_t *)&pkt_dev->cur_daddr,
|
||||
(xfrm_address_t *)&pkt_dev->cur_saddr,
|
||||
AF_INET,
|
||||
pkt_dev->ipsmode,
|
||||
@@ -3169,6 +3173,24 @@ static void pktgen_run_all_threads(void)
|
||||
pktgen_wait_all_threads_run();
|
||||
}
|
||||
|
||||
static void pktgen_reset_all_threads(void)
|
||||
{
|
||||
struct pktgen_thread *t;
|
||||
|
||||
pr_debug("pktgen: entering pktgen_reset_all_threads.\n");
|
||||
|
||||
mutex_lock(&pktgen_thread_lock);
|
||||
|
||||
list_for_each_entry(t, &pktgen_threads, th_list)
|
||||
t->control |= (T_REMDEVALL);
|
||||
|
||||
mutex_unlock(&pktgen_thread_lock);
|
||||
|
||||
schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */
|
||||
|
||||
pktgen_wait_all_threads_run();
|
||||
}
|
||||
|
||||
static void show_results(struct pktgen_dev *pkt_dev, int nr_frags)
|
||||
{
|
||||
__u64 total_us, bps, mbps, pps, idle;
|
||||
@@ -3331,14 +3353,14 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
|
||||
|
||||
static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
|
||||
{
|
||||
struct net_device *odev = NULL;
|
||||
struct net_device *odev = pkt_dev->odev;
|
||||
int (*xmit)(struct sk_buff *, struct net_device *)
|
||||
= odev->netdev_ops->ndo_start_xmit;
|
||||
struct netdev_queue *txq;
|
||||
__u64 idle_start = 0;
|
||||
u16 queue_map;
|
||||
int ret;
|
||||
|
||||
odev = pkt_dev->odev;
|
||||
|
||||
if (pkt_dev->delay_us || pkt_dev->delay_ns) {
|
||||
u64 now;
|
||||
|
||||
@@ -3419,7 +3441,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
|
||||
|
||||
atomic_inc(&(pkt_dev->skb->users));
|
||||
retry_now:
|
||||
ret = odev->hard_start_xmit(pkt_dev->skb, odev);
|
||||
ret = (*xmit)(pkt_dev->skb, odev);
|
||||
if (likely(ret == NETDEV_TX_OK)) {
|
||||
pkt_dev->last_ok = 1;
|
||||
pkt_dev->sofar++;
|
||||
|
@@ -551,7 +551,7 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
|
||||
}
|
||||
|
||||
static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
|
||||
struct net_device_stats *b)
|
||||
const struct net_device_stats *b)
|
||||
{
|
||||
a->rx_packets = b->rx_packets;
|
||||
a->tx_packets = b->tx_packets;
|
||||
@@ -609,7 +609,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
|
||||
struct netdev_queue *txq;
|
||||
struct ifinfomsg *ifm;
|
||||
struct nlmsghdr *nlh;
|
||||
struct net_device_stats *stats;
|
||||
const struct net_device_stats *stats;
|
||||
struct nlattr *attr;
|
||||
|
||||
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
|
||||
@@ -666,7 +666,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
|
||||
if (attr == NULL)
|
||||
goto nla_put_failure;
|
||||
|
||||
stats = dev->get_stats(dev);
|
||||
stats = dev_get_stats(dev);
|
||||
copy_rtnl_link_stats(nla_data(attr), stats);
|
||||
|
||||
if (dev->rtnl_link_ops) {
|
||||
@@ -762,6 +762,7 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
|
||||
static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
|
||||
struct nlattr **tb, char *ifname, int modified)
|
||||
{
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
int send_addr_notify = 0;
|
||||
int err;
|
||||
|
||||
@@ -783,7 +784,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
|
||||
struct rtnl_link_ifmap *u_map;
|
||||
struct ifmap k_map;
|
||||
|
||||
if (!dev->set_config) {
|
||||
if (!ops->ndo_set_config) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto errout;
|
||||
}
|
||||
@@ -801,7 +802,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
|
||||
k_map.dma = (unsigned char) u_map->dma;
|
||||
k_map.port = (unsigned char) u_map->port;
|
||||
|
||||
err = dev->set_config(dev, &k_map);
|
||||
err = ops->ndo_set_config(dev, &k_map);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
@@ -812,7 +813,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
|
||||
struct sockaddr *sa;
|
||||
int len;
|
||||
|
||||
if (!dev->set_mac_address) {
|
||||
if (!ops->ndo_set_mac_address) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto errout;
|
||||
}
|
||||
@@ -831,7 +832,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
|
||||
sa->sa_family = dev->type;
|
||||
memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
|
||||
dev->addr_len);
|
||||
err = dev->set_mac_address(dev, sa);
|
||||
err = ops->ndo_set_mac_address(dev, sa);
|
||||
kfree(sa);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
@@ -501,7 +501,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
|
||||
new->network_header = old->network_header;
|
||||
new->mac_header = old->mac_header;
|
||||
new->dst = dst_clone(old->dst);
|
||||
#ifdef CONFIG_INET
|
||||
#ifdef CONFIG_XFRM
|
||||
new->sp = secpath_get(old->sp);
|
||||
#endif
|
||||
memcpy(new->cb, old->cb, sizeof(old->cb));
|
||||
@@ -556,6 +556,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
|
||||
C(truesize);
|
||||
#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
|
||||
C(do_not_encrypt);
|
||||
C(requeue);
|
||||
#endif
|
||||
atomic_set(&n->users, 1);
|
||||
|
||||
@@ -2017,6 +2018,148 @@ void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len)
|
||||
skb_split_no_header(skb, skb1, len, pos);
|
||||
}
|
||||
|
||||
/* Shifting from/to a cloned skb is a no-go.
|
||||
*
|
||||
* Caller cannot keep skb_shinfo related pointers past calling here!
|
||||
*/
|
||||
static int skb_prepare_for_shift(struct sk_buff *skb)
|
||||
{
|
||||
return skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* skb_shift - Shifts paged data partially from skb to another
|
||||
* @tgt: buffer into which tail data gets added
|
||||
* @skb: buffer from which the paged data comes from
|
||||
* @shiftlen: shift up to this many bytes
|
||||
*
|
||||
* Attempts to shift up to shiftlen worth of bytes, which may be less than
|
||||
* the length of the skb, from tgt to skb. Returns number bytes shifted.
|
||||
* It's up to caller to free skb if everything was shifted.
|
||||
*
|
||||
* If @tgt runs out of frags, the whole operation is aborted.
|
||||
*
|
||||
* Skb cannot include anything else but paged data while tgt is allowed
|
||||
* to have non-paged data as well.
|
||||
*
|
||||
* TODO: full sized shift could be optimized but that would need
|
||||
* specialized skb free'er to handle frags without up-to-date nr_frags.
|
||||
*/
|
||||
int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
|
||||
{
|
||||
int from, to, merge, todo;
|
||||
struct skb_frag_struct *fragfrom, *fragto;
|
||||
|
||||
BUG_ON(shiftlen > skb->len);
|
||||
BUG_ON(skb_headlen(skb)); /* Would corrupt stream */
|
||||
|
||||
todo = shiftlen;
|
||||
from = 0;
|
||||
to = skb_shinfo(tgt)->nr_frags;
|
||||
fragfrom = &skb_shinfo(skb)->frags[from];
|
||||
|
||||
/* Actual merge is delayed until the point when we know we can
|
||||
* commit all, so that we don't have to undo partial changes
|
||||
*/
|
||||
if (!to ||
|
||||
!skb_can_coalesce(tgt, to, fragfrom->page, fragfrom->page_offset)) {
|
||||
merge = -1;
|
||||
} else {
|
||||
merge = to - 1;
|
||||
|
||||
todo -= fragfrom->size;
|
||||
if (todo < 0) {
|
||||
if (skb_prepare_for_shift(skb) ||
|
||||
skb_prepare_for_shift(tgt))
|
||||
return 0;
|
||||
|
||||
/* All previous frag pointers might be stale! */
|
||||
fragfrom = &skb_shinfo(skb)->frags[from];
|
||||
fragto = &skb_shinfo(tgt)->frags[merge];
|
||||
|
||||
fragto->size += shiftlen;
|
||||
fragfrom->size -= shiftlen;
|
||||
fragfrom->page_offset += shiftlen;
|
||||
|
||||
goto onlymerged;
|
||||
}
|
||||
|
||||
from++;
|
||||
}
|
||||
|
||||
/* Skip full, not-fitting skb to avoid expensive operations */
|
||||
if ((shiftlen == skb->len) &&
|
||||
(skb_shinfo(skb)->nr_frags - from) > (MAX_SKB_FRAGS - to))
|
||||
return 0;
|
||||
|
||||
if (skb_prepare_for_shift(skb) || skb_prepare_for_shift(tgt))
|
||||
return 0;
|
||||
|
||||
while ((todo > 0) && (from < skb_shinfo(skb)->nr_frags)) {
|
||||
if (to == MAX_SKB_FRAGS)
|
||||
return 0;
|
||||
|
||||
fragfrom = &skb_shinfo(skb)->frags[from];
|
||||
fragto = &skb_shinfo(tgt)->frags[to];
|
||||
|
||||
if (todo >= fragfrom->size) {
|
||||
*fragto = *fragfrom;
|
||||
todo -= fragfrom->size;
|
||||
from++;
|
||||
to++;
|
||||
|
||||
} else {
|
||||
get_page(fragfrom->page);
|
||||
fragto->page = fragfrom->page;
|
||||
fragto->page_offset = fragfrom->page_offset;
|
||||
fragto->size = todo;
|
||||
|
||||
fragfrom->page_offset += todo;
|
||||
fragfrom->size -= todo;
|
||||
todo = 0;
|
||||
|
||||
to++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ready to "commit" this state change to tgt */
|
||||
skb_shinfo(tgt)->nr_frags = to;
|
||||
|
||||
if (merge >= 0) {
|
||||
fragfrom = &skb_shinfo(skb)->frags[0];
|
||||
fragto = &skb_shinfo(tgt)->frags[merge];
|
||||
|
||||
fragto->size += fragfrom->size;
|
||||
put_page(fragfrom->page);
|
||||
}
|
||||
|
||||
/* Reposition in the original skb */
|
||||
to = 0;
|
||||
while (from < skb_shinfo(skb)->nr_frags)
|
||||
skb_shinfo(skb)->frags[to++] = skb_shinfo(skb)->frags[from++];
|
||||
skb_shinfo(skb)->nr_frags = to;
|
||||
|
||||
BUG_ON(todo > 0 && !skb_shinfo(skb)->nr_frags);
|
||||
|
||||
onlymerged:
|
||||
/* Most likely the tgt won't ever need its checksum anymore, skb on
|
||||
* the other hand might need it if it needs to be resent
|
||||
*/
|
||||
tgt->ip_summed = CHECKSUM_PARTIAL;
|
||||
skb->ip_summed = CHECKSUM_PARTIAL;
|
||||
|
||||
/* Yak, is it really working this way? Some helper please? */
|
||||
skb->len -= shiftlen;
|
||||
skb->data_len -= shiftlen;
|
||||
skb->truesize -= shiftlen;
|
||||
tgt->len += shiftlen;
|
||||
tgt->data_len += shiftlen;
|
||||
tgt->truesize += shiftlen;
|
||||
|
||||
return shiftlen;
|
||||
}
|
||||
|
||||
/**
|
||||
* skb_prepare_seq_read - Prepare a sequential read of skb data
|
||||
* @skb: the buffer to read
|
||||
@@ -2285,6 +2428,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
|
||||
{
|
||||
struct sk_buff *segs = NULL;
|
||||
struct sk_buff *tail = NULL;
|
||||
struct sk_buff *fskb = skb_shinfo(skb)->frag_list;
|
||||
unsigned int mss = skb_shinfo(skb)->gso_size;
|
||||
unsigned int doffset = skb->data - skb_mac_header(skb);
|
||||
unsigned int offset = doffset;
|
||||
@@ -2304,7 +2448,6 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
|
||||
struct sk_buff *nskb;
|
||||
skb_frag_t *frag;
|
||||
int hsize;
|
||||
int k;
|
||||
int size;
|
||||
|
||||
len = skb->len - offset;
|
||||
@@ -2317,9 +2460,36 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
|
||||
if (hsize > len || !sg)
|
||||
hsize = len;
|
||||
|
||||
nskb = alloc_skb(hsize + doffset + headroom, GFP_ATOMIC);
|
||||
if (unlikely(!nskb))
|
||||
goto err;
|
||||
if (!hsize && i >= nfrags) {
|
||||
BUG_ON(fskb->len != len);
|
||||
|
||||
pos += len;
|
||||
nskb = skb_clone(fskb, GFP_ATOMIC);
|
||||
fskb = fskb->next;
|
||||
|
||||
if (unlikely(!nskb))
|
||||
goto err;
|
||||
|
||||
hsize = skb_end_pointer(nskb) - nskb->head;
|
||||
if (skb_cow_head(nskb, doffset + headroom)) {
|
||||
kfree_skb(nskb);
|
||||
goto err;
|
||||
}
|
||||
|
||||
nskb->truesize += skb_end_pointer(nskb) - nskb->head -
|
||||
hsize;
|
||||
skb_release_head_state(nskb);
|
||||
__skb_push(nskb, doffset);
|
||||
} else {
|
||||
nskb = alloc_skb(hsize + doffset + headroom,
|
||||
GFP_ATOMIC);
|
||||
|
||||
if (unlikely(!nskb))
|
||||
goto err;
|
||||
|
||||
skb_reserve(nskb, headroom);
|
||||
__skb_put(nskb, doffset);
|
||||
}
|
||||
|
||||
if (segs)
|
||||
tail->next = nskb;
|
||||
@@ -2330,13 +2500,15 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
|
||||
__copy_skb_header(nskb, skb);
|
||||
nskb->mac_len = skb->mac_len;
|
||||
|
||||
skb_reserve(nskb, headroom);
|
||||
skb_reset_mac_header(nskb);
|
||||
skb_set_network_header(nskb, skb->mac_len);
|
||||
nskb->transport_header = (nskb->network_header +
|
||||
skb_network_header_len(skb));
|
||||
skb_copy_from_linear_data(skb, skb_put(nskb, doffset),
|
||||
doffset);
|
||||
skb_copy_from_linear_data(skb, nskb->data, doffset);
|
||||
|
||||
if (pos >= offset + len)
|
||||
continue;
|
||||
|
||||
if (!sg) {
|
||||
nskb->ip_summed = CHECKSUM_NONE;
|
||||
nskb->csum = skb_copy_and_csum_bits(skb, offset,
|
||||
@@ -2346,14 +2518,11 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
|
||||
}
|
||||
|
||||
frag = skb_shinfo(nskb)->frags;
|
||||
k = 0;
|
||||
|
||||
skb_copy_from_linear_data_offset(skb, offset,
|
||||
skb_put(nskb, hsize), hsize);
|
||||
|
||||
while (pos < offset + len) {
|
||||
BUG_ON(i >= nfrags);
|
||||
|
||||
while (pos < offset + len && i < nfrags) {
|
||||
*frag = skb_shinfo(skb)->frags[i];
|
||||
get_page(frag->page);
|
||||
size = frag->size;
|
||||
@@ -2363,20 +2532,39 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
|
||||
frag->size -= offset - pos;
|
||||
}
|
||||
|
||||
k++;
|
||||
skb_shinfo(nskb)->nr_frags++;
|
||||
|
||||
if (pos + size <= offset + len) {
|
||||
i++;
|
||||
pos += size;
|
||||
} else {
|
||||
frag->size -= pos + size - (offset + len);
|
||||
break;
|
||||
goto skip_fraglist;
|
||||
}
|
||||
|
||||
frag++;
|
||||
}
|
||||
|
||||
skb_shinfo(nskb)->nr_frags = k;
|
||||
if (pos < offset + len) {
|
||||
struct sk_buff *fskb2 = fskb;
|
||||
|
||||
BUG_ON(pos + fskb->len != offset + len);
|
||||
|
||||
pos += fskb->len;
|
||||
fskb = fskb->next;
|
||||
|
||||
if (fskb2->next) {
|
||||
fskb2 = skb_clone(fskb2, GFP_ATOMIC);
|
||||
if (!fskb2)
|
||||
goto err;
|
||||
} else
|
||||
skb_get(fskb2);
|
||||
|
||||
BUG_ON(skb_shinfo(nskb)->frag_list);
|
||||
skb_shinfo(nskb)->frag_list = fskb2;
|
||||
}
|
||||
|
||||
skip_fraglist:
|
||||
nskb->data_len = len - hsize;
|
||||
nskb->len += nskb->data_len;
|
||||
nskb->truesize += nskb->data_len;
|
||||
@@ -2394,6 +2582,65 @@ err:
|
||||
|
||||
EXPORT_SYMBOL_GPL(skb_segment);
|
||||
|
||||
int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *p = *head;
|
||||
struct sk_buff *nskb;
|
||||
unsigned int headroom;
|
||||
unsigned int hlen = p->data - skb_mac_header(p);
|
||||
|
||||
if (hlen + p->len + skb->len >= 65536)
|
||||
return -E2BIG;
|
||||
|
||||
if (skb_shinfo(p)->frag_list)
|
||||
goto merge;
|
||||
|
||||
headroom = skb_headroom(p);
|
||||
nskb = netdev_alloc_skb(p->dev, headroom);
|
||||
if (unlikely(!nskb))
|
||||
return -ENOMEM;
|
||||
|
||||
__copy_skb_header(nskb, p);
|
||||
nskb->mac_len = p->mac_len;
|
||||
|
||||
skb_reserve(nskb, headroom);
|
||||
|
||||
skb_set_mac_header(nskb, -hlen);
|
||||
skb_set_network_header(nskb, skb_network_offset(p));
|
||||
skb_set_transport_header(nskb, skb_transport_offset(p));
|
||||
|
||||
memcpy(skb_mac_header(nskb), skb_mac_header(p), hlen);
|
||||
|
||||
*NAPI_GRO_CB(nskb) = *NAPI_GRO_CB(p);
|
||||
skb_shinfo(nskb)->frag_list = p;
|
||||
skb_header_release(p);
|
||||
nskb->prev = p;
|
||||
|
||||
nskb->data_len += p->len;
|
||||
nskb->truesize += p->len;
|
||||
nskb->len += p->len;
|
||||
|
||||
*head = nskb;
|
||||
nskb->next = p->next;
|
||||
p->next = NULL;
|
||||
|
||||
p = nskb;
|
||||
|
||||
merge:
|
||||
NAPI_GRO_CB(p)->count++;
|
||||
p->prev->next = skb;
|
||||
p->prev = skb;
|
||||
skb_header_release(skb);
|
||||
|
||||
p->data_len += skb->len;
|
||||
p->truesize += skb->len;
|
||||
p->len += skb->len;
|
||||
|
||||
NAPI_GRO_CB(skb)->same_flow = 1;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(skb_gro_receive);
|
||||
|
||||
void __init skb_init(void)
|
||||
{
|
||||
skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
|
||||
|
@@ -1071,7 +1071,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
|
||||
newsk->sk_sleep = NULL;
|
||||
|
||||
if (newsk->sk_prot->sockets_allocated)
|
||||
atomic_inc(newsk->sk_prot->sockets_allocated);
|
||||
percpu_counter_inc(newsk->sk_prot->sockets_allocated);
|
||||
}
|
||||
out:
|
||||
return newsk;
|
||||
@@ -1463,8 +1463,12 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind)
|
||||
}
|
||||
|
||||
if (prot->memory_pressure) {
|
||||
if (!*prot->memory_pressure ||
|
||||
prot->sysctl_mem[2] > atomic_read(prot->sockets_allocated) *
|
||||
int alloc;
|
||||
|
||||
if (!*prot->memory_pressure)
|
||||
return 1;
|
||||
alloc = percpu_counter_read_positive(prot->sockets_allocated);
|
||||
if (prot->sysctl_mem[2] > alloc *
|
||||
sk_mem_pages(sk->sk_wmem_queued +
|
||||
atomic_read(&sk->sk_rmem_alloc) +
|
||||
sk->sk_forward_alloc))
|
||||
@@ -2037,7 +2041,8 @@ int proto_register(struct proto *prot, int alloc_slab)
|
||||
{
|
||||
if (alloc_slab) {
|
||||
prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
SLAB_HWCACHE_ALIGN | prot->slab_flags,
|
||||
NULL);
|
||||
|
||||
if (prot->slab == NULL) {
|
||||
printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n",
|
||||
@@ -2076,7 +2081,9 @@ int proto_register(struct proto *prot, int alloc_slab)
|
||||
prot->twsk_prot->twsk_slab =
|
||||
kmem_cache_create(prot->twsk_prot->twsk_slab_name,
|
||||
prot->twsk_prot->twsk_obj_size,
|
||||
0, SLAB_HWCACHE_ALIGN,
|
||||
0,
|
||||
SLAB_HWCACHE_ALIGN |
|
||||
prot->slab_flags,
|
||||
NULL);
|
||||
if (prot->twsk_prot->twsk_slab == NULL)
|
||||
goto out_free_timewait_sock_slab_name;
|
||||
@@ -2164,7 +2171,7 @@ static void proto_seq_printf(struct seq_file *seq, struct proto *proto)
|
||||
"%2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c\n",
|
||||
proto->name,
|
||||
proto->obj_size,
|
||||
proto->sockets_allocated != NULL ? atomic_read(proto->sockets_allocated) : -1,
|
||||
sock_prot_inuse_get(seq_file_net(seq), proto),
|
||||
proto->memory_allocated != NULL ? atomic_read(proto->memory_allocated) : -1,
|
||||
proto->memory_pressure != NULL ? *proto->memory_pressure ? "yes" : "no" : "NI",
|
||||
proto->max_header,
|
||||
@@ -2218,7 +2225,8 @@ static const struct seq_operations proto_seq_ops = {
|
||||
|
||||
static int proto_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &proto_seq_ops);
|
||||
return seq_open_net(inode, file, &proto_seq_ops,
|
||||
sizeof(struct seq_net_private));
|
||||
}
|
||||
|
||||
static const struct file_operations proto_seq_fops = {
|
||||
@@ -2226,13 +2234,31 @@ static const struct file_operations proto_seq_fops = {
|
||||
.open = proto_seq_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
.release = seq_release_net,
|
||||
};
|
||||
|
||||
static __net_init int proto_init_net(struct net *net)
|
||||
{
|
||||
if (!proc_net_fops_create(net, "protocols", S_IRUGO, &proto_seq_fops))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __net_exit void proto_exit_net(struct net *net)
|
||||
{
|
||||
proc_net_remove(net, "protocols");
|
||||
}
|
||||
|
||||
|
||||
static __net_initdata struct pernet_operations proto_net_ops = {
|
||||
.init = proto_init_net,
|
||||
.exit = proto_exit_net,
|
||||
};
|
||||
|
||||
static int __init proto_init(void)
|
||||
{
|
||||
/* register /proc/net/protocols */
|
||||
return proc_net_fops_create(&init_net, "protocols", S_IRUGO, &proto_seq_fops) == NULL ? -ENOBUFS : 0;
|
||||
return register_pernet_subsys(&proto_net_ops);
|
||||
}
|
||||
|
||||
subsys_initcall(proto_init);
|
||||
|
@@ -12,7 +12,6 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/init.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/xfrm.h>
|
||||
|
||||
static struct ctl_table net_core_table[] = {
|
||||
#ifdef CONFIG_NET
|
||||
@@ -22,7 +21,7 @@ static struct ctl_table net_core_table[] = {
|
||||
.data = &sysctl_wmem_max,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
.proc_handler = proc_dointvec
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_CORE_RMEM_MAX,
|
||||
@@ -30,7 +29,7 @@ static struct ctl_table net_core_table[] = {
|
||||
.data = &sysctl_rmem_max,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
.proc_handler = proc_dointvec
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_CORE_WMEM_DEFAULT,
|
||||
@@ -38,7 +37,7 @@ static struct ctl_table net_core_table[] = {
|
||||
.data = &sysctl_wmem_default,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
.proc_handler = proc_dointvec
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_CORE_RMEM_DEFAULT,
|
||||
@@ -46,7 +45,7 @@ static struct ctl_table net_core_table[] = {
|
||||
.data = &sysctl_rmem_default,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
.proc_handler = proc_dointvec
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_CORE_DEV_WEIGHT,
|
||||
@@ -54,7 +53,7 @@ static struct ctl_table net_core_table[] = {
|
||||
.data = &weight_p,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
.proc_handler = proc_dointvec
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_CORE_MAX_BACKLOG,
|
||||
@@ -62,7 +61,7 @@ static struct ctl_table net_core_table[] = {
|
||||
.data = &netdev_max_backlog,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
.proc_handler = proc_dointvec
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_CORE_MSG_COST,
|
||||
@@ -70,8 +69,8 @@ static struct ctl_table net_core_table[] = {
|
||||
.data = &net_ratelimit_state.interval,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_jiffies,
|
||||
.strategy = &sysctl_jiffies,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
.strategy = sysctl_jiffies,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_CORE_MSG_BURST,
|
||||
@@ -79,7 +78,7 @@ static struct ctl_table net_core_table[] = {
|
||||
.data = &net_ratelimit_state.burst,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_CORE_OPTMEM_MAX,
|
||||
@@ -87,42 +86,8 @@ static struct ctl_table net_core_table[] = {
|
||||
.data = &sysctl_optmem_max,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
.proc_handler = proc_dointvec
|
||||
},
|
||||
#ifdef CONFIG_XFRM
|
||||
{
|
||||
.ctl_name = NET_CORE_AEVENT_ETIME,
|
||||
.procname = "xfrm_aevent_etime",
|
||||
.data = &sysctl_xfrm_aevent_etime,
|
||||
.maxlen = sizeof(u32),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_CORE_AEVENT_RSEQTH,
|
||||
.procname = "xfrm_aevent_rseqth",
|
||||
.data = &sysctl_xfrm_aevent_rseqth,
|
||||
.maxlen = sizeof(u32),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
},
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
.procname = "xfrm_larval_drop",
|
||||
.data = &sysctl_xfrm_larval_drop,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
},
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
.procname = "xfrm_acq_expires",
|
||||
.data = &sysctl_xfrm_acq_expires,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
},
|
||||
#endif /* CONFIG_XFRM */
|
||||
#endif /* CONFIG_NET */
|
||||
{
|
||||
.ctl_name = NET_CORE_BUDGET,
|
||||
@@ -130,7 +95,7 @@ static struct ctl_table net_core_table[] = {
|
||||
.data = &netdev_budget,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
.proc_handler = proc_dointvec
|
||||
},
|
||||
{
|
||||
.ctl_name = NET_CORE_WARNINGS,
|
||||
@@ -138,7 +103,7 @@ static struct ctl_table net_core_table[] = {
|
||||
.data = &net_msg_warn,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
.proc_handler = proc_dointvec
|
||||
},
|
||||
{ .ctl_name = 0 }
|
||||
};
|
||||
@@ -150,12 +115,12 @@ static struct ctl_table netns_core_table[] = {
|
||||
.data = &init_net.core.sysctl_somaxconn,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec
|
||||
.proc_handler = proc_dointvec
|
||||
},
|
||||
{ .ctl_name = 0 }
|
||||
};
|
||||
|
||||
static __net_initdata struct ctl_path net_core_path[] = {
|
||||
__net_initdata struct ctl_path net_core_path[] = {
|
||||
{ .procname = "net", .ctl_name = CTL_NET, },
|
||||
{ .procname = "core", .ctl_name = NET_CORE, },
|
||||
{ },
|
||||
@@ -207,8 +172,11 @@ static __net_initdata struct pernet_operations sysctl_core_ops = {
|
||||
|
||||
static __init int sysctl_core_init(void)
|
||||
{
|
||||
static struct ctl_table empty[1];
|
||||
|
||||
register_sysctl_paths(net_core_path, empty);
|
||||
register_net_sysctl_rotable(net_core_path, net_core_table);
|
||||
return register_pernet_subsys(&sysctl_core_ops);
|
||||
}
|
||||
|
||||
__initcall(sysctl_core_init);
|
||||
fs_initcall(sysctl_core_init);
|
||||
|
22
net/dcb/Kconfig
Normal file
22
net/dcb/Kconfig
Normal file
@@ -0,0 +1,22 @@
|
||||
config DCB
|
||||
bool "Data Center Bridging support"
|
||||
default n
|
||||
---help---
|
||||
This enables support for configuring Data Center Bridging (DCB)
|
||||
features on DCB capable Ethernet adapters via rtnetlink. Say 'Y'
|
||||
if you have a DCB capable Ethernet adapter which supports this
|
||||
interface and you are connected to a DCB capable switch.
|
||||
|
||||
DCB is a collection of Ethernet enhancements which allow DCB capable
|
||||
NICs and switches to support network traffic with differing
|
||||
requirements (highly reliable, no drops vs. best effort vs. low
|
||||
latency) to co-exist on Ethernet.
|
||||
|
||||
DCB features include:
|
||||
Enhanced Transmission Selection (aka Priority Grouping) - provides a
|
||||
framework for assigning bandwidth guarantees to traffic classes.
|
||||
Priority-based Flow Control (PFC) - a MAC control pause frame which
|
||||
works at the granularity of the 802.1p priority instead of the
|
||||
link (802.3x).
|
||||
|
||||
If unsure, say N.
|
1
net/dcb/Makefile
Normal file
1
net/dcb/Makefile
Normal file
@@ -0,0 +1 @@
|
||||
obj-$(CONFIG_DCB) += dcbnl.o
|
1122
net/dcb/dcbnl.c
Normal file
1122
net/dcb/dcbnl.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,6 @@
|
||||
#include "ackvec.h"
|
||||
#include "dccp.h"
|
||||
|
||||
#include <linux/dccp.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
@@ -68,7 +67,7 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
|
||||
/* Figure out how many options do we need to represent the ackvec */
|
||||
const u16 nr_opts = DIV_ROUND_UP(av->av_vec_len, DCCP_MAX_ACKVEC_OPT_LEN);
|
||||
const u8 nr_opts = DIV_ROUND_UP(av->av_vec_len, DCCP_SINGLE_OPT_MAXLEN);
|
||||
u16 len = av->av_vec_len + 2 * nr_opts, i;
|
||||
u32 elapsed_time;
|
||||
const unsigned char *tail, *from;
|
||||
@@ -100,8 +99,8 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
|
||||
for (i = 0; i < nr_opts; ++i) {
|
||||
int copylen = len;
|
||||
|
||||
if (len > DCCP_MAX_ACKVEC_OPT_LEN)
|
||||
copylen = DCCP_MAX_ACKVEC_OPT_LEN;
|
||||
if (len > DCCP_SINGLE_OPT_MAXLEN)
|
||||
copylen = DCCP_SINGLE_OPT_MAXLEN;
|
||||
|
||||
*to++ = DCCPO_ACK_VECTOR_0;
|
||||
*to++ = copylen + 2;
|
||||
@@ -432,7 +431,7 @@ found:
|
||||
int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
|
||||
u64 *ackno, const u8 opt, const u8 *value, const u8 len)
|
||||
{
|
||||
if (len > DCCP_MAX_ACKVEC_OPT_LEN)
|
||||
if (len > DCCP_SINGLE_OPT_MAXLEN)
|
||||
return -1;
|
||||
|
||||
/* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */
|
||||
|
@@ -11,15 +11,14 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/dccp.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Read about the ECN nonce to see why it is 253 */
|
||||
#define DCCP_MAX_ACKVEC_OPT_LEN 253
|
||||
/* We can spread an ack vector across multiple options */
|
||||
#define DCCP_MAX_ACKVEC_LEN (DCCP_MAX_ACKVEC_OPT_LEN * 2)
|
||||
#define DCCP_MAX_ACKVEC_LEN (DCCP_SINGLE_OPT_MAXLEN * 2)
|
||||
|
||||
#define DCCP_ACKVEC_STATE_RECEIVED 0
|
||||
#define DCCP_ACKVEC_STATE_ECN_MARKED (1 << 6)
|
||||
|
@@ -13,6 +13,13 @@
|
||||
|
||||
#include "ccid.h"
|
||||
|
||||
static u8 builtin_ccids[] = {
|
||||
DCCPC_CCID2, /* CCID2 is supported by default */
|
||||
#if defined(CONFIG_IP_DCCP_CCID3) || defined(CONFIG_IP_DCCP_CCID3_MODULE)
|
||||
DCCPC_CCID3,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct ccid_operations *ccids[CCID_MAX];
|
||||
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
|
||||
static atomic_t ccids_lockct = ATOMIC_INIT(0);
|
||||
@@ -86,6 +93,47 @@ static void ccid_kmem_cache_destroy(struct kmem_cache *slab)
|
||||
}
|
||||
}
|
||||
|
||||
/* check that up to @array_len members in @ccid_array are supported */
|
||||
bool ccid_support_check(u8 const *ccid_array, u8 array_len)
|
||||
{
|
||||
u8 i, j, found;
|
||||
|
||||
for (i = 0, found = 0; i < array_len; i++, found = 0) {
|
||||
for (j = 0; !found && j < ARRAY_SIZE(builtin_ccids); j++)
|
||||
found = (ccid_array[i] == builtin_ccids[j]);
|
||||
if (!found)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ccid_get_builtin_ccids - Provide copy of `builtin' CCID array
|
||||
* @ccid_array: pointer to copy into
|
||||
* @array_len: value to return length into
|
||||
* This function allocates memory - caller must see that it is freed after use.
|
||||
*/
|
||||
int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len)
|
||||
{
|
||||
*ccid_array = kmemdup(builtin_ccids, sizeof(builtin_ccids), gfp_any());
|
||||
if (*ccid_array == NULL)
|
||||
return -ENOBUFS;
|
||||
*array_len = ARRAY_SIZE(builtin_ccids);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
|
||||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
if (len < sizeof(builtin_ccids))
|
||||
return -EINVAL;
|
||||
|
||||
if (put_user(sizeof(builtin_ccids), optlen) ||
|
||||
copy_to_user(optval, builtin_ccids, sizeof(builtin_ccids)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ccid_register(struct ccid_operations *ccid_ops)
|
||||
{
|
||||
int err = -ENOBUFS;
|
||||
@@ -205,20 +253,6 @@ out_module_put:
|
||||
|
||||
EXPORT_SYMBOL_GPL(ccid_new);
|
||||
|
||||
struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk, gfp_t gfp)
|
||||
{
|
||||
return ccid_new(id, sk, 1, gfp);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ccid_hc_rx_new);
|
||||
|
||||
struct ccid *ccid_hc_tx_new(unsigned char id,struct sock *sk, gfp_t gfp)
|
||||
{
|
||||
return ccid_new(id, sk, 0, gfp);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ccid_hc_tx_new);
|
||||
|
||||
static void ccid_delete(struct ccid *ccid, struct sock *sk, int rx)
|
||||
{
|
||||
struct ccid_operations *ccid_ops;
|
||||
|
@@ -103,13 +103,31 @@ static inline void *ccid_priv(const struct ccid *ccid)
|
||||
return (void *)ccid->ccid_priv;
|
||||
}
|
||||
|
||||
extern bool ccid_support_check(u8 const *ccid_array, u8 array_len);
|
||||
extern int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len);
|
||||
extern int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
|
||||
char __user *, int __user *);
|
||||
|
||||
extern struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx,
|
||||
gfp_t gfp);
|
||||
|
||||
extern struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk,
|
||||
gfp_t gfp);
|
||||
extern struct ccid *ccid_hc_tx_new(unsigned char id, struct sock *sk,
|
||||
gfp_t gfp);
|
||||
static inline int ccid_get_current_rx_ccid(struct dccp_sock *dp)
|
||||
{
|
||||
struct ccid *ccid = dp->dccps_hc_rx_ccid;
|
||||
|
||||
if (ccid == NULL || ccid->ccid_ops == NULL)
|
||||
return -1;
|
||||
return ccid->ccid_ops->ccid_id;
|
||||
}
|
||||
|
||||
static inline int ccid_get_current_tx_ccid(struct dccp_sock *dp)
|
||||
{
|
||||
struct ccid *ccid = dp->dccps_hc_tx_ccid;
|
||||
|
||||
if (ccid == NULL || ccid->ccid_ops == NULL)
|
||||
return -1;
|
||||
return ccid->ccid_ops->ccid_id;
|
||||
}
|
||||
|
||||
extern void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk);
|
||||
extern void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk);
|
||||
|
@@ -25,7 +25,7 @@
|
||||
/*
|
||||
* This implementation should follow RFC 4341
|
||||
*/
|
||||
|
||||
#include "../feat.h"
|
||||
#include "../ccid.h"
|
||||
#include "../dccp.h"
|
||||
#include "ccid2.h"
|
||||
@@ -147,8 +147,8 @@ static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val)
|
||||
DCCP_WARN("Limiting Ack Ratio (%u) to %u\n", val, max_ratio);
|
||||
val = max_ratio;
|
||||
}
|
||||
if (val > 0xFFFF) /* RFC 4340, 11.3 */
|
||||
val = 0xFFFF;
|
||||
if (val > DCCPF_ACK_RATIO_MAX)
|
||||
val = DCCPF_ACK_RATIO_MAX;
|
||||
|
||||
if (val == dp->dccps_l_ack_ratio)
|
||||
return;
|
||||
|
@@ -49,7 +49,7 @@ extern int dccp_debug;
|
||||
|
||||
extern struct inet_hashinfo dccp_hashinfo;
|
||||
|
||||
extern atomic_t dccp_orphan_count;
|
||||
extern struct percpu_counter dccp_orphan_count;
|
||||
|
||||
extern void dccp_time_wait(struct sock *sk, int state, int timeo);
|
||||
|
||||
@@ -98,9 +98,6 @@ extern int sysctl_dccp_retries2;
|
||||
extern int sysctl_dccp_feat_sequence_window;
|
||||
extern int sysctl_dccp_feat_rx_ccid;
|
||||
extern int sysctl_dccp_feat_tx_ccid;
|
||||
extern int sysctl_dccp_feat_ack_ratio;
|
||||
extern int sysctl_dccp_feat_send_ack_vector;
|
||||
extern int sysctl_dccp_feat_send_ndp_count;
|
||||
extern int sysctl_dccp_tx_qlen;
|
||||
extern int sysctl_dccp_sync_ratelimit;
|
||||
|
||||
@@ -252,7 +249,8 @@ extern const char *dccp_state_name(const int state);
|
||||
extern void dccp_set_state(struct sock *sk, const int state);
|
||||
extern void dccp_done(struct sock *sk);
|
||||
|
||||
extern void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb);
|
||||
extern int dccp_reqsk_init(struct request_sock *rq, struct dccp_sock const *dp,
|
||||
struct sk_buff const *skb);
|
||||
|
||||
extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
|
||||
|
||||
@@ -435,12 +433,19 @@ static inline int dccp_ack_pending(const struct sock *sk)
|
||||
const struct dccp_sock *dp = dccp_sk(sk);
|
||||
return dp->dccps_timestamp_echo != 0 ||
|
||||
#ifdef CONFIG_IP_DCCP_ACKVEC
|
||||
(dccp_msk(sk)->dccpms_send_ack_vector &&
|
||||
(dp->dccps_hc_rx_ackvec != NULL &&
|
||||
dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) ||
|
||||
#endif
|
||||
inet_csk_ack_scheduled(sk);
|
||||
}
|
||||
|
||||
extern int dccp_feat_finalise_settings(struct dccp_sock *dp);
|
||||
extern int dccp_feat_server_ccid_dependencies(struct dccp_request_sock *dreq);
|
||||
extern int dccp_feat_insert_opts(struct dccp_sock*, struct dccp_request_sock*,
|
||||
struct sk_buff *skb);
|
||||
extern int dccp_feat_activate_values(struct sock *sk, struct list_head *fn);
|
||||
extern void dccp_feat_list_purge(struct list_head *fn_list);
|
||||
|
||||
extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb);
|
||||
extern int dccp_insert_options_rsk(struct dccp_request_sock*, struct sk_buff*);
|
||||
extern int dccp_insert_option_elapsed_time(struct sock *sk,
|
||||
|
@@ -29,11 +29,14 @@ static void dccp_get_info(struct sock *sk, struct tcp_info *info)
|
||||
info->tcpi_backoff = icsk->icsk_backoff;
|
||||
info->tcpi_pmtu = icsk->icsk_pmtu_cookie;
|
||||
|
||||
if (dccp_msk(sk)->dccpms_send_ack_vector)
|
||||
if (dp->dccps_hc_rx_ackvec != NULL)
|
||||
info->tcpi_options |= TCPI_OPT_SACK;
|
||||
|
||||
ccid_hc_rx_get_info(dp->dccps_hc_rx_ccid, sk, info);
|
||||
ccid_hc_tx_get_info(dp->dccps_hc_tx_ccid, sk, info);
|
||||
if (dp->dccps_hc_rx_ccid != NULL)
|
||||
ccid_hc_rx_get_info(dp->dccps_hc_rx_ccid, sk, info);
|
||||
|
||||
if (dp->dccps_hc_tx_ccid != NULL)
|
||||
ccid_hc_tx_get_info(dp->dccps_hc_tx_ccid, sk, info);
|
||||
}
|
||||
|
||||
static void dccp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
|
||||
@@ -45,7 +48,7 @@ static void dccp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
|
||||
dccp_get_info(sk, _info);
|
||||
}
|
||||
|
||||
static struct inet_diag_handler dccp_diag_handler = {
|
||||
static const struct inet_diag_handler dccp_diag_handler = {
|
||||
.idiag_hashinfo = &dccp_hashinfo,
|
||||
.idiag_get_info = dccp_diag_get_info,
|
||||
.idiag_type = DCCPDIAG_GETSOCK,
|
||||
|
1652
net/dccp/feat.c
1652
net/dccp/feat.c
File diff suppressed because it is too large
Load Diff
130
net/dccp/feat.h
130
net/dccp/feat.h
@@ -3,17 +3,103 @@
|
||||
/*
|
||||
* net/dccp/feat.h
|
||||
*
|
||||
* An implementation of the DCCP protocol
|
||||
* Feature negotiation for the DCCP protocol (RFC 4340, section 6)
|
||||
* Copyright (c) 2008 Gerrit Renker <gerrit@erg.abdn.ac.uk>
|
||||
* Copyright (c) 2005 Andrea Bittau <a.bittau@cs.ucl.ac.uk>
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include "dccp.h"
|
||||
|
||||
/*
|
||||
* Known limit values
|
||||
*/
|
||||
/* Ack Ratio takes 2-byte integer values (11.3) */
|
||||
#define DCCPF_ACK_RATIO_MAX 0xFFFF
|
||||
/* Wmin=32 and Wmax=2^46-1 from 7.5.2 */
|
||||
#define DCCPF_SEQ_WMIN 32
|
||||
#define DCCPF_SEQ_WMAX 0x3FFFFFFFFFFFull
|
||||
/* Maximum number of SP values that fit in a single (Confirm) option */
|
||||
#define DCCP_FEAT_MAX_SP_VALS (DCCP_SINGLE_OPT_MAXLEN - 2)
|
||||
|
||||
enum dccp_feat_type {
|
||||
FEAT_AT_RX = 1, /* located at RX side of half-connection */
|
||||
FEAT_AT_TX = 2, /* located at TX side of half-connection */
|
||||
FEAT_SP = 4, /* server-priority reconciliation (6.3.1) */
|
||||
FEAT_NN = 8, /* non-negotiable reconciliation (6.3.2) */
|
||||
FEAT_UNKNOWN = 0xFF /* not understood or invalid feature */
|
||||
};
|
||||
|
||||
enum dccp_feat_state {
|
||||
FEAT_DEFAULT = 0, /* using default values from 6.4 */
|
||||
FEAT_INITIALISING, /* feature is being initialised */
|
||||
FEAT_CHANGING, /* Change sent but not confirmed yet */
|
||||
FEAT_UNSTABLE, /* local modification in state CHANGING */
|
||||
FEAT_STABLE /* both ends (think they) agree */
|
||||
};
|
||||
|
||||
/**
|
||||
* dccp_feat_val - Container for SP or NN feature values
|
||||
* @nn: single NN value
|
||||
* @sp.vec: single SP value plus optional preference list
|
||||
* @sp.len: length of @sp.vec in bytes
|
||||
*/
|
||||
typedef union {
|
||||
u64 nn;
|
||||
struct {
|
||||
u8 *vec;
|
||||
u8 len;
|
||||
} sp;
|
||||
} dccp_feat_val;
|
||||
|
||||
/**
|
||||
* struct feat_entry - Data structure to perform feature negotiation
|
||||
* @val: feature's current value (SP features may have preference list)
|
||||
* @state: feature's current state
|
||||
* @feat_num: one of %dccp_feature_numbers
|
||||
* @needs_mandatory: whether Mandatory options should be sent
|
||||
* @needs_confirm: whether to send a Confirm instead of a Change
|
||||
* @empty_confirm: whether to send an empty Confirm (depends on @needs_confirm)
|
||||
* @is_local: feature location (1) or feature-remote (0)
|
||||
* @node: list pointers, entries arranged in FIFO order
|
||||
*/
|
||||
struct dccp_feat_entry {
|
||||
dccp_feat_val val;
|
||||
enum dccp_feat_state state:8;
|
||||
u8 feat_num;
|
||||
|
||||
bool needs_mandatory,
|
||||
needs_confirm,
|
||||
empty_confirm,
|
||||
is_local;
|
||||
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
static inline u8 dccp_feat_genopt(struct dccp_feat_entry *entry)
|
||||
{
|
||||
if (entry->needs_confirm)
|
||||
return entry->is_local ? DCCPO_CONFIRM_L : DCCPO_CONFIRM_R;
|
||||
return entry->is_local ? DCCPO_CHANGE_L : DCCPO_CHANGE_R;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct ccid_dependency - Track changes resulting from choosing a CCID
|
||||
* @dependent_feat: one of %dccp_feature_numbers
|
||||
* @is_local: local (1) or remote (0) @dependent_feat
|
||||
* @is_mandatory: whether presence of @dependent_feat is mission-critical or not
|
||||
* @val: corresponding default value for @dependent_feat (u8 is sufficient here)
|
||||
*/
|
||||
struct ccid_dependency {
|
||||
u8 dependent_feat;
|
||||
bool is_local:1,
|
||||
is_mandatory:1;
|
||||
u8 val;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IP_DCCP_DEBUG
|
||||
extern const char *dccp_feat_typename(const u8 type);
|
||||
extern const char *dccp_feat_name(const u8 feat);
|
||||
@@ -27,14 +113,30 @@ static inline void dccp_feat_debug(const u8 type, const u8 feat, const u8 val)
|
||||
#define dccp_feat_debug(type, feat, val)
|
||||
#endif /* CONFIG_IP_DCCP_DEBUG */
|
||||
|
||||
extern int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
|
||||
u8 *val, u8 len, gfp_t gfp);
|
||||
extern int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature,
|
||||
u8 *val, u8 len);
|
||||
extern int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature,
|
||||
u8 *val, u8 len);
|
||||
extern void dccp_feat_clean(struct dccp_minisock *dmsk);
|
||||
extern int dccp_feat_clone(struct sock *oldsk, struct sock *newsk);
|
||||
extern int dccp_feat_init(struct dccp_minisock *dmsk);
|
||||
extern int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local,
|
||||
u8 const *list, u8 len);
|
||||
extern int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val);
|
||||
extern int dccp_feat_parse_options(struct sock *, struct dccp_request_sock *,
|
||||
u8 mand, u8 opt, u8 feat, u8 *val, u8 len);
|
||||
extern int dccp_feat_clone_list(struct list_head const *, struct list_head *);
|
||||
extern int dccp_feat_init(struct sock *sk);
|
||||
|
||||
/*
|
||||
* Encoding variable-length options and their maximum length.
|
||||
*
|
||||
* This affects NN options (SP options are all u8) and other variable-length
|
||||
* options (see table 3 in RFC 4340). The limit is currently given the Sequence
|
||||
* Window NN value (sec. 7.5.2) and the NDP count (sec. 7.7) option, all other
|
||||
* options consume less than 6 bytes (timestamps are 4 bytes).
|
||||
* When updating this constant (e.g. due to new internet drafts / RFCs), make
|
||||
* sure that you also update all code which refers to it.
|
||||
*/
|
||||
#define DCCP_OPTVAL_MAXLEN 6
|
||||
|
||||
extern void dccp_encode_value_var(const u64 value, u8 *to, const u8 len);
|
||||
extern u64 dccp_decode_value_var(const u8 *bf, const u8 len);
|
||||
|
||||
extern int dccp_insert_option_mandatory(struct sk_buff *skb);
|
||||
extern int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat,
|
||||
u8 *val, u8 len, bool repeat_first);
|
||||
#endif /* _DCCP_FEAT_H */
|
||||
|
@@ -163,7 +163,7 @@ static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
|
||||
if (dccp_msk(sk)->dccpms_send_ack_vector)
|
||||
if (dp->dccps_hc_rx_ackvec != NULL)
|
||||
dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk,
|
||||
DCCP_SKB_CB(skb)->dccpd_ack_seq);
|
||||
}
|
||||
@@ -375,7 +375,7 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
|
||||
if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
|
||||
dccp_event_ack_recv(sk, skb);
|
||||
|
||||
if (dccp_msk(sk)->dccpms_send_ack_vector &&
|
||||
if (dp->dccps_hc_rx_ackvec != NULL &&
|
||||
dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
|
||||
DCCP_SKB_CB(skb)->dccpd_seq,
|
||||
DCCP_ACKVEC_STATE_RECEIVED))
|
||||
@@ -421,20 +421,19 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
|
||||
goto out_invalid_packet;
|
||||
}
|
||||
|
||||
/*
|
||||
* If option processing (Step 8) failed, return 1 here so that
|
||||
* dccp_v4_do_rcv() sends a Reset. The Reset code depends on
|
||||
* the option type and is set in dccp_parse_options().
|
||||
*/
|
||||
if (dccp_parse_options(sk, NULL, skb))
|
||||
goto out_invalid_packet;
|
||||
return 1;
|
||||
|
||||
/* Obtain usec RTT sample from SYN exchange (used by CCID 3) */
|
||||
if (likely(dp->dccps_options_received.dccpor_timestamp_echo))
|
||||
dp->dccps_syn_rtt = dccp_sample_rtt(sk, 10 * (tstamp -
|
||||
dp->dccps_options_received.dccpor_timestamp_echo));
|
||||
|
||||
if (dccp_msk(sk)->dccpms_send_ack_vector &&
|
||||
dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
|
||||
DCCP_SKB_CB(skb)->dccpd_seq,
|
||||
DCCP_ACKVEC_STATE_RECEIVED))
|
||||
goto out_invalid_packet; /* FIXME: change error code */
|
||||
|
||||
/* Stop the REQUEST timer */
|
||||
inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);
|
||||
WARN_ON(sk->sk_send_head == NULL);
|
||||
@@ -475,6 +474,15 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
|
||||
*/
|
||||
dccp_set_state(sk, DCCP_PARTOPEN);
|
||||
|
||||
/*
|
||||
* If feature negotiation was successful, activate features now;
|
||||
* an activation failure means that this host could not activate
|
||||
* one ore more features (e.g. insufficient memory), which would
|
||||
* leave at least one feature in an undefined state.
|
||||
*/
|
||||
if (dccp_feat_activate_values(sk, &dp->dccps_featneg))
|
||||
goto unable_to_proceed;
|
||||
|
||||
/* Make sure socket is routed, for correct metrics. */
|
||||
icsk->icsk_af_ops->rebuild_header(sk);
|
||||
|
||||
@@ -509,6 +517,16 @@ out_invalid_packet:
|
||||
/* dccp_v4_do_rcv will send a reset */
|
||||
DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
|
||||
return 1;
|
||||
|
||||
unable_to_proceed:
|
||||
DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_ABORTED;
|
||||
/*
|
||||
* We mark this socket as no longer usable, so that the loop in
|
||||
* dccp_sendmsg() terminates and the application gets notified.
|
||||
*/
|
||||
dccp_set_state(sk, DCCP_CLOSED);
|
||||
sk->sk_err = ECOMM;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
|
||||
@@ -590,8 +608,6 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
|
||||
if (inet_csk(sk)->icsk_af_ops->conn_request(sk,
|
||||
skb) < 0)
|
||||
return 1;
|
||||
|
||||
/* FIXME: do congestion control initialization */
|
||||
goto discard;
|
||||
}
|
||||
if (dh->dccph_type == DCCP_PKT_RESET)
|
||||
@@ -602,7 +618,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sk->sk_state != DCCP_REQUESTING) {
|
||||
if (sk->sk_state != DCCP_REQUESTING && sk->sk_state != DCCP_RESPOND) {
|
||||
if (dccp_check_seqno(sk, skb))
|
||||
goto discard;
|
||||
|
||||
@@ -615,7 +631,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
|
||||
if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
|
||||
dccp_event_ack_recv(sk, skb);
|
||||
|
||||
if (dccp_msk(sk)->dccpms_send_ack_vector &&
|
||||
if (dp->dccps_hc_rx_ackvec != NULL &&
|
||||
dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
|
||||
DCCP_SKB_CB(skb)->dccpd_seq,
|
||||
DCCP_ACKVEC_STATE_RECEIVED))
|
||||
@@ -667,8 +683,6 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
|
||||
return 1;
|
||||
|
||||
case DCCP_REQUESTING:
|
||||
/* FIXME: do congestion control initialization */
|
||||
|
||||
queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len);
|
||||
if (queued >= 0)
|
||||
return queued;
|
||||
|
@@ -545,6 +545,7 @@ out:
|
||||
|
||||
static void dccp_v4_reqsk_destructor(struct request_sock *req)
|
||||
{
|
||||
dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
|
||||
kfree(inet_rsk(req)->opt);
|
||||
}
|
||||
|
||||
@@ -595,7 +596,8 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
|
||||
if (req == NULL)
|
||||
goto drop;
|
||||
|
||||
dccp_reqsk_init(req, skb);
|
||||
if (dccp_reqsk_init(req, dccp_sk(sk), skb))
|
||||
goto drop_and_free;
|
||||
|
||||
dreq = dccp_rsk(req);
|
||||
if (dccp_parse_options(sk, dreq, skb))
|
||||
@@ -792,12 +794,10 @@ static int dccp_v4_rcv(struct sk_buff *skb)
|
||||
DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(dh);
|
||||
DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
|
||||
|
||||
dccp_pr_debug("%8.8s "
|
||||
"src=%u.%u.%u.%u@%-5d "
|
||||
"dst=%u.%u.%u.%u@%-5d seq=%llu",
|
||||
dccp_pr_debug("%8.8s src=%pI4@%-5d dst=%pI4@%-5d seq=%llu",
|
||||
dccp_packet_name(dh->dccph_type),
|
||||
NIPQUAD(iph->saddr), ntohs(dh->dccph_sport),
|
||||
NIPQUAD(iph->daddr), ntohs(dh->dccph_dport),
|
||||
&iph->saddr, ntohs(dh->dccph_sport),
|
||||
&iph->daddr, ntohs(dh->dccph_dport),
|
||||
(unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
|
||||
|
||||
if (dccp_packet_without_ack(skb)) {
|
||||
@@ -938,6 +938,7 @@ static struct proto dccp_v4_prot = {
|
||||
.orphan_count = &dccp_orphan_count,
|
||||
.max_header = MAX_DCCP_HEADER,
|
||||
.obj_size = sizeof(struct dccp_sock),
|
||||
.slab_flags = SLAB_DESTROY_BY_RCU,
|
||||
.rsk_prot = &dccp_request_sock_ops,
|
||||
.twsk_prot = &dccp_timewait_sock_ops,
|
||||
.h.hashinfo = &dccp_hashinfo,
|
||||
|
@@ -168,7 +168,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = xfrm_lookup(&dst, &fl, sk, 0);
|
||||
err = xfrm_lookup(net, &dst, &fl, sk, 0);
|
||||
if (err < 0) {
|
||||
sk->sk_err_soft = -err;
|
||||
goto out;
|
||||
@@ -279,7 +279,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req)
|
||||
if (final_p)
|
||||
ipv6_addr_copy(&fl.fl6_dst, final_p);
|
||||
|
||||
err = xfrm_lookup(&dst, &fl, sk, 0);
|
||||
err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0);
|
||||
if (err < 0)
|
||||
goto done;
|
||||
|
||||
@@ -304,6 +304,7 @@ done:
|
||||
|
||||
static void dccp_v6_reqsk_destructor(struct request_sock *req)
|
||||
{
|
||||
dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
|
||||
if (inet6_rsk(req)->pktopts != NULL)
|
||||
kfree_skb(inet6_rsk(req)->pktopts);
|
||||
}
|
||||
@@ -342,7 +343,7 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
|
||||
|
||||
/* sk = NULL, but it is safe for now. RST socket required. */
|
||||
if (!ip6_dst_lookup(ctl_sk, &skb->dst, &fl)) {
|
||||
if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
|
||||
if (xfrm_lookup(net, &skb->dst, &fl, NULL, 0) >= 0) {
|
||||
ip6_xmit(ctl_sk, skb, &fl, NULL, 0);
|
||||
DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
|
||||
DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
|
||||
@@ -426,7 +427,8 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
|
||||
if (req == NULL)
|
||||
goto drop;
|
||||
|
||||
dccp_reqsk_init(req, skb);
|
||||
if (dccp_reqsk_init(req, dccp_sk(sk), skb))
|
||||
goto drop_and_free;
|
||||
|
||||
dreq = dccp_rsk(req);
|
||||
if (dccp_parse_options(sk, dreq, skb))
|
||||
@@ -567,7 +569,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
|
||||
if (final_p)
|
||||
ipv6_addr_copy(&fl.fl6_dst, final_p);
|
||||
|
||||
if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
|
||||
if ((xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1002,7 +1004,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
|
||||
if (final_p)
|
||||
ipv6_addr_copy(&fl.fl6_dst, final_p);
|
||||
|
||||
err = __xfrm_lookup(&dst, &fl, sk, XFRM_LOOKUP_WAIT);
|
||||
err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT);
|
||||
if (err < 0) {
|
||||
if (err == -EREMOTE)
|
||||
err = ip6_dst_blackhole(sk, &dst, &fl);
|
||||
@@ -1138,6 +1140,7 @@ static struct proto dccp_v6_prot = {
|
||||
.orphan_count = &dccp_orphan_count,
|
||||
.max_header = MAX_DCCP_HEADER,
|
||||
.obj_size = sizeof(struct dccp6_sock),
|
||||
.slab_flags = SLAB_DESTROY_BY_RCU,
|
||||
.rsk_prot = &dccp6_request_sock_ops,
|
||||
.twsk_prot = &dccp6_timewait_sock_ops,
|
||||
.h.hashinfo = &dccp_hashinfo,
|
||||
|
@@ -45,11 +45,6 @@ EXPORT_SYMBOL_GPL(dccp_death_row);
|
||||
void dccp_minisock_init(struct dccp_minisock *dmsk)
|
||||
{
|
||||
dmsk->dccpms_sequence_window = sysctl_dccp_feat_sequence_window;
|
||||
dmsk->dccpms_rx_ccid = sysctl_dccp_feat_rx_ccid;
|
||||
dmsk->dccpms_tx_ccid = sysctl_dccp_feat_tx_ccid;
|
||||
dmsk->dccpms_ack_ratio = sysctl_dccp_feat_ack_ratio;
|
||||
dmsk->dccpms_send_ack_vector = sysctl_dccp_feat_send_ack_vector;
|
||||
dmsk->dccpms_send_ndp_count = sysctl_dccp_feat_send_ndp_count;
|
||||
}
|
||||
|
||||
void dccp_time_wait(struct sock *sk, int state, int timeo)
|
||||
@@ -112,7 +107,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
|
||||
struct sock *newsk = inet_csk_clone(sk, req, GFP_ATOMIC);
|
||||
|
||||
if (newsk != NULL) {
|
||||
const struct dccp_request_sock *dreq = dccp_rsk(req);
|
||||
struct dccp_request_sock *dreq = dccp_rsk(req);
|
||||
struct inet_connection_sock *newicsk = inet_csk(newsk);
|
||||
struct dccp_sock *newdp = dccp_sk(newsk);
|
||||
struct dccp_minisock *newdmsk = dccp_msk(newsk);
|
||||
@@ -125,35 +120,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
|
||||
newdp->dccps_timestamp_time = dreq->dreq_timestamp_time;
|
||||
newicsk->icsk_rto = DCCP_TIMEOUT_INIT;
|
||||
|
||||
if (dccp_feat_clone(sk, newsk))
|
||||
goto out_free;
|
||||
|
||||
if (newdmsk->dccpms_send_ack_vector) {
|
||||
newdp->dccps_hc_rx_ackvec =
|
||||
dccp_ackvec_alloc(GFP_ATOMIC);
|
||||
if (unlikely(newdp->dccps_hc_rx_ackvec == NULL))
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
newdp->dccps_hc_rx_ccid =
|
||||
ccid_hc_rx_new(newdmsk->dccpms_rx_ccid,
|
||||
newsk, GFP_ATOMIC);
|
||||
newdp->dccps_hc_tx_ccid =
|
||||
ccid_hc_tx_new(newdmsk->dccpms_tx_ccid,
|
||||
newsk, GFP_ATOMIC);
|
||||
if (unlikely(newdp->dccps_hc_rx_ccid == NULL ||
|
||||
newdp->dccps_hc_tx_ccid == NULL)) {
|
||||
dccp_ackvec_free(newdp->dccps_hc_rx_ackvec);
|
||||
ccid_hc_rx_delete(newdp->dccps_hc_rx_ccid, newsk);
|
||||
ccid_hc_tx_delete(newdp->dccps_hc_tx_ccid, newsk);
|
||||
out_free:
|
||||
/* It is still raw copy of parent, so invalidate
|
||||
* destructor and make plain sk_free() */
|
||||
newsk->sk_destruct = NULL;
|
||||
sk_free(newsk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&newdp->dccps_featneg);
|
||||
/*
|
||||
* Step 3: Process LISTEN state
|
||||
*
|
||||
@@ -184,6 +151,17 @@ out_free:
|
||||
dccp_set_seqno(&newdp->dccps_awl,
|
||||
max48(newdp->dccps_awl, newdp->dccps_iss));
|
||||
|
||||
/*
|
||||
* Activate features after initialising the sequence numbers,
|
||||
* since CCID initialisation may depend on GSS, ISR, ISS etc.
|
||||
*/
|
||||
if (dccp_feat_activate_values(newsk, &dreq->dreq_featneg)) {
|
||||
/* It is still raw copy of parent, so invalidate
|
||||
* destructor and make plain sk_free() */
|
||||
newsk->sk_destruct = NULL;
|
||||
sk_free(newsk);
|
||||
return NULL;
|
||||
}
|
||||
dccp_init_xmit_timers(newsk);
|
||||
|
||||
DCCP_INC_STATS_BH(DCCP_MIB_PASSIVEOPENS);
|
||||
@@ -304,7 +282,8 @@ void dccp_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
|
||||
|
||||
EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack);
|
||||
|
||||
void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb)
|
||||
int dccp_reqsk_init(struct request_sock *req,
|
||||
struct dccp_sock const *dp, struct sk_buff const *skb)
|
||||
{
|
||||
struct dccp_request_sock *dreq = dccp_rsk(req);
|
||||
|
||||
@@ -313,6 +292,9 @@ void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb)
|
||||
inet_rsk(req)->acked = 0;
|
||||
req->rcv_wnd = sysctl_dccp_feat_sequence_window;
|
||||
dreq->dreq_timestamp_echo = 0;
|
||||
|
||||
/* inherit feature negotiation options from listening socket */
|
||||
return dccp_feat_clone_list(&dp->dccps_featneg, &dreq->dreq_featneg);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(dccp_reqsk_init);
|
||||
|
@@ -26,20 +26,21 @@
|
||||
int sysctl_dccp_feat_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW;
|
||||
int sysctl_dccp_feat_rx_ccid = DCCPF_INITIAL_CCID;
|
||||
int sysctl_dccp_feat_tx_ccid = DCCPF_INITIAL_CCID;
|
||||
int sysctl_dccp_feat_ack_ratio = DCCPF_INITIAL_ACK_RATIO;
|
||||
int sysctl_dccp_feat_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR;
|
||||
int sysctl_dccp_feat_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT;
|
||||
|
||||
static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len)
|
||||
u64 dccp_decode_value_var(const u8 *bf, const u8 len)
|
||||
{
|
||||
u32 value = 0;
|
||||
u64 value = 0;
|
||||
|
||||
if (len >= DCCP_OPTVAL_MAXLEN)
|
||||
value += ((u64)*bf++) << 40;
|
||||
if (len > 4)
|
||||
value += ((u64)*bf++) << 32;
|
||||
if (len > 3)
|
||||
value += *bf++ << 24;
|
||||
value += ((u64)*bf++) << 24;
|
||||
if (len > 2)
|
||||
value += *bf++ << 16;
|
||||
value += ((u64)*bf++) << 16;
|
||||
if (len > 1)
|
||||
value += *bf++ << 8;
|
||||
value += ((u64)*bf++) << 8;
|
||||
if (len > 0)
|
||||
value += *bf;
|
||||
|
||||
@@ -64,7 +65,7 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
|
||||
(dh->dccph_doff * 4);
|
||||
struct dccp_options_received *opt_recv = &dp->dccps_options_received;
|
||||
unsigned char opt, len;
|
||||
unsigned char *value;
|
||||
unsigned char *uninitialized_var(value);
|
||||
u32 elapsed_time;
|
||||
__be32 opt_val;
|
||||
int rc;
|
||||
@@ -131,41 +132,19 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
|
||||
dccp_pr_debug("%s opt: NDP count=%llu\n", dccp_role(sk),
|
||||
(unsigned long long)opt_recv->dccpor_ndp);
|
||||
break;
|
||||
case DCCPO_CHANGE_L:
|
||||
/* fall through */
|
||||
case DCCPO_CHANGE_R:
|
||||
if (pkt_type == DCCP_PKT_DATA)
|
||||
case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R:
|
||||
if (pkt_type == DCCP_PKT_DATA) /* RFC 4340, 6 */
|
||||
break;
|
||||
if (len < 2)
|
||||
goto out_invalid_option;
|
||||
rc = dccp_feat_change_recv(sk, opt, *value, value + 1,
|
||||
len - 1);
|
||||
/*
|
||||
* When there is a change error, change_recv is
|
||||
* responsible for dealing with it. i.e. reply with an
|
||||
* empty confirm.
|
||||
* If the change was mandatory, then we need to die.
|
||||
*/
|
||||
if (rc && mandatory)
|
||||
goto out_invalid_option;
|
||||
break;
|
||||
case DCCPO_CONFIRM_L:
|
||||
/* fall through */
|
||||
case DCCPO_CONFIRM_R:
|
||||
if (pkt_type == DCCP_PKT_DATA)
|
||||
break;
|
||||
if (len < 2) /* FIXME this disallows empty confirm */
|
||||
goto out_invalid_option;
|
||||
if (dccp_feat_confirm_recv(sk, opt, *value,
|
||||
value + 1, len - 1))
|
||||
goto out_invalid_option;
|
||||
rc = dccp_feat_parse_options(sk, dreq, mandatory, opt,
|
||||
*value, value + 1, len - 1);
|
||||
if (rc)
|
||||
goto out_featneg_failed;
|
||||
break;
|
||||
case DCCPO_ACK_VECTOR_0:
|
||||
case DCCPO_ACK_VECTOR_1:
|
||||
if (dccp_packet_without_ack(skb)) /* RFC 4340, 11.4 */
|
||||
break;
|
||||
|
||||
if (dccp_msk(sk)->dccpms_send_ack_vector &&
|
||||
if (dp->dccps_hc_rx_ackvec != NULL &&
|
||||
dccp_ackvec_parse(sk, skb, &ackno, opt, value, len))
|
||||
goto out_invalid_option;
|
||||
break;
|
||||
@@ -289,8 +268,10 @@ out_nonsensical_length:
|
||||
|
||||
out_invalid_option:
|
||||
DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT);
|
||||
DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_OPTION_ERROR;
|
||||
DCCP_WARN("DCCP(%p): invalid option %d, len=%d", sk, opt, len);
|
||||
rc = DCCP_RESET_CODE_OPTION_ERROR;
|
||||
out_featneg_failed:
|
||||
DCCP_WARN("DCCP(%p): Option %d (len=%d) error=%u\n", sk, opt, len, rc);
|
||||
DCCP_SKB_CB(skb)->dccpd_reset_code = rc;
|
||||
DCCP_SKB_CB(skb)->dccpd_reset_data[0] = opt;
|
||||
DCCP_SKB_CB(skb)->dccpd_reset_data[1] = len > 0 ? value[0] : 0;
|
||||
DCCP_SKB_CB(skb)->dccpd_reset_data[2] = len > 1 ? value[1] : 0;
|
||||
@@ -299,9 +280,12 @@ out_invalid_option:
|
||||
|
||||
EXPORT_SYMBOL_GPL(dccp_parse_options);
|
||||
|
||||
static void dccp_encode_value_var(const u32 value, unsigned char *to,
|
||||
const unsigned int len)
|
||||
void dccp_encode_value_var(const u64 value, u8 *to, const u8 len)
|
||||
{
|
||||
if (len >= DCCP_OPTVAL_MAXLEN)
|
||||
*to++ = (value & 0xFF0000000000ull) >> 40;
|
||||
if (len > 4)
|
||||
*to++ = (value & 0xFF00000000ull) >> 32;
|
||||
if (len > 3)
|
||||
*to++ = (value & 0xFF000000) >> 24;
|
||||
if (len > 2)
|
||||
@@ -461,23 +445,61 @@ static int dccp_insert_option_timestamp_echo(struct dccp_sock *dp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
|
||||
u8 *val, u8 len)
|
||||
/**
|
||||
* dccp_insert_option_mandatory - Mandatory option (5.8.2)
|
||||
* Note that since we are using skb_push, this function needs to be called
|
||||
* _after_ inserting the option it is supposed to influence (stack order).
|
||||
*/
|
||||
int dccp_insert_option_mandatory(struct sk_buff *skb)
|
||||
{
|
||||
u8 *to;
|
||||
if (DCCP_SKB_CB(skb)->dccpd_opt_len >= DCCP_MAX_OPT_LEN)
|
||||
return -1;
|
||||
|
||||
if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 3 > DCCP_MAX_OPT_LEN) {
|
||||
DCCP_WARN("packet too small for feature %d option!\n", feat);
|
||||
DCCP_SKB_CB(skb)->dccpd_opt_len++;
|
||||
*skb_push(skb, 1) = DCCPO_MANDATORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dccp_insert_fn_opt - Insert single Feature-Negotiation option into @skb
|
||||
* @type: %DCCPO_CHANGE_L, %DCCPO_CHANGE_R, %DCCPO_CONFIRM_L, %DCCPO_CONFIRM_R
|
||||
* @feat: one out of %dccp_feature_numbers
|
||||
* @val: NN value or SP array (preferred element first) to copy
|
||||
* @len: true length of @val in bytes (excluding first element repetition)
|
||||
* @repeat_first: whether to copy the first element of @val twice
|
||||
* The last argument is used to construct Confirm options, where the preferred
|
||||
* value and the preference list appear separately (RFC 4340, 6.3.1). Preference
|
||||
* lists are kept such that the preferred entry is always first, so we only need
|
||||
* to copy twice, and avoid the overhead of cloning into a bigger array.
|
||||
*/
|
||||
int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat,
|
||||
u8 *val, u8 len, bool repeat_first)
|
||||
{
|
||||
u8 tot_len, *to;
|
||||
|
||||
/* take the `Feature' field and possible repetition into account */
|
||||
if (len > (DCCP_SINGLE_OPT_MAXLEN - 2)) {
|
||||
DCCP_WARN("length %u for feature %u too large\n", len, feat);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DCCP_SKB_CB(skb)->dccpd_opt_len += len + 3;
|
||||
if (unlikely(val == NULL || len == 0))
|
||||
len = repeat_first = 0;
|
||||
tot_len = 3 + repeat_first + len;
|
||||
|
||||
to = skb_push(skb, len + 3);
|
||||
if (DCCP_SKB_CB(skb)->dccpd_opt_len + tot_len > DCCP_MAX_OPT_LEN) {
|
||||
DCCP_WARN("packet too small for feature %d option!\n", feat);
|
||||
return -1;
|
||||
}
|
||||
DCCP_SKB_CB(skb)->dccpd_opt_len += tot_len;
|
||||
|
||||
to = skb_push(skb, tot_len);
|
||||
*to++ = type;
|
||||
*to++ = len + 3;
|
||||
*to++ = tot_len;
|
||||
*to++ = feat;
|
||||
|
||||
if (repeat_first)
|
||||
*to++ = *val;
|
||||
if (len)
|
||||
memcpy(to, val, len);
|
||||
|
||||
@@ -487,69 +509,6 @@ static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct dccp_minisock *dmsk = dccp_msk(sk);
|
||||
struct dccp_opt_pend *opt, *next;
|
||||
int change = 0;
|
||||
|
||||
/* confirm any options [NN opts] */
|
||||
list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) {
|
||||
dccp_insert_feat_opt(skb, opt->dccpop_type,
|
||||
opt->dccpop_feat, opt->dccpop_val,
|
||||
opt->dccpop_len);
|
||||
/* fear empty confirms */
|
||||
if (opt->dccpop_val)
|
||||
kfree(opt->dccpop_val);
|
||||
kfree(opt);
|
||||
}
|
||||
INIT_LIST_HEAD(&dmsk->dccpms_conf);
|
||||
|
||||
/* see which features we need to send */
|
||||
list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
|
||||
/* see if we need to send any confirm */
|
||||
if (opt->dccpop_sc) {
|
||||
dccp_insert_feat_opt(skb, opt->dccpop_type + 1,
|
||||
opt->dccpop_feat,
|
||||
opt->dccpop_sc->dccpoc_val,
|
||||
opt->dccpop_sc->dccpoc_len);
|
||||
|
||||
BUG_ON(!opt->dccpop_sc->dccpoc_val);
|
||||
kfree(opt->dccpop_sc->dccpoc_val);
|
||||
kfree(opt->dccpop_sc);
|
||||
opt->dccpop_sc = NULL;
|
||||
}
|
||||
|
||||
/* any option not confirmed, re-send it */
|
||||
if (!opt->dccpop_conf) {
|
||||
dccp_insert_feat_opt(skb, opt->dccpop_type,
|
||||
opt->dccpop_feat, opt->dccpop_val,
|
||||
opt->dccpop_len);
|
||||
change++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Retransmit timer.
|
||||
* If this is the master listening sock, we don't set a timer on it. It
|
||||
* should be fine because if the dude doesn't receive our RESPONSE
|
||||
* [which will contain the CHANGE] he will send another REQUEST which
|
||||
* will "retrnasmit" the change.
|
||||
*/
|
||||
if (change && dp->dccps_role != DCCP_ROLE_LISTEN) {
|
||||
dccp_pr_debug("reset feat negotiation timer %p\n", sk);
|
||||
|
||||
/* XXX don't reset the timer on re-transmissions. I.e. reset it
|
||||
* only when sending new stuff i guess. Currently the timer
|
||||
* never backs off because on re-transmission it just resets it!
|
||||
*/
|
||||
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
|
||||
inet_csk(sk)->icsk_rto, DCCP_RTO_MAX);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The length of all options needs to be a multiple of 4 (5.8) */
|
||||
static void dccp_insert_option_padding(struct sk_buff *skb)
|
||||
{
|
||||
@@ -565,19 +524,31 @@ static void dccp_insert_option_padding(struct sk_buff *skb)
|
||||
int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct dccp_minisock *dmsk = dccp_msk(sk);
|
||||
|
||||
DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
|
||||
|
||||
if (dmsk->dccpms_send_ndp_count &&
|
||||
dccp_insert_option_ndp(sk, skb))
|
||||
if (dp->dccps_send_ndp_count && dccp_insert_option_ndp(sk, skb))
|
||||
return -1;
|
||||
|
||||
if (!dccp_packet_without_ack(skb)) {
|
||||
if (dmsk->dccpms_send_ack_vector &&
|
||||
dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) &&
|
||||
dccp_insert_option_ackvec(sk, skb))
|
||||
if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA) {
|
||||
|
||||
/* Feature Negotiation */
|
||||
if (dccp_feat_insert_opts(dp, NULL, skb))
|
||||
return -1;
|
||||
|
||||
if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_REQUEST) {
|
||||
/*
|
||||
* Obtain RTT sample from Request/Response exchange.
|
||||
* This is currently used in CCID 3 initialisation.
|
||||
*/
|
||||
if (dccp_insert_option_timestamp(sk, skb))
|
||||
return -1;
|
||||
|
||||
} else if (dp->dccps_hc_rx_ackvec != NULL &&
|
||||
dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) &&
|
||||
dccp_insert_option_ackvec(sk, skb)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dp->dccps_hc_rx_insert_options) {
|
||||
@@ -586,21 +557,6 @@ int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
|
||||
dp->dccps_hc_rx_insert_options = 0;
|
||||
}
|
||||
|
||||
/* Feature negotiation */
|
||||
/* Data packets can't do feat negotiation */
|
||||
if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA &&
|
||||
DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATAACK &&
|
||||
dccp_insert_options_feat(sk, skb))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Obtain RTT sample from Request/Response exchange.
|
||||
* This is currently used in CCID 3 initialisation.
|
||||
*/
|
||||
if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_REQUEST &&
|
||||
dccp_insert_option_timestamp(sk, skb))
|
||||
return -1;
|
||||
|
||||
if (dp->dccps_timestamp_echo != 0 &&
|
||||
dccp_insert_option_timestamp_echo(dp, NULL, skb))
|
||||
return -1;
|
||||
@@ -613,6 +569,9 @@ int dccp_insert_options_rsk(struct dccp_request_sock *dreq, struct sk_buff *skb)
|
||||
{
|
||||
DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
|
||||
|
||||
if (dccp_feat_insert_opts(NULL, dreq, skb))
|
||||
return -1;
|
||||
|
||||
if (dreq->dreq_timestamp_echo != 0 &&
|
||||
dccp_insert_option_timestamp_echo(NULL, dreq, skb))
|
||||
return -1;
|
||||
|
@@ -175,7 +175,7 @@ unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu)
|
||||
* make it a multiple of 4
|
||||
*/
|
||||
|
||||
cur_mps -= ((5 + 6 + 10 + 6 + 6 + 6 + 3) / 4) * 4;
|
||||
cur_mps -= roundup(5 + 6 + 10 + 6 + 6 + 6, 4);
|
||||
|
||||
/* And store cached results */
|
||||
icsk->icsk_pmtu_cookie = pmtu;
|
||||
@@ -339,10 +339,12 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
|
||||
DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
|
||||
DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss;
|
||||
|
||||
if (dccp_insert_options_rsk(dreq, skb)) {
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
/* Resolve feature dependencies resulting from choice of CCID */
|
||||
if (dccp_feat_server_ccid_dependencies(dreq))
|
||||
goto response_failed;
|
||||
|
||||
if (dccp_insert_options_rsk(dreq, skb))
|
||||
goto response_failed;
|
||||
|
||||
/* Build and checksum header */
|
||||
dh = dccp_zeroed_hdr(skb, dccp_header_size);
|
||||
@@ -363,6 +365,9 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
|
||||
inet_rsk(req)->acked = 1;
|
||||
DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
|
||||
return skb;
|
||||
response_failed:
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(dccp_make_response);
|
||||
@@ -469,6 +474,10 @@ int dccp_connect(struct sock *sk)
|
||||
struct sk_buff *skb;
|
||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
|
||||
/* do not connect if feature negotiation setup fails */
|
||||
if (dccp_feat_finalise_settings(dccp_sk(sk)))
|
||||
return -EPROTO;
|
||||
|
||||
dccp_connect_init(sk);
|
||||
|
||||
skb = alloc_skb(sk->sk_prot->max_header, sk->sk_allocation);
|
||||
|
@@ -74,30 +74,27 @@ static void printl(const char *fmt, ...)
|
||||
static int jdccp_sendmsg(struct kiocb *iocb, struct sock *sk,
|
||||
struct msghdr *msg, size_t size)
|
||||
{
|
||||
const struct dccp_minisock *dmsk = dccp_msk(sk);
|
||||
const struct inet_sock *inet = inet_sk(sk);
|
||||
const struct ccid3_hc_tx_sock *hctx;
|
||||
struct ccid3_hc_tx_sock *hctx = NULL;
|
||||
|
||||
if (dmsk->dccpms_tx_ccid == DCCPC_CCID3)
|
||||
if (ccid_get_current_tx_ccid(dccp_sk(sk)) == DCCPC_CCID3)
|
||||
hctx = ccid3_hc_tx_sk(sk);
|
||||
else
|
||||
hctx = NULL;
|
||||
|
||||
if (port == 0 || ntohs(inet->dport) == port ||
|
||||
ntohs(inet->sport) == port) {
|
||||
if (hctx)
|
||||
printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %d %d %d %u "
|
||||
printl("%pI4:%u %pI4:%u %d %d %d %d %u "
|
||||
"%llu %llu %d\n",
|
||||
NIPQUAD(inet->saddr), ntohs(inet->sport),
|
||||
NIPQUAD(inet->daddr), ntohs(inet->dport), size,
|
||||
&inet->saddr, ntohs(inet->sport),
|
||||
&inet->daddr, ntohs(inet->dport), size,
|
||||
hctx->ccid3hctx_s, hctx->ccid3hctx_rtt,
|
||||
hctx->ccid3hctx_p, hctx->ccid3hctx_x_calc,
|
||||
hctx->ccid3hctx_x_recv >> 6,
|
||||
hctx->ccid3hctx_x >> 6, hctx->ccid3hctx_t_ipi);
|
||||
else
|
||||
printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d\n",
|
||||
NIPQUAD(inet->saddr), ntohs(inet->sport),
|
||||
NIPQUAD(inet->daddr), ntohs(inet->dport), size);
|
||||
printl("%pI4:%u %pI4:%u %d\n",
|
||||
&inet->saddr, ntohs(inet->sport),
|
||||
&inet->daddr, ntohs(inet->dport), size);
|
||||
}
|
||||
|
||||
jprobe_return();
|
||||
|
224
net/dccp/proto.c
224
net/dccp/proto.c
@@ -40,16 +40,10 @@ DEFINE_SNMP_STAT(struct dccp_mib, dccp_statistics) __read_mostly;
|
||||
|
||||
EXPORT_SYMBOL_GPL(dccp_statistics);
|
||||
|
||||
atomic_t dccp_orphan_count = ATOMIC_INIT(0);
|
||||
|
||||
struct percpu_counter dccp_orphan_count;
|
||||
EXPORT_SYMBOL_GPL(dccp_orphan_count);
|
||||
|
||||
struct inet_hashinfo __cacheline_aligned dccp_hashinfo = {
|
||||
.lhash_lock = RW_LOCK_UNLOCKED,
|
||||
.lhash_users = ATOMIC_INIT(0),
|
||||
.lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(dccp_hashinfo.lhash_wait),
|
||||
};
|
||||
|
||||
struct inet_hashinfo dccp_hashinfo;
|
||||
EXPORT_SYMBOL_GPL(dccp_hashinfo);
|
||||
|
||||
/* the maximum queue length for tx in packets. 0 is no limit */
|
||||
@@ -67,6 +61,9 @@ void dccp_set_state(struct sock *sk, const int state)
|
||||
case DCCP_OPEN:
|
||||
if (oldstate != DCCP_OPEN)
|
||||
DCCP_INC_STATS(DCCP_MIB_CURRESTAB);
|
||||
/* Client retransmits all Confirm options until entering OPEN */
|
||||
if (oldstate == DCCP_PARTOPEN)
|
||||
dccp_feat_list_purge(&dccp_sk(sk)->dccps_featneg);
|
||||
break;
|
||||
|
||||
case DCCP_CLOSED:
|
||||
@@ -175,7 +172,6 @@ EXPORT_SYMBOL_GPL(dccp_state_name);
|
||||
int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct dccp_minisock *dmsk = dccp_msk(sk);
|
||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
|
||||
dccp_minisock_init(&dp->dccps_minisock);
|
||||
@@ -193,45 +189,10 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
|
||||
|
||||
dccp_init_xmit_timers(sk);
|
||||
|
||||
/*
|
||||
* FIXME: We're hardcoding the CCID, and doing this at this point makes
|
||||
* the listening (master) sock get CCID control blocks, which is not
|
||||
* necessary, but for now, to not mess with the test userspace apps,
|
||||
* lets leave it here, later the real solution is to do this in a
|
||||
* setsockopt(CCIDs-I-want/accept). -acme
|
||||
*/
|
||||
if (likely(ctl_sock_initialized)) {
|
||||
int rc = dccp_feat_init(dmsk);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (dmsk->dccpms_send_ack_vector) {
|
||||
dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL);
|
||||
if (dp->dccps_hc_rx_ackvec == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
dp->dccps_hc_rx_ccid = ccid_hc_rx_new(dmsk->dccpms_rx_ccid,
|
||||
sk, GFP_KERNEL);
|
||||
dp->dccps_hc_tx_ccid = ccid_hc_tx_new(dmsk->dccpms_tx_ccid,
|
||||
sk, GFP_KERNEL);
|
||||
if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
|
||||
dp->dccps_hc_tx_ccid == NULL)) {
|
||||
ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
|
||||
ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
|
||||
if (dmsk->dccpms_send_ack_vector) {
|
||||
dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
|
||||
dp->dccps_hc_rx_ackvec = NULL;
|
||||
}
|
||||
dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
} else {
|
||||
/* control socket doesn't need feat nego */
|
||||
INIT_LIST_HEAD(&dmsk->dccpms_pending);
|
||||
INIT_LIST_HEAD(&dmsk->dccpms_conf);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&dp->dccps_featneg);
|
||||
/* control socket doesn't need feat nego */
|
||||
if (likely(ctl_sock_initialized))
|
||||
return dccp_feat_init(sk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -240,7 +201,6 @@ EXPORT_SYMBOL_GPL(dccp_init_sock);
|
||||
void dccp_destroy_sock(struct sock *sk)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct dccp_minisock *dmsk = dccp_msk(sk);
|
||||
|
||||
/*
|
||||
* DCCP doesn't use sk_write_queue, just sk_send_head
|
||||
@@ -258,7 +218,7 @@ void dccp_destroy_sock(struct sock *sk)
|
||||
kfree(dp->dccps_service_list);
|
||||
dp->dccps_service_list = NULL;
|
||||
|
||||
if (dmsk->dccpms_send_ack_vector) {
|
||||
if (dp->dccps_hc_rx_ackvec != NULL) {
|
||||
dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
|
||||
dp->dccps_hc_rx_ackvec = NULL;
|
||||
}
|
||||
@@ -267,7 +227,7 @@ void dccp_destroy_sock(struct sock *sk)
|
||||
dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
|
||||
|
||||
/* clean up feature negotiation state */
|
||||
dccp_feat_clean(dmsk);
|
||||
dccp_feat_list_purge(&dp->dccps_featneg);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(dccp_destroy_sock);
|
||||
@@ -277,6 +237,9 @@ static inline int dccp_listen_start(struct sock *sk, int backlog)
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
|
||||
dp->dccps_role = DCCP_ROLE_LISTEN;
|
||||
/* do not start to listen if feature negotiation setup fails */
|
||||
if (dccp_feat_finalise_settings(dp))
|
||||
return -EPROTO;
|
||||
return inet_csk_listen_start(sk, backlog);
|
||||
}
|
||||
|
||||
@@ -466,42 +429,70 @@ static int dccp_setsockopt_service(struct sock *sk, const __be32 service,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* byte 1 is feature. the rest is the preference list */
|
||||
static int dccp_setsockopt_change(struct sock *sk, int type,
|
||||
struct dccp_so_feat __user *optval)
|
||||
static int dccp_setsockopt_cscov(struct sock *sk, int cscov, bool rx)
|
||||
{
|
||||
struct dccp_so_feat opt;
|
||||
u8 *val;
|
||||
int rc;
|
||||
u8 *list, len;
|
||||
int i, rc;
|
||||
|
||||
if (copy_from_user(&opt, optval, sizeof(opt)))
|
||||
return -EFAULT;
|
||||
if (cscov < 0 || cscov > 15)
|
||||
return -EINVAL;
|
||||
/*
|
||||
* rfc4340: 6.1. Change Options
|
||||
* Populate a list of permissible values, in the range cscov...15. This
|
||||
* is necessary since feature negotiation of single values only works if
|
||||
* both sides incidentally choose the same value. Since the list starts
|
||||
* lowest-value first, negotiation will pick the smallest shared value.
|
||||
*/
|
||||
if (opt.dccpsf_len < 1)
|
||||
if (cscov == 0)
|
||||
return 0;
|
||||
len = 16 - cscov;
|
||||
|
||||
list = kmalloc(len, GFP_KERNEL);
|
||||
if (list == NULL)
|
||||
return -ENOBUFS;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
list[i] = cscov++;
|
||||
|
||||
rc = dccp_feat_register_sp(sk, DCCPF_MIN_CSUM_COVER, rx, list, len);
|
||||
|
||||
if (rc == 0) {
|
||||
if (rx)
|
||||
dccp_sk(sk)->dccps_pcrlen = cscov;
|
||||
else
|
||||
dccp_sk(sk)->dccps_pcslen = cscov;
|
||||
}
|
||||
kfree(list);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dccp_setsockopt_ccid(struct sock *sk, int type,
|
||||
char __user *optval, int optlen)
|
||||
{
|
||||
u8 *val;
|
||||
int rc = 0;
|
||||
|
||||
if (optlen < 1 || optlen > DCCP_FEAT_MAX_SP_VALS)
|
||||
return -EINVAL;
|
||||
|
||||
val = kmalloc(opt.dccpsf_len, GFP_KERNEL);
|
||||
if (!val)
|
||||
val = kmalloc(optlen, GFP_KERNEL);
|
||||
if (val == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(val, opt.dccpsf_val, opt.dccpsf_len)) {
|
||||
rc = -EFAULT;
|
||||
goto out_free_val;
|
||||
if (copy_from_user(val, optval, optlen)) {
|
||||
kfree(val);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
rc = dccp_feat_change(dccp_msk(sk), type, opt.dccpsf_feat,
|
||||
val, opt.dccpsf_len, GFP_KERNEL);
|
||||
if (rc)
|
||||
goto out_free_val;
|
||||
lock_sock(sk);
|
||||
if (type == DCCP_SOCKOPT_TX_CCID || type == DCCP_SOCKOPT_CCID)
|
||||
rc = dccp_feat_register_sp(sk, DCCPF_CCID, 1, val, optlen);
|
||||
|
||||
out:
|
||||
return rc;
|
||||
if (!rc && (type == DCCP_SOCKOPT_RX_CCID || type == DCCP_SOCKOPT_CCID))
|
||||
rc = dccp_feat_register_sp(sk, DCCPF_CCID, 0, val, optlen);
|
||||
release_sock(sk);
|
||||
|
||||
out_free_val:
|
||||
kfree(val);
|
||||
goto out;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
|
||||
@@ -510,7 +501,21 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
int val, err = 0;
|
||||
|
||||
if (optlen < sizeof(int))
|
||||
switch (optname) {
|
||||
case DCCP_SOCKOPT_PACKET_SIZE:
|
||||
DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n");
|
||||
return 0;
|
||||
case DCCP_SOCKOPT_CHANGE_L:
|
||||
case DCCP_SOCKOPT_CHANGE_R:
|
||||
DCCP_WARN("sockopt(CHANGE_L/R) is deprecated: fix your app\n");
|
||||
return 0;
|
||||
case DCCP_SOCKOPT_CCID:
|
||||
case DCCP_SOCKOPT_RX_CCID:
|
||||
case DCCP_SOCKOPT_TX_CCID:
|
||||
return dccp_setsockopt_ccid(sk, optname, optval, optlen);
|
||||
}
|
||||
|
||||
if (optlen < (int)sizeof(int))
|
||||
return -EINVAL;
|
||||
|
||||
if (get_user(val, (int __user *)optval))
|
||||
@@ -521,53 +526,24 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
|
||||
|
||||
lock_sock(sk);
|
||||
switch (optname) {
|
||||
case DCCP_SOCKOPT_PACKET_SIZE:
|
||||
DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n");
|
||||
err = 0;
|
||||
break;
|
||||
case DCCP_SOCKOPT_CHANGE_L:
|
||||
if (optlen != sizeof(struct dccp_so_feat))
|
||||
err = -EINVAL;
|
||||
else
|
||||
err = dccp_setsockopt_change(sk, DCCPO_CHANGE_L,
|
||||
(struct dccp_so_feat __user *)
|
||||
optval);
|
||||
break;
|
||||
case DCCP_SOCKOPT_CHANGE_R:
|
||||
if (optlen != sizeof(struct dccp_so_feat))
|
||||
err = -EINVAL;
|
||||
else
|
||||
err = dccp_setsockopt_change(sk, DCCPO_CHANGE_R,
|
||||
(struct dccp_so_feat __user *)
|
||||
optval);
|
||||
break;
|
||||
case DCCP_SOCKOPT_SERVER_TIMEWAIT:
|
||||
if (dp->dccps_role != DCCP_ROLE_SERVER)
|
||||
err = -EOPNOTSUPP;
|
||||
else
|
||||
dp->dccps_server_timewait = (val != 0);
|
||||
break;
|
||||
case DCCP_SOCKOPT_SEND_CSCOV: /* sender side, RFC 4340, sec. 9.2 */
|
||||
if (val < 0 || val > 15)
|
||||
err = -EINVAL;
|
||||
else
|
||||
dp->dccps_pcslen = val;
|
||||
case DCCP_SOCKOPT_SEND_CSCOV:
|
||||
err = dccp_setsockopt_cscov(sk, val, false);
|
||||
break;
|
||||
case DCCP_SOCKOPT_RECV_CSCOV: /* receiver side, RFC 4340 sec. 9.2.1 */
|
||||
if (val < 0 || val > 15)
|
||||
err = -EINVAL;
|
||||
else {
|
||||
dp->dccps_pcrlen = val;
|
||||
/* FIXME: add feature negotiation,
|
||||
* ChangeL(MinimumChecksumCoverage, val) */
|
||||
}
|
||||
case DCCP_SOCKOPT_RECV_CSCOV:
|
||||
err = dccp_setsockopt_cscov(sk, val, true);
|
||||
break;
|
||||
default:
|
||||
err = -ENOPROTOOPT;
|
||||
break;
|
||||
}
|
||||
|
||||
release_sock(sk);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -648,6 +624,18 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
|
||||
case DCCP_SOCKOPT_GET_CUR_MPS:
|
||||
val = dp->dccps_mss_cache;
|
||||
break;
|
||||
case DCCP_SOCKOPT_AVAILABLE_CCIDS:
|
||||
return ccid_getsockopt_builtin_ccids(sk, len, optval, optlen);
|
||||
case DCCP_SOCKOPT_TX_CCID:
|
||||
val = ccid_get_current_tx_ccid(dp);
|
||||
if (val < 0)
|
||||
return -ENOPROTOOPT;
|
||||
break;
|
||||
case DCCP_SOCKOPT_RX_CCID:
|
||||
val = ccid_get_current_rx_ccid(dp);
|
||||
if (val < 0)
|
||||
return -ENOPROTOOPT;
|
||||
break;
|
||||
case DCCP_SOCKOPT_SERVER_TIMEWAIT:
|
||||
val = dp->dccps_server_timewait;
|
||||
break;
|
||||
@@ -976,7 +964,7 @@ adjudge_to_death:
|
||||
state = sk->sk_state;
|
||||
sock_hold(sk);
|
||||
sock_orphan(sk);
|
||||
atomic_inc(sk->sk_prot->orphan_count);
|
||||
percpu_counter_inc(sk->sk_prot->orphan_count);
|
||||
|
||||
/*
|
||||
* It is the last release_sock in its life. It will remove backlog.
|
||||
@@ -1040,17 +1028,21 @@ static int __init dccp_init(void)
|
||||
{
|
||||
unsigned long goal;
|
||||
int ehash_order, bhash_order, i;
|
||||
int rc = -ENOBUFS;
|
||||
int rc;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct dccp_skb_cb) >
|
||||
FIELD_SIZEOF(struct sk_buff, cb));
|
||||
|
||||
rc = percpu_counter_init(&dccp_orphan_count, 0);
|
||||
if (rc)
|
||||
goto out;
|
||||
rc = -ENOBUFS;
|
||||
inet_hashinfo_init(&dccp_hashinfo);
|
||||
dccp_hashinfo.bind_bucket_cachep =
|
||||
kmem_cache_create("dccp_bind_bucket",
|
||||
sizeof(struct inet_bind_bucket), 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
if (!dccp_hashinfo.bind_bucket_cachep)
|
||||
goto out;
|
||||
goto out_free_percpu;
|
||||
|
||||
/*
|
||||
* Size and allocate the main established and bind bucket
|
||||
@@ -1084,8 +1076,8 @@ static int __init dccp_init(void)
|
||||
}
|
||||
|
||||
for (i = 0; i < dccp_hashinfo.ehash_size; i++) {
|
||||
INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].chain);
|
||||
INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].twchain);
|
||||
INIT_HLIST_NULLS_HEAD(&dccp_hashinfo.ehash[i].chain, i);
|
||||
INIT_HLIST_NULLS_HEAD(&dccp_hashinfo.ehash[i].twchain, i);
|
||||
}
|
||||
|
||||
if (inet_ehash_locks_alloc(&dccp_hashinfo))
|
||||
@@ -1143,6 +1135,8 @@ out_free_dccp_ehash:
|
||||
out_free_bind_bucket_cachep:
|
||||
kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
|
||||
dccp_hashinfo.bind_bucket_cachep = NULL;
|
||||
out_free_percpu:
|
||||
percpu_counter_destroy(&dccp_orphan_count);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@@ -40,27 +40,6 @@ static struct ctl_table dccp_default_table[] = {
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.procname = "ack_ratio",
|
||||
.data = &sysctl_dccp_feat_ack_ratio,
|
||||
.maxlen = sizeof(sysctl_dccp_feat_ack_ratio),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.procname = "send_ackvec",
|
||||
.data = &sysctl_dccp_feat_send_ack_vector,
|
||||
.maxlen = sizeof(sysctl_dccp_feat_send_ack_vector),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.procname = "send_ndp",
|
||||
.data = &sysctl_dccp_feat_send_ndp_count,
|
||||
.maxlen = sizeof(sysctl_dccp_feat_send_ndp_count),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.procname = "request_retries",
|
||||
.data = &sysctl_dccp_request_retries,
|
||||
|
@@ -87,17 +87,6 @@ static void dccp_retransmit_timer(struct sock *sk)
|
||||
{
|
||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
|
||||
/* retransmit timer is used for feature negotiation throughout
|
||||
* connection. In this case, no packet is re-transmitted, but rather an
|
||||
* ack is generated and pending changes are placed into its options.
|
||||
*/
|
||||
if (sk->sk_send_head == NULL) {
|
||||
dccp_pr_debug("feat negotiation retransmit timeout %p\n", sk);
|
||||
if (sk->sk_state == DCCP_OPEN)
|
||||
dccp_send_ack(sk);
|
||||
goto backoff;
|
||||
}
|
||||
|
||||
/*
|
||||
* More than than 4MSL (8 minutes) has passed, a RESET(aborted) was
|
||||
* sent, no need to retransmit, this sock is dead.
|
||||
@@ -126,7 +115,6 @@ static void dccp_retransmit_timer(struct sock *sk)
|
||||
return;
|
||||
}
|
||||
|
||||
backoff:
|
||||
icsk->icsk_backoff++;
|
||||
|
||||
icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX);
|
||||
|
@@ -167,7 +167,7 @@ static struct hlist_head *dn_find_list(struct sock *sk)
|
||||
if (scp->addr.sdn_flags & SDF_WILD)
|
||||
return hlist_empty(&dn_wild_sk) ? &dn_wild_sk : NULL;
|
||||
|
||||
return &dn_sk_hash[dn_ntohs(scp->addrloc) & DN_SK_HASH_MASK];
|
||||
return &dn_sk_hash[le16_to_cpu(scp->addrloc) & DN_SK_HASH_MASK];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -181,7 +181,7 @@ static int check_port(__le16 port)
|
||||
if (port == 0)
|
||||
return -1;
|
||||
|
||||
sk_for_each(sk, node, &dn_sk_hash[dn_ntohs(port) & DN_SK_HASH_MASK]) {
|
||||
sk_for_each(sk, node, &dn_sk_hash[le16_to_cpu(port) & DN_SK_HASH_MASK]) {
|
||||
struct dn_scp *scp = DN_SK(sk);
|
||||
if (scp->addrloc == port)
|
||||
return -1;
|
||||
@@ -195,12 +195,12 @@ static unsigned short port_alloc(struct sock *sk)
|
||||
static unsigned short port = 0x2000;
|
||||
unsigned short i_port = port;
|
||||
|
||||
while(check_port(dn_htons(++port)) != 0) {
|
||||
while(check_port(cpu_to_le16(++port)) != 0) {
|
||||
if (port == i_port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
scp->addrloc = dn_htons(port);
|
||||
scp->addrloc = cpu_to_le16(port);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -255,7 +255,7 @@ static struct hlist_head *listen_hash(struct sockaddr_dn *addr)
|
||||
|
||||
if (hash == 0) {
|
||||
hash = addr->sdn_objnamel;
|
||||
for(i = 0; i < dn_ntohs(addr->sdn_objnamel); i++) {
|
||||
for(i = 0; i < le16_to_cpu(addr->sdn_objnamel); i++) {
|
||||
hash ^= addr->sdn_objname[i];
|
||||
hash ^= (hash << 3);
|
||||
}
|
||||
@@ -297,16 +297,16 @@ int dn_sockaddr2username(struct sockaddr_dn *sdn, unsigned char *buf, unsigned c
|
||||
break;
|
||||
case 1:
|
||||
*buf++ = 0;
|
||||
*buf++ = dn_ntohs(sdn->sdn_objnamel);
|
||||
memcpy(buf, sdn->sdn_objname, dn_ntohs(sdn->sdn_objnamel));
|
||||
len = 3 + dn_ntohs(sdn->sdn_objnamel);
|
||||
*buf++ = le16_to_cpu(sdn->sdn_objnamel);
|
||||
memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
|
||||
len = 3 + le16_to_cpu(sdn->sdn_objnamel);
|
||||
break;
|
||||
case 2:
|
||||
memset(buf, 0, 5);
|
||||
buf += 5;
|
||||
*buf++ = dn_ntohs(sdn->sdn_objnamel);
|
||||
memcpy(buf, sdn->sdn_objname, dn_ntohs(sdn->sdn_objnamel));
|
||||
len = 7 + dn_ntohs(sdn->sdn_objnamel);
|
||||
*buf++ = le16_to_cpu(sdn->sdn_objnamel);
|
||||
memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
|
||||
len = 7 + le16_to_cpu(sdn->sdn_objnamel);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *sdn,
|
||||
int namel = 12;
|
||||
|
||||
sdn->sdn_objnum = 0;
|
||||
sdn->sdn_objnamel = dn_htons(0);
|
||||
sdn->sdn_objnamel = cpu_to_le16(0);
|
||||
memset(sdn->sdn_objname, 0, DN_MAXOBJL);
|
||||
|
||||
if (len < 2)
|
||||
@@ -361,13 +361,13 @@ int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *sdn,
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
sdn->sdn_objnamel = dn_htons(*data++);
|
||||
len -= dn_ntohs(sdn->sdn_objnamel);
|
||||
sdn->sdn_objnamel = cpu_to_le16(*data++);
|
||||
len -= le16_to_cpu(sdn->sdn_objnamel);
|
||||
|
||||
if ((len < 0) || (dn_ntohs(sdn->sdn_objnamel) > namel))
|
||||
if ((len < 0) || (le16_to_cpu(sdn->sdn_objnamel) > namel))
|
||||
return -1;
|
||||
|
||||
memcpy(sdn->sdn_objname, data, dn_ntohs(sdn->sdn_objnamel));
|
||||
memcpy(sdn->sdn_objname, data, le16_to_cpu(sdn->sdn_objnamel));
|
||||
|
||||
return size - len;
|
||||
}
|
||||
@@ -391,7 +391,7 @@ struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr)
|
||||
continue;
|
||||
if (scp->addr.sdn_objnamel != addr->sdn_objnamel)
|
||||
continue;
|
||||
if (memcmp(scp->addr.sdn_objname, addr->sdn_objname, dn_ntohs(addr->sdn_objnamel)) != 0)
|
||||
if (memcmp(scp->addr.sdn_objname, addr->sdn_objname, le16_to_cpu(addr->sdn_objnamel)) != 0)
|
||||
continue;
|
||||
}
|
||||
sock_hold(sk);
|
||||
@@ -419,7 +419,7 @@ struct sock *dn_find_by_skb(struct sk_buff *skb)
|
||||
struct dn_scp *scp;
|
||||
|
||||
read_lock(&dn_hash_lock);
|
||||
sk_for_each(sk, node, &dn_sk_hash[dn_ntohs(cb->dst_port) & DN_SK_HASH_MASK]) {
|
||||
sk_for_each(sk, node, &dn_sk_hash[le16_to_cpu(cb->dst_port) & DN_SK_HASH_MASK]) {
|
||||
scp = DN_SK(sk);
|
||||
if (cb->src != dn_saddr2dn(&scp->peer))
|
||||
continue;
|
||||
@@ -734,10 +734,10 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
if (saddr->sdn_family != AF_DECnet)
|
||||
return -EINVAL;
|
||||
|
||||
if (dn_ntohs(saddr->sdn_nodeaddrl) && (dn_ntohs(saddr->sdn_nodeaddrl) != 2))
|
||||
if (le16_to_cpu(saddr->sdn_nodeaddrl) && (le16_to_cpu(saddr->sdn_nodeaddrl) != 2))
|
||||
return -EINVAL;
|
||||
|
||||
if (dn_ntohs(saddr->sdn_objnamel) > DN_MAXOBJL)
|
||||
if (le16_to_cpu(saddr->sdn_objnamel) > DN_MAXOBJL)
|
||||
return -EINVAL;
|
||||
|
||||
if (saddr->sdn_flags & ~SDF_WILD)
|
||||
@@ -748,7 +748,7 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
return -EACCES;
|
||||
|
||||
if (!(saddr->sdn_flags & SDF_WILD)) {
|
||||
if (dn_ntohs(saddr->sdn_nodeaddrl)) {
|
||||
if (le16_to_cpu(saddr->sdn_nodeaddrl)) {
|
||||
read_lock(&dev_base_lock);
|
||||
ldev = NULL;
|
||||
for_each_netdev(&init_net, dev) {
|
||||
@@ -799,15 +799,15 @@ static int dn_auto_bind(struct socket *sock)
|
||||
if ((scp->accessdata.acc_accl != 0) &&
|
||||
(scp->accessdata.acc_accl <= 12)) {
|
||||
|
||||
scp->addr.sdn_objnamel = dn_htons(scp->accessdata.acc_accl);
|
||||
memcpy(scp->addr.sdn_objname, scp->accessdata.acc_acc, dn_ntohs(scp->addr.sdn_objnamel));
|
||||
scp->addr.sdn_objnamel = cpu_to_le16(scp->accessdata.acc_accl);
|
||||
memcpy(scp->addr.sdn_objname, scp->accessdata.acc_acc, le16_to_cpu(scp->addr.sdn_objnamel));
|
||||
|
||||
scp->accessdata.acc_accl = 0;
|
||||
memset(scp->accessdata.acc_acc, 0, 40);
|
||||
}
|
||||
/* End of compatibility stuff */
|
||||
|
||||
scp->addr.sdn_add.a_len = dn_htons(2);
|
||||
scp->addr.sdn_add.a_len = cpu_to_le16(2);
|
||||
rv = dn_dev_bind_default((__le16 *)scp->addr.sdn_add.a_addr);
|
||||
if (rv == 0) {
|
||||
rv = dn_hash_sock(sk);
|
||||
@@ -1027,7 +1027,7 @@ static void dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt)
|
||||
u16 len = *ptr++; /* yes, it's 8bit on the wire */
|
||||
|
||||
BUG_ON(len > 16); /* we've checked the contents earlier */
|
||||
opt->opt_optl = dn_htons(len);
|
||||
opt->opt_optl = cpu_to_le16(len);
|
||||
opt->opt_status = 0;
|
||||
memcpy(opt->opt_data, ptr, len);
|
||||
skb_pull(skb, len + 1);
|
||||
@@ -1375,7 +1375,7 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us
|
||||
if (optlen != sizeof(struct optdata_dn))
|
||||
return -EINVAL;
|
||||
|
||||
if (dn_ntohs(u.opt.opt_optl) > 16)
|
||||
if (le16_to_cpu(u.opt.opt_optl) > 16)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(&scp->conndata_out, &u.opt, optlen);
|
||||
@@ -1388,7 +1388,7 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us
|
||||
if (optlen != sizeof(struct optdata_dn))
|
||||
return -EINVAL;
|
||||
|
||||
if (dn_ntohs(u.opt.opt_optl) > 16)
|
||||
if (le16_to_cpu(u.opt.opt_optl) > 16)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(&scp->discdata_out, &u.opt, optlen);
|
||||
@@ -2213,12 +2213,12 @@ static void dn_printable_object(struct sockaddr_dn *dn, unsigned char *buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (dn_ntohs(dn->sdn_objnamel)) {
|
||||
switch (le16_to_cpu(dn->sdn_objnamel)) {
|
||||
case 0:
|
||||
sprintf(buf, "%d", dn->sdn_objnum);
|
||||
break;
|
||||
default:
|
||||
for (i = 0; i < dn_ntohs(dn->sdn_objnamel); i++) {
|
||||
for (i = 0; i < le16_to_cpu(dn->sdn_objnamel); i++) {
|
||||
buf[i] = dn->sdn_objname[i];
|
||||
if (IS_NOT_PRINTABLE(buf[i]))
|
||||
buf[i] = '.';
|
||||
@@ -2281,7 +2281,7 @@ static inline void dn_socket_format_entry(struct seq_file *seq, struct sock *sk)
|
||||
seq_printf(seq,
|
||||
"%6s/%04X %04d:%04d %04d:%04d %01d %-16s "
|
||||
"%6s/%04X %04d:%04d %04d:%04d %01d %-16s %4s %s\n",
|
||||
dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->addr)), buf1),
|
||||
dn_addr2asc(le16_to_cpu(dn_saddr2dn(&scp->addr)), buf1),
|
||||
scp->addrloc,
|
||||
scp->numdat,
|
||||
scp->numoth,
|
||||
@@ -2289,7 +2289,7 @@ static inline void dn_socket_format_entry(struct seq_file *seq, struct sock *sk)
|
||||
scp->ackxmt_oth,
|
||||
scp->flowloc_sw,
|
||||
local_object,
|
||||
dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->peer)), buf2),
|
||||
dn_addr2asc(le16_to_cpu(dn_saddr2dn(&scp->peer)), buf2),
|
||||
scp->addrrem,
|
||||
scp->numdat_rcv,
|
||||
scp->numoth_rcv,
|
||||
|
@@ -885,7 +885,7 @@ static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa)
|
||||
memcpy(msg->tiver, dn_eco_version, 3);
|
||||
dn_dn2eth(msg->id, ifa->ifa_local);
|
||||
msg->iinfo = DN_RT_INFO_ENDN;
|
||||
msg->blksize = dn_htons(mtu2blksize(dev));
|
||||
msg->blksize = cpu_to_le16(mtu2blksize(dev));
|
||||
msg->area = 0x00;
|
||||
memset(msg->seed, 0, 8);
|
||||
memcpy(msg->neighbor, dn_hiord, ETH_ALEN);
|
||||
@@ -895,13 +895,13 @@ static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa)
|
||||
dn_dn2eth(msg->neighbor, dn->addr);
|
||||
}
|
||||
|
||||
msg->timer = dn_htons((unsigned short)dn_db->parms.t3);
|
||||
msg->timer = cpu_to_le16((unsigned short)dn_db->parms.t3);
|
||||
msg->mpd = 0x00;
|
||||
msg->datalen = 0x02;
|
||||
memset(msg->data, 0xAA, 2);
|
||||
|
||||
pktlen = (__le16 *)skb_push(skb,2);
|
||||
*pktlen = dn_htons(skb->len - 2);
|
||||
*pktlen = cpu_to_le16(skb->len - 2);
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
|
||||
@@ -929,7 +929,7 @@ static int dn_am_i_a_router(struct dn_neigh *dn, struct dn_dev *dn_db, struct dn
|
||||
if (dn->priority != dn_db->parms.priority)
|
||||
return 0;
|
||||
|
||||
if (dn_ntohs(dn->addr) < dn_ntohs(ifa->ifa_local))
|
||||
if (le16_to_cpu(dn->addr) < le16_to_cpu(ifa->ifa_local))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -973,11 +973,11 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa)
|
||||
ptr += ETH_ALEN;
|
||||
*ptr++ = dn_db->parms.forwarding == 1 ?
|
||||
DN_RT_INFO_L1RT : DN_RT_INFO_L2RT;
|
||||
*((__le16 *)ptr) = dn_htons(mtu2blksize(dev));
|
||||
*((__le16 *)ptr) = cpu_to_le16(mtu2blksize(dev));
|
||||
ptr += 2;
|
||||
*ptr++ = dn_db->parms.priority; /* Priority */
|
||||
*ptr++ = 0; /* Area: Reserved */
|
||||
*((__le16 *)ptr) = dn_htons((unsigned short)dn_db->parms.t3);
|
||||
*((__le16 *)ptr) = cpu_to_le16((unsigned short)dn_db->parms.t3);
|
||||
ptr += 2;
|
||||
*ptr++ = 0; /* MPD: Reserved */
|
||||
i1 = ptr++;
|
||||
@@ -993,7 +993,7 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa)
|
||||
skb_trim(skb, (27 + *i2));
|
||||
|
||||
pktlen = (__le16 *)skb_push(skb, 2);
|
||||
*pktlen = dn_htons(skb->len - 2);
|
||||
*pktlen = cpu_to_le16(skb->len - 2);
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
|
||||
@@ -1106,7 +1106,7 @@ static void dn_dev_set_timer(struct net_device *dev)
|
||||
add_timer(&dn_db->timer);
|
||||
}
|
||||
|
||||
struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
|
||||
static struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
|
||||
{
|
||||
int i;
|
||||
struct dn_dev_parms *p = dn_dev_list;
|
||||
@@ -1401,8 +1401,8 @@ static int dn_dev_seq_show(struct seq_file *seq, void *v)
|
||||
mtu2blksize(dev),
|
||||
dn_db->parms.priority,
|
||||
dn_db->parms.state, dn_db->parms.name,
|
||||
dn_db->router ? dn_addr2asc(dn_ntohs(*(__le16 *)dn_db->router->primary_key), router_buf) : "",
|
||||
dn_db->peer ? dn_addr2asc(dn_ntohs(*(__le16 *)dn_db->peer->primary_key), peer_buf) : "");
|
||||
dn_db->router ? dn_addr2asc(le16_to_cpu(*(__le16 *)dn_db->router->primary_key), router_buf) : "",
|
||||
dn_db->peer ? dn_addr2asc(le16_to_cpu(*(__le16 *)dn_db->peer->primary_key), peer_buf) : "");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1445,7 +1445,7 @@ void __init dn_dev_init(void)
|
||||
return;
|
||||
}
|
||||
|
||||
decnet_address = dn_htons((addr[0] << 10) | addr[1]);
|
||||
decnet_address = cpu_to_le16((addr[0] << 10) | addr[1]);
|
||||
|
||||
dn_dev_devices_on();
|
||||
|
||||
|
@@ -250,7 +250,7 @@ static int dn_long_output(struct sk_buff *skb)
|
||||
data = skb_push(skb, sizeof(struct dn_long_packet) + 3);
|
||||
lp = (struct dn_long_packet *)(data+3);
|
||||
|
||||
*((__le16 *)data) = dn_htons(skb->len - 2);
|
||||
*((__le16 *)data) = cpu_to_le16(skb->len - 2);
|
||||
*(data + 2) = 1 | DN_RT_F_PF; /* Padding */
|
||||
|
||||
lp->msgflg = DN_RT_PKT_LONG|(cb->rt_flags&(DN_RT_F_IE|DN_RT_F_RQR|DN_RT_F_RTS));
|
||||
@@ -294,7 +294,7 @@ static int dn_short_output(struct sk_buff *skb)
|
||||
}
|
||||
|
||||
data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
|
||||
*((__le16 *)data) = dn_htons(skb->len - 2);
|
||||
*((__le16 *)data) = cpu_to_le16(skb->len - 2);
|
||||
sp = (struct dn_short_packet *)(data+2);
|
||||
|
||||
sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
|
||||
@@ -336,12 +336,12 @@ static int dn_phase3_output(struct sk_buff *skb)
|
||||
}
|
||||
|
||||
data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
|
||||
*((__le16 *)data) = dn_htons(skb->len - 2);
|
||||
*((__le16 *)data) = cpu_to_le16(skb->len - 2);
|
||||
sp = (struct dn_short_packet *)(data + 2);
|
||||
|
||||
sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
|
||||
sp->dstnode = cb->dst & dn_htons(0x03ff);
|
||||
sp->srcnode = cb->src & dn_htons(0x03ff);
|
||||
sp->dstnode = cb->dst & cpu_to_le16(0x03ff);
|
||||
sp->srcnode = cb->src & cpu_to_le16(0x03ff);
|
||||
sp->forward = cb->hops & 0x3f;
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
@@ -394,7 +394,7 @@ int dn_neigh_router_hello(struct sk_buff *skb)
|
||||
if (neigh->dev->type == ARPHRD_ETHER)
|
||||
memcpy(neigh->ha, ð_hdr(skb)->h_source, ETH_ALEN);
|
||||
|
||||
dn->blksize = dn_ntohs(msg->blksize);
|
||||
dn->blksize = le16_to_cpu(msg->blksize);
|
||||
dn->priority = msg->priority;
|
||||
|
||||
dn->flags &= ~DN_NDFLAG_P3;
|
||||
@@ -410,7 +410,7 @@ int dn_neigh_router_hello(struct sk_buff *skb)
|
||||
}
|
||||
|
||||
/* Only use routers in our area */
|
||||
if ((dn_ntohs(src)>>10) == (dn_ntohs((decnet_address))>>10)) {
|
||||
if ((le16_to_cpu(src)>>10) == (le16_to_cpu((decnet_address))>>10)) {
|
||||
if (!dn_db->router) {
|
||||
dn_db->router = neigh_clone(neigh);
|
||||
} else {
|
||||
@@ -453,7 +453,7 @@ int dn_neigh_endnode_hello(struct sk_buff *skb)
|
||||
if (neigh->dev->type == ARPHRD_ETHER)
|
||||
memcpy(neigh->ha, ð_hdr(skb)->h_source, ETH_ALEN);
|
||||
dn->flags &= ~(DN_NDFLAG_R1 | DN_NDFLAG_R2);
|
||||
dn->blksize = dn_ntohs(msg->blksize);
|
||||
dn->blksize = le16_to_cpu(msg->blksize);
|
||||
dn->priority = 0;
|
||||
}
|
||||
|
||||
@@ -543,7 +543,7 @@ static inline void dn_neigh_format_entry(struct seq_file *seq,
|
||||
|
||||
read_lock(&n->lock);
|
||||
seq_printf(seq, "%-7s %s%s%s %02x %02d %07ld %-8s\n",
|
||||
dn_addr2asc(dn_ntohs(dn->addr), buf),
|
||||
dn_addr2asc(le16_to_cpu(dn->addr), buf),
|
||||
(dn->flags&DN_NDFLAG_R1) ? "1" : "-",
|
||||
(dn->flags&DN_NDFLAG_R2) ? "2" : "-",
|
||||
(dn->flags&DN_NDFLAG_P3) ? "3" : "-",
|
||||
|
@@ -83,7 +83,9 @@ static void dn_log_martian(struct sk_buff *skb, const char *msg)
|
||||
if (decnet_log_martians && net_ratelimit()) {
|
||||
char *devname = skb->dev ? skb->dev->name : "???";
|
||||
struct dn_skb_cb *cb = DN_SKB_CB(skb);
|
||||
printk(KERN_INFO "DECnet: Martian packet (%s) dev=%s src=0x%04hx dst=0x%04hx srcport=0x%04hx dstport=0x%04hx\n", msg, devname, dn_ntohs(cb->src), dn_ntohs(cb->dst), dn_ntohs(cb->src_port), dn_ntohs(cb->dst_port));
|
||||
printk(KERN_INFO "DECnet: Martian packet (%s) dev=%s src=0x%04hx dst=0x%04hx srcport=0x%04hx dstport=0x%04hx\n",
|
||||
msg, devname, le16_to_cpu(cb->src), le16_to_cpu(cb->dst),
|
||||
le16_to_cpu(cb->src_port), le16_to_cpu(cb->dst_port));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +135,7 @@ static int dn_process_ack(struct sock *sk, struct sk_buff *skb, int oth)
|
||||
if (skb->len < 2)
|
||||
return len;
|
||||
|
||||
if ((ack = dn_ntohs(*ptr)) & 0x8000) {
|
||||
if ((ack = le16_to_cpu(*ptr)) & 0x8000) {
|
||||
skb_pull(skb, 2);
|
||||
ptr++;
|
||||
len += 2;
|
||||
@@ -147,7 +149,7 @@ static int dn_process_ack(struct sock *sk, struct sk_buff *skb, int oth)
|
||||
if (skb->len < 2)
|
||||
return len;
|
||||
|
||||
if ((ack = dn_ntohs(*ptr)) & 0x8000) {
|
||||
if ((ack = le16_to_cpu(*ptr)) & 0x8000) {
|
||||
skb_pull(skb, 2);
|
||||
len += 2;
|
||||
if ((ack & 0x4000) == 0) {
|
||||
@@ -237,7 +239,7 @@ static struct sock *dn_find_listener(struct sk_buff *skb, unsigned short *reason
|
||||
cb->dst_port = msg->dstaddr;
|
||||
cb->services = msg->services;
|
||||
cb->info = msg->info;
|
||||
cb->segsize = dn_ntohs(msg->segsize);
|
||||
cb->segsize = le16_to_cpu(msg->segsize);
|
||||
|
||||
if (!pskb_may_pull(skb, sizeof(*msg)))
|
||||
goto err_out;
|
||||
@@ -344,7 +346,7 @@ static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb)
|
||||
ptr = skb->data;
|
||||
cb->services = *ptr++;
|
||||
cb->info = *ptr++;
|
||||
cb->segsize = dn_ntohs(*(__le16 *)ptr);
|
||||
cb->segsize = le16_to_cpu(*(__le16 *)ptr);
|
||||
|
||||
if ((scp->state == DN_CI) || (scp->state == DN_CD)) {
|
||||
scp->persist = 0;
|
||||
@@ -361,7 +363,7 @@ static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb)
|
||||
if (skb->len > 0) {
|
||||
u16 dlen = *skb->data;
|
||||
if ((dlen <= 16) && (dlen <= skb->len)) {
|
||||
scp->conndata_in.opt_optl = dn_htons(dlen);
|
||||
scp->conndata_in.opt_optl = cpu_to_le16(dlen);
|
||||
skb_copy_from_linear_data_offset(skb, 1,
|
||||
scp->conndata_in.opt_data, dlen);
|
||||
}
|
||||
@@ -396,17 +398,17 @@ static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb)
|
||||
if (skb->len < 2)
|
||||
goto out;
|
||||
|
||||
reason = dn_ntohs(*(__le16 *)skb->data);
|
||||
reason = le16_to_cpu(*(__le16 *)skb->data);
|
||||
skb_pull(skb, 2);
|
||||
|
||||
scp->discdata_in.opt_status = dn_htons(reason);
|
||||
scp->discdata_in.opt_status = cpu_to_le16(reason);
|
||||
scp->discdata_in.opt_optl = 0;
|
||||
memset(scp->discdata_in.opt_data, 0, 16);
|
||||
|
||||
if (skb->len > 0) {
|
||||
u16 dlen = *skb->data;
|
||||
if ((dlen <= 16) && (dlen <= skb->len)) {
|
||||
scp->discdata_in.opt_optl = dn_htons(dlen);
|
||||
scp->discdata_in.opt_optl = cpu_to_le16(dlen);
|
||||
skb_copy_from_linear_data_offset(skb, 1, scp->discdata_in.opt_data, dlen);
|
||||
}
|
||||
}
|
||||
@@ -463,7 +465,7 @@ static void dn_nsp_disc_conf(struct sock *sk, struct sk_buff *skb)
|
||||
if (skb->len != 2)
|
||||
goto out;
|
||||
|
||||
reason = dn_ntohs(*(__le16 *)skb->data);
|
||||
reason = le16_to_cpu(*(__le16 *)skb->data);
|
||||
|
||||
sk->sk_state = TCP_CLOSE;
|
||||
|
||||
@@ -512,7 +514,7 @@ static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb)
|
||||
if (skb->len != 4)
|
||||
goto out;
|
||||
|
||||
segnum = dn_ntohs(*(__le16 *)ptr);
|
||||
segnum = le16_to_cpu(*(__le16 *)ptr);
|
||||
ptr += 2;
|
||||
lsflags = *(unsigned char *)ptr++;
|
||||
fcval = *ptr;
|
||||
@@ -620,7 +622,7 @@ static void dn_nsp_otherdata(struct sock *sk, struct sk_buff *skb)
|
||||
if (skb->len < 2)
|
||||
goto out;
|
||||
|
||||
cb->segnum = segnum = dn_ntohs(*(__le16 *)skb->data);
|
||||
cb->segnum = segnum = le16_to_cpu(*(__le16 *)skb->data);
|
||||
skb_pull(skb, 2);
|
||||
|
||||
if (seq_next(scp->numoth_rcv, segnum)) {
|
||||
@@ -648,7 +650,7 @@ static void dn_nsp_data(struct sock *sk, struct sk_buff *skb)
|
||||
if (skb->len < 2)
|
||||
goto out;
|
||||
|
||||
cb->segnum = segnum = dn_ntohs(*(__le16 *)skb->data);
|
||||
cb->segnum = segnum = le16_to_cpu(*(__le16 *)skb->data);
|
||||
skb_pull(skb, 2);
|
||||
|
||||
if (seq_next(scp->numdat_rcv, segnum)) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user