Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: drivers/net/wireless/ath/ath9k/recv.c drivers/net/wireless/mwifiex/pcie.c net/ipv6/sit.c The SIT driver conflict consists of a bug fix being done by hand in 'net' (missing u64_stats_init()) whilst in 'net-next' a helper was created (netdev_alloc_pcpu_stats()) which takes care of this. The two wireless conflicts were overlapping changes. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
+5
-21
@@ -121,13 +121,9 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
|
||||
if (!ro->recv_own_msgs && oskb->sk == sk)
|
||||
return;
|
||||
|
||||
/* do not pass frames with DLC > 8 to a legacy socket */
|
||||
if (!ro->fd_frames) {
|
||||
struct canfd_frame *cfd = (struct canfd_frame *)oskb->data;
|
||||
|
||||
if (unlikely(cfd->len > CAN_MAX_DLEN))
|
||||
return;
|
||||
}
|
||||
/* do not pass non-CAN2.0 frames to a legacy socket */
|
||||
if (!ro->fd_frames && oskb->len != CAN_MTU)
|
||||
return;
|
||||
|
||||
/* clone the given skb to be able to enqueue it into the rcv queue */
|
||||
skb = skb_clone(oskb, GFP_ATOMIC);
|
||||
@@ -738,9 +734,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
struct msghdr *msg, size_t size, int flags)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
struct raw_sock *ro = raw_sk(sk);
|
||||
struct sk_buff *skb;
|
||||
int rxmtu;
|
||||
int err = 0;
|
||||
int noblock;
|
||||
|
||||
@@ -751,20 +745,10 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
if (!skb)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* when serving a legacy socket the DLC <= 8 is already checked inside
|
||||
* raw_rcv(). Now check if we need to pass a canfd_frame to a legacy
|
||||
* socket and cut the possible CANFD_MTU/CAN_MTU length to CAN_MTU
|
||||
*/
|
||||
if (!ro->fd_frames)
|
||||
rxmtu = CAN_MTU;
|
||||
else
|
||||
rxmtu = skb->len;
|
||||
|
||||
if (size < rxmtu)
|
||||
if (size < skb->len)
|
||||
msg->msg_flags |= MSG_TRUNC;
|
||||
else
|
||||
size = rxmtu;
|
||||
size = skb->len;
|
||||
|
||||
err = memcpy_toiovec(msg->msg_iov, skb->data, size);
|
||||
if (err < 0) {
|
||||
|
||||
@@ -766,9 +766,6 @@ static void neigh_periodic_work(struct work_struct *work)
|
||||
nht = rcu_dereference_protected(tbl->nht,
|
||||
lockdep_is_held(&tbl->lock));
|
||||
|
||||
if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* periodically recompute ReachableTime from random function
|
||||
*/
|
||||
@@ -781,6 +778,9 @@ static void neigh_periodic_work(struct work_struct *work)
|
||||
neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
|
||||
}
|
||||
|
||||
if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
|
||||
goto out;
|
||||
|
||||
for (i = 0 ; i < (1 << nht->hash_shift); i++) {
|
||||
np = &nht->hash_buckets[i];
|
||||
|
||||
@@ -3047,7 +3047,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
|
||||
if (!t)
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(t->neigh_vars); i++) {
|
||||
for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
|
||||
t->neigh_vars[i].data += (long) p;
|
||||
t->neigh_vars[i].extra1 = dev;
|
||||
t->neigh_vars[i].extra2 = p;
|
||||
|
||||
@@ -707,9 +707,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
|
||||
new->mark = old->mark;
|
||||
new->skb_iif = old->skb_iif;
|
||||
__nf_copy(new, old);
|
||||
#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
|
||||
new->nf_trace = old->nf_trace;
|
||||
#endif
|
||||
#ifdef CONFIG_NET_SCHED
|
||||
new->tc_index = old->tc_index;
|
||||
#ifdef CONFIG_NET_CLS_ACT
|
||||
|
||||
@@ -297,7 +297,7 @@ static bool seq_nr_after(u16 a, u16 b)
|
||||
|
||||
void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx)
|
||||
{
|
||||
if ((dev_idx < 0) || (dev_idx >= HSR_MAX_DEV)) {
|
||||
if ((dev_idx < 0) || (dev_idx >= HSR_MAX_SLAVE)) {
|
||||
WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
+5
-2
@@ -1296,8 +1296,11 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
|
||||
|
||||
segs = ERR_PTR(-EPROTONOSUPPORT);
|
||||
|
||||
/* Note : following gso_segment() might change skb->encapsulation */
|
||||
udpfrag = !skb->encapsulation && proto == IPPROTO_UDP;
|
||||
if (skb->encapsulation &&
|
||||
skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP))
|
||||
udpfrag = proto == IPPROTO_UDP && encap;
|
||||
else
|
||||
udpfrag = proto == IPPROTO_UDP && !skb->encapsulation;
|
||||
|
||||
ops = rcu_dereference(inet_offloads[proto]);
|
||||
if (likely(ops && ops->callbacks.gso_segment))
|
||||
|
||||
@@ -422,9 +422,6 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
|
||||
to->tc_index = from->tc_index;
|
||||
#endif
|
||||
nf_copy(to, from);
|
||||
#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
|
||||
to->nf_trace = from->nf_trace;
|
||||
#endif
|
||||
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
|
||||
to->ipvs_property = from->ipvs_property;
|
||||
#endif
|
||||
|
||||
+4
-49
@@ -93,13 +93,14 @@ static void tunnel_dst_reset(struct ip_tunnel *t)
|
||||
tunnel_dst_set(t, NULL);
|
||||
}
|
||||
|
||||
static void tunnel_dst_reset_all(struct ip_tunnel *t)
|
||||
void ip_tunnel_dst_reset_all(struct ip_tunnel *t)
|
||||
{
|
||||
int i;
|
||||
|
||||
for_each_possible_cpu(i)
|
||||
__tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(ip_tunnel_dst_reset_all);
|
||||
|
||||
static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie)
|
||||
{
|
||||
@@ -119,52 +120,6 @@ static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie)
|
||||
return (struct rtable *)dst;
|
||||
}
|
||||
|
||||
/* Often modified stats are per cpu, other are shared (netdev->stats) */
|
||||
struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
|
||||
struct rtnl_link_stats64 *tot)
|
||||
{
|
||||
int i;
|
||||
|
||||
for_each_possible_cpu(i) {
|
||||
const struct pcpu_sw_netstats *tstats =
|
||||
per_cpu_ptr(dev->tstats, i);
|
||||
u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
|
||||
unsigned int start;
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin_bh(&tstats->syncp);
|
||||
rx_packets = tstats->rx_packets;
|
||||
tx_packets = tstats->tx_packets;
|
||||
rx_bytes = tstats->rx_bytes;
|
||||
tx_bytes = tstats->tx_bytes;
|
||||
} while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
|
||||
|
||||
tot->rx_packets += rx_packets;
|
||||
tot->tx_packets += tx_packets;
|
||||
tot->rx_bytes += rx_bytes;
|
||||
tot->tx_bytes += tx_bytes;
|
||||
}
|
||||
|
||||
tot->multicast = dev->stats.multicast;
|
||||
|
||||
tot->rx_crc_errors = dev->stats.rx_crc_errors;
|
||||
tot->rx_fifo_errors = dev->stats.rx_fifo_errors;
|
||||
tot->rx_length_errors = dev->stats.rx_length_errors;
|
||||
tot->rx_frame_errors = dev->stats.rx_frame_errors;
|
||||
tot->rx_errors = dev->stats.rx_errors;
|
||||
|
||||
tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
|
||||
tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
|
||||
tot->tx_dropped = dev->stats.tx_dropped;
|
||||
tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
|
||||
tot->tx_errors = dev->stats.tx_errors;
|
||||
|
||||
tot->collisions = dev->stats.collisions;
|
||||
|
||||
return tot;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64);
|
||||
|
||||
static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p,
|
||||
__be16 flags, __be32 key)
|
||||
{
|
||||
@@ -763,7 +718,7 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn,
|
||||
if (set_mtu)
|
||||
dev->mtu = mtu;
|
||||
}
|
||||
tunnel_dst_reset_all(t);
|
||||
ip_tunnel_dst_reset_all(t);
|
||||
netdev_state_change(dev);
|
||||
}
|
||||
|
||||
@@ -1091,7 +1046,7 @@ void ip_tunnel_uninit(struct net_device *dev)
|
||||
if (itn->fb_tunnel_dev != dev)
|
||||
ip_tunnel_del(netdev_priv(dev));
|
||||
|
||||
tunnel_dst_reset_all(tunnel);
|
||||
ip_tunnel_dst_reset_all(tunnel);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip_tunnel_uninit);
|
||||
|
||||
|
||||
@@ -108,7 +108,6 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto)
|
||||
nf_reset(skb);
|
||||
secpath_reset(skb);
|
||||
skb_clear_hash_if_not_l4(skb);
|
||||
skb_dst_drop(skb);
|
||||
skb->vlan_tci = 0;
|
||||
skb_set_queue_mapping(skb, 0);
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
@@ -148,3 +147,49 @@ error:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iptunnel_handle_offloads);
|
||||
|
||||
/* Often modified stats are per cpu, other are shared (netdev->stats) */
|
||||
struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
|
||||
struct rtnl_link_stats64 *tot)
|
||||
{
|
||||
int i;
|
||||
|
||||
for_each_possible_cpu(i) {
|
||||
const struct pcpu_sw_netstats *tstats =
|
||||
per_cpu_ptr(dev->tstats, i);
|
||||
u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
|
||||
unsigned int start;
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin_bh(&tstats->syncp);
|
||||
rx_packets = tstats->rx_packets;
|
||||
tx_packets = tstats->tx_packets;
|
||||
rx_bytes = tstats->rx_bytes;
|
||||
tx_bytes = tstats->tx_bytes;
|
||||
} while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
|
||||
|
||||
tot->rx_packets += rx_packets;
|
||||
tot->tx_packets += tx_packets;
|
||||
tot->rx_bytes += rx_bytes;
|
||||
tot->tx_bytes += tx_bytes;
|
||||
}
|
||||
|
||||
tot->multicast = dev->stats.multicast;
|
||||
|
||||
tot->rx_crc_errors = dev->stats.rx_crc_errors;
|
||||
tot->rx_fifo_errors = dev->stats.rx_fifo_errors;
|
||||
tot->rx_length_errors = dev->stats.rx_length_errors;
|
||||
tot->rx_frame_errors = dev->stats.rx_frame_errors;
|
||||
tot->rx_errors = dev->stats.rx_errors;
|
||||
|
||||
tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
|
||||
tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
|
||||
tot->tx_dropped = dev->stats.tx_dropped;
|
||||
tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
|
||||
tot->tx_errors = dev->stats.tx_errors;
|
||||
|
||||
tot->collisions = dev->stats.collisions;
|
||||
|
||||
return tot;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64);
|
||||
|
||||
@@ -1198,8 +1198,8 @@ static int snmp_translate(struct nf_conn *ct,
|
||||
map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip);
|
||||
} else {
|
||||
/* DNAT replies */
|
||||
map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip);
|
||||
map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip);
|
||||
map.from = NOCT1(&ct->tuplehash[!dir].tuple.src.u3.ip);
|
||||
map.to = NOCT1(&ct->tuplehash[dir].tuple.dst.u3.ip);
|
||||
}
|
||||
|
||||
if (map.from == map.to)
|
||||
|
||||
+5
-3
@@ -1044,7 +1044,8 @@ void tcp_free_fastopen_req(struct tcp_sock *tp)
|
||||
}
|
||||
}
|
||||
|
||||
static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size)
|
||||
static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
|
||||
int *copied, size_t size)
|
||||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
int err, flags;
|
||||
@@ -1059,11 +1060,12 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size)
|
||||
if (unlikely(tp->fastopen_req == NULL))
|
||||
return -ENOBUFS;
|
||||
tp->fastopen_req->data = msg;
|
||||
tp->fastopen_req->size = size;
|
||||
|
||||
flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
|
||||
err = __inet_stream_connect(sk->sk_socket, msg->msg_name,
|
||||
msg->msg_namelen, flags);
|
||||
*size = tp->fastopen_req->copied;
|
||||
*copied = tp->fastopen_req->copied;
|
||||
tcp_free_fastopen_req(tp);
|
||||
return err;
|
||||
}
|
||||
@@ -1083,7 +1085,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
||||
|
||||
flags = msg->msg_flags;
|
||||
if (flags & MSG_FASTOPEN) {
|
||||
err = tcp_sendmsg_fastopen(sk, msg, &copied_syn);
|
||||
err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size);
|
||||
if (err == -EINPROGRESS && copied_syn > 0)
|
||||
goto out;
|
||||
else if (err)
|
||||
|
||||
+1
-2
@@ -290,8 +290,7 @@ bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight)
|
||||
left = tp->snd_cwnd - in_flight;
|
||||
if (sk_can_gso(sk) &&
|
||||
left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd &&
|
||||
left * tp->mss_cache < sk->sk_gso_max_size &&
|
||||
left < sk->sk_gso_max_segs)
|
||||
left < tp->xmit_size_goal_segs)
|
||||
return true;
|
||||
return left <= tcp_max_tso_deferred_mss(tp);
|
||||
}
|
||||
|
||||
@@ -1944,8 +1944,9 @@ void tcp_enter_loss(struct sock *sk, int how)
|
||||
if (skb == tcp_send_head(sk))
|
||||
break;
|
||||
|
||||
if (TCP_SKB_CB(skb)->sacked & TCPCB_RETRANS)
|
||||
if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
|
||||
tp->undo_marker = 0;
|
||||
|
||||
TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED;
|
||||
if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || how) {
|
||||
TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED;
|
||||
|
||||
+16
-6
@@ -873,8 +873,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
|
||||
|
||||
if (unlikely(skb->fclone == SKB_FCLONE_ORIG &&
|
||||
fclone->fclone == SKB_FCLONE_CLONE))
|
||||
NET_INC_STATS_BH(sock_net(sk),
|
||||
LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES);
|
||||
NET_INC_STATS(sock_net(sk),
|
||||
LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES);
|
||||
|
||||
if (unlikely(skb_cloned(skb)))
|
||||
skb = pskb_copy(skb, gfp_mask);
|
||||
@@ -2358,6 +2358,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
unsigned int cur_mss;
|
||||
int err;
|
||||
|
||||
/* Inconslusive MTU probe */
|
||||
if (icsk->icsk_mtup.probe_size) {
|
||||
@@ -2421,11 +2422,15 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
|
||||
skb_headroom(skb) >= 0xFFFF)) {
|
||||
struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
|
||||
GFP_ATOMIC);
|
||||
return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
|
||||
-ENOBUFS;
|
||||
err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
|
||||
-ENOBUFS;
|
||||
} else {
|
||||
return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
|
||||
err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
if (likely(!err))
|
||||
TCP_SKB_CB(skb)->sacked |= TCPCB_EVER_RETRANS;
|
||||
return err;
|
||||
}
|
||||
|
||||
int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
|
||||
@@ -2930,7 +2935,12 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
|
||||
space = __tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) -
|
||||
MAX_TCP_OPTION_SPACE;
|
||||
|
||||
syn_data = skb_copy_expand(syn, skb_headroom(syn), space,
|
||||
space = min_t(size_t, space, fo->size);
|
||||
|
||||
/* limit to order-0 allocations */
|
||||
space = min_t(size_t, space, SKB_MAX_HEAD(MAX_TCP_HEADER));
|
||||
|
||||
syn_data = skb_copy_expand(syn, MAX_TCP_HEADER, space,
|
||||
sk->sk_allocation);
|
||||
if (syn_data == NULL)
|
||||
goto fallback;
|
||||
|
||||
@@ -138,6 +138,7 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION
|
||||
config IPV6_VTI
|
||||
tristate "Virtual (secure) IPv6: tunneling"
|
||||
select IPV6_TUNNEL
|
||||
select NET_IP_TUNNEL
|
||||
depends on INET6_XFRM_MODE_TUNNEL
|
||||
---help---
|
||||
Tunneling means encapsulating data of one protocol type within
|
||||
|
||||
@@ -212,7 +212,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
|
||||
found = (nexthdr == target);
|
||||
|
||||
if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
|
||||
if (target < 0)
|
||||
if (target < 0 || found)
|
||||
break;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
+12
-8
@@ -89,7 +89,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
|
||||
unsigned int unfrag_ip6hlen;
|
||||
u8 *prevhdr;
|
||||
int offset = 0;
|
||||
bool tunnel;
|
||||
bool encap, udpfrag;
|
||||
int nhoff;
|
||||
|
||||
if (unlikely(skb_shinfo(skb)->gso_type &
|
||||
@@ -110,8 +110,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
|
||||
if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
|
||||
goto out;
|
||||
|
||||
tunnel = SKB_GSO_CB(skb)->encap_level > 0;
|
||||
if (tunnel)
|
||||
encap = SKB_GSO_CB(skb)->encap_level > 0;
|
||||
if (encap)
|
||||
features = skb->dev->hw_enc_features & netif_skb_features(skb);
|
||||
SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h);
|
||||
|
||||
@@ -121,6 +121,12 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
|
||||
|
||||
proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
|
||||
|
||||
if (skb->encapsulation &&
|
||||
skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP))
|
||||
udpfrag = proto == IPPROTO_UDP && encap;
|
||||
else
|
||||
udpfrag = proto == IPPROTO_UDP && !skb->encapsulation;
|
||||
|
||||
ops = rcu_dereference(inet6_offloads[proto]);
|
||||
if (likely(ops && ops->callbacks.gso_segment)) {
|
||||
skb_reset_transport_header(skb);
|
||||
@@ -133,13 +139,9 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
|
||||
for (skb = segs; skb; skb = skb->next) {
|
||||
ipv6h = (struct ipv6hdr *)(skb_mac_header(skb) + nhoff);
|
||||
ipv6h->payload_len = htons(skb->len - nhoff - sizeof(*ipv6h));
|
||||
if (tunnel) {
|
||||
skb_reset_inner_headers(skb);
|
||||
skb->encapsulation = 1;
|
||||
}
|
||||
skb->network_header = (u8 *)ipv6h - skb->head;
|
||||
|
||||
if (!tunnel && proto == IPPROTO_UDP) {
|
||||
if (udpfrag) {
|
||||
unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
|
||||
fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen);
|
||||
fptr->frag_off = htons(offset);
|
||||
@@ -148,6 +150,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
|
||||
offset += (ntohs(ipv6h->payload_len) -
|
||||
sizeof(struct frag_hdr));
|
||||
}
|
||||
if (encap)
|
||||
skb_reset_inner_headers(skb);
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
@@ -530,9 +530,6 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
|
||||
to->tc_index = from->tc_index;
|
||||
#endif
|
||||
nf_copy(to, from);
|
||||
#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
|
||||
to->nf_trace = from->nf_trace;
|
||||
#endif
|
||||
skb_copy_secmark(to, from);
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +135,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
||||
fl6.flowi6_proto = IPPROTO_ICMPV6;
|
||||
fl6.saddr = np->saddr;
|
||||
fl6.daddr = *daddr;
|
||||
fl6.flowi6_mark = sk->sk_mark;
|
||||
fl6.fl6_icmp_type = user_icmph.icmp6_type;
|
||||
fl6.fl6_icmp_code = user_icmph.icmp6_code;
|
||||
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
|
||||
|
||||
@@ -475,6 +475,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
|
||||
ipip6_tunnel_unlink(sitn, tunnel);
|
||||
ipip6_tunnel_del_prl(tunnel, NULL);
|
||||
}
|
||||
ip_tunnel_dst_reset_all(tunnel);
|
||||
dev_put(dev);
|
||||
}
|
||||
|
||||
@@ -1082,6 +1083,7 @@ static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p)
|
||||
t->parms.link = p->link;
|
||||
ipip6_tunnel_bind_dev(t->dev);
|
||||
}
|
||||
ip_tunnel_dst_reset_all(t);
|
||||
netdev_state_change(t->dev);
|
||||
}
|
||||
|
||||
@@ -1112,6 +1114,7 @@ static int ipip6_tunnel_update_6rd(struct ip_tunnel *t,
|
||||
t->ip6rd.relay_prefix = relay_prefix;
|
||||
t->ip6rd.prefixlen = ip6rd->prefixlen;
|
||||
t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen;
|
||||
ip_tunnel_dst_reset_all(t);
|
||||
netdev_state_change(t->dev);
|
||||
return 0;
|
||||
}
|
||||
@@ -1271,6 +1274,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL);
|
||||
break;
|
||||
}
|
||||
ip_tunnel_dst_reset_all(t);
|
||||
netdev_state_change(dev);
|
||||
break;
|
||||
|
||||
@@ -1326,6 +1330,9 @@ static const struct net_device_ops ipip6_netdev_ops = {
|
||||
|
||||
static void ipip6_dev_free(struct net_device *dev)
|
||||
{
|
||||
struct ip_tunnel *tunnel = netdev_priv(dev);
|
||||
|
||||
free_percpu(tunnel->dst_cache);
|
||||
free_percpu(dev->tstats);
|
||||
free_netdev(dev);
|
||||
}
|
||||
@@ -1368,6 +1375,12 @@ static int ipip6_tunnel_init(struct net_device *dev)
|
||||
if (!dev->tstats)
|
||||
return -ENOMEM;
|
||||
|
||||
tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst);
|
||||
if (!tunnel->dst_cache) {
|
||||
free_percpu(dev->tstats);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1391,6 +1404,12 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev)
|
||||
if (!dev->tstats)
|
||||
return -ENOMEM;
|
||||
|
||||
tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst);
|
||||
if (!tunnel->dst_cache) {
|
||||
free_percpu(dev->tstats);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev_hold(dev);
|
||||
rcu_assign_pointer(sitn->tunnels_wc[0], tunnel);
|
||||
return 0;
|
||||
|
||||
@@ -113,7 +113,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
|
||||
fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
|
||||
fptr->nexthdr = nexthdr;
|
||||
fptr->reserved = 0;
|
||||
ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
|
||||
fptr->identification = skb_shinfo(skb)->ip6_frag_id;
|
||||
|
||||
/* Fragment the skb. ipv6 header and the remaining fields of the
|
||||
* fragment header are updated in ipv6_gso_segment()
|
||||
|
||||
@@ -1698,14 +1698,8 @@ void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
|
||||
void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue);
|
||||
void ieee80211_add_pending_skb(struct ieee80211_local *local,
|
||||
struct sk_buff *skb);
|
||||
void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs,
|
||||
void (*fn)(void *data), void *data);
|
||||
static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs)
|
||||
{
|
||||
ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL);
|
||||
}
|
||||
void ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs);
|
||||
void ieee80211_flush_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
|
||||
@@ -222,6 +222,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
||||
switch (vht_oper->chan_width) {
|
||||
case IEEE80211_VHT_CHANWIDTH_USE_HT:
|
||||
vht_chandef.width = chandef->width;
|
||||
vht_chandef.center_freq1 = chandef->center_freq1;
|
||||
break;
|
||||
case IEEE80211_VHT_CHANWIDTH_80MHZ:
|
||||
vht_chandef.width = NL80211_CHAN_WIDTH_80;
|
||||
@@ -271,6 +272,28 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
/*
|
||||
* When tracking the current AP, don't do any further checks if the
|
||||
* new chandef is identical to the one we're currently using for the
|
||||
* connection. This keeps us from playing ping-pong with regulatory,
|
||||
* without it the following can happen (for example):
|
||||
* - connect to an AP with 80 MHz, world regdom allows 80 MHz
|
||||
* - AP advertises regdom US
|
||||
* - CRDA loads regdom US with 80 MHz prohibited (old database)
|
||||
* - the code below detects an unsupported channel, downgrades, and
|
||||
* we disconnect from the AP in the caller
|
||||
* - disconnect causes CRDA to reload world regdomain and the game
|
||||
* starts anew.
|
||||
* (see https://bugzilla.kernel.org/show_bug.cgi?id=70881)
|
||||
*
|
||||
* It seems possible that there are still scenarios with CSA or real
|
||||
* bandwidth changes where a this could happen, but those cases are
|
||||
* less common and wouldn't completely prevent using the AP.
|
||||
*/
|
||||
if (tracking &&
|
||||
cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef))
|
||||
return ret;
|
||||
|
||||
/* don't print the message below for VHT mismatch if VHT is disabled */
|
||||
if (ret & IEEE80211_STA_DISABLE_VHT)
|
||||
vht_chandef = *chandef;
|
||||
@@ -3792,6 +3815,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
|
||||
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||
if (WARN_ON(!chanctx_conf)) {
|
||||
rcu_read_unlock();
|
||||
sta_info_free(local, new_sta);
|
||||
return -EINVAL;
|
||||
}
|
||||
rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
|
||||
|
||||
@@ -1092,6 +1092,13 @@ static void sta_ps_end(struct sta_info *sta)
|
||||
sta->sta.addr, sta->sta.aid);
|
||||
|
||||
if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
|
||||
/*
|
||||
* Clear the flag only if the other one is still set
|
||||
* so that the TX path won't start TX'ing new frames
|
||||
* directly ... In the case that the driver flag isn't
|
||||
* set ieee80211_sta_ps_deliver_wakeup() will clear it.
|
||||
*/
|
||||
clear_sta_flag(sta, WLAN_STA_PS_STA);
|
||||
ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n",
|
||||
sta->sta.addr, sta->sta.aid);
|
||||
return;
|
||||
|
||||
+42
-24
@@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static void cleanup_single_sta(struct sta_info *sta)
|
||||
static void __cleanup_single_sta(struct sta_info *sta)
|
||||
{
|
||||
int ac, i;
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
@@ -99,7 +99,8 @@ static void cleanup_single_sta(struct sta_info *sta)
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ps_data *ps;
|
||||
|
||||
if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
|
||||
if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
|
||||
test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
|
||||
if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
ps = &sdata->bss->ps;
|
||||
@@ -109,6 +110,7 @@ static void cleanup_single_sta(struct sta_info *sta)
|
||||
return;
|
||||
|
||||
clear_sta_flag(sta, WLAN_STA_PS_STA);
|
||||
clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
|
||||
|
||||
atomic_dec(&ps->num_sta_ps);
|
||||
sta_info_recalc_tim(sta);
|
||||
@@ -139,7 +141,14 @@ static void cleanup_single_sta(struct sta_info *sta)
|
||||
ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending);
|
||||
kfree(tid_tx);
|
||||
}
|
||||
}
|
||||
|
||||
static void cleanup_single_sta(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
__cleanup_single_sta(sta);
|
||||
sta_info_free(local, sta);
|
||||
}
|
||||
|
||||
@@ -330,6 +339,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
||||
rcu_read_unlock();
|
||||
|
||||
spin_lock_init(&sta->lock);
|
||||
spin_lock_init(&sta->ps_lock);
|
||||
INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
|
||||
INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
|
||||
mutex_init(&sta->ampdu_mlme.mtx);
|
||||
@@ -487,21 +497,26 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* notify driver */
|
||||
err = sta_info_insert_drv_state(local, sdata, sta);
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
||||
local->num_sta++;
|
||||
local->sta_generation++;
|
||||
smp_mb();
|
||||
|
||||
/* simplify things and don't accept BA sessions yet */
|
||||
set_sta_flag(sta, WLAN_STA_BLOCK_BA);
|
||||
|
||||
/* make the station visible */
|
||||
sta_info_hash_add(local, sta);
|
||||
|
||||
list_add_rcu(&sta->list, &local->sta_list);
|
||||
|
||||
/* notify driver */
|
||||
err = sta_info_insert_drv_state(local, sdata, sta);
|
||||
if (err)
|
||||
goto out_remove;
|
||||
|
||||
set_sta_flag(sta, WLAN_STA_INSERTED);
|
||||
/* accept BA sessions now */
|
||||
clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
|
||||
|
||||
ieee80211_recalc_min_chandef(sdata);
|
||||
ieee80211_sta_debugfs_add(sta);
|
||||
@@ -522,6 +537,12 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
|
||||
mesh_accept_plinks_update(sdata);
|
||||
|
||||
return 0;
|
||||
out_remove:
|
||||
sta_info_hash_del(local, sta);
|
||||
list_del_rcu(&sta->list);
|
||||
local->num_sta--;
|
||||
synchronize_net();
|
||||
__cleanup_single_sta(sta);
|
||||
out_err:
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
rcu_read_lock();
|
||||
@@ -1071,10 +1092,14 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_find_sta);
|
||||
|
||||
static void clear_sta_ps_flags(void *_sta)
|
||||
/* powersave support code */
|
||||
void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
|
||||
{
|
||||
struct sta_info *sta = _sta;
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sk_buff_head pending;
|
||||
int filtered = 0, buffered = 0, ac;
|
||||
unsigned long flags;
|
||||
struct ps_data *ps;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
@@ -1085,20 +1110,6 @@ static void clear_sta_ps_flags(void *_sta)
|
||||
else
|
||||
return;
|
||||
|
||||
clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
|
||||
if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA))
|
||||
atomic_dec(&ps->num_sta_ps);
|
||||
}
|
||||
|
||||
/* powersave support code */
|
||||
void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sk_buff_head pending;
|
||||
int filtered = 0, buffered = 0, ac;
|
||||
unsigned long flags;
|
||||
|
||||
clear_sta_flag(sta, WLAN_STA_SP);
|
||||
|
||||
BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1);
|
||||
@@ -1109,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
|
||||
|
||||
skb_queue_head_init(&pending);
|
||||
|
||||
/* sync with ieee80211_tx_h_unicast_ps_buf */
|
||||
spin_lock(&sta->ps_lock);
|
||||
/* Send all buffered frames to the station */
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
int count = skb_queue_len(&pending), tmp;
|
||||
@@ -1127,7 +1140,12 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
|
||||
buffered += tmp - count;
|
||||
}
|
||||
|
||||
ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta);
|
||||
ieee80211_add_pending_skbs(local, &pending);
|
||||
clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
|
||||
clear_sta_flag(sta, WLAN_STA_PS_STA);
|
||||
spin_unlock(&sta->ps_lock);
|
||||
|
||||
atomic_dec(&ps->num_sta_ps);
|
||||
|
||||
/* This station just woke up and isn't aware of our SMPS state */
|
||||
if (!ieee80211_smps_is_restrictive(sta->known_smps_mode,
|
||||
|
||||
@@ -268,6 +268,7 @@ struct ieee80211_tx_latency_stat {
|
||||
* @drv_unblock_wk: used for driver PS unblocking
|
||||
* @listen_interval: listen interval of this station, when we're acting as AP
|
||||
* @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
|
||||
* @ps_lock: used for powersave (when mac80211 is the AP) related locking
|
||||
* @ps_tx_buf: buffers (per AC) of frames to transmit to this station
|
||||
* when it leaves power saving state or polls
|
||||
* @tx_filtered: buffers (per AC) of frames we already tried to
|
||||
@@ -357,10 +358,8 @@ struct sta_info {
|
||||
/* use the accessors defined below */
|
||||
unsigned long _flags;
|
||||
|
||||
/*
|
||||
* STA powersave frame queues, no more than the internal
|
||||
* locking required.
|
||||
*/
|
||||
/* STA powersave lock and frame queues */
|
||||
spinlock_t ps_lock;
|
||||
struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS];
|
||||
struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS];
|
||||
unsigned long driver_buffered_tids;
|
||||
|
||||
@@ -477,6 +477,20 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
||||
sta->sta.addr, sta->sta.aid, ac);
|
||||
if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
|
||||
purge_old_ps_buffers(tx->local);
|
||||
|
||||
/* sync with ieee80211_sta_ps_deliver_wakeup */
|
||||
spin_lock(&sta->ps_lock);
|
||||
/*
|
||||
* STA woke up the meantime and all the frames on ps_tx_buf have
|
||||
* been queued to pending queue. No reordering can happen, go
|
||||
* ahead and Tx the packet.
|
||||
*/
|
||||
if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
|
||||
!test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
|
||||
spin_unlock(&sta->ps_lock);
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
|
||||
if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) {
|
||||
struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]);
|
||||
ps_dbg(tx->sdata,
|
||||
@@ -491,6 +505,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
|
||||
skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb);
|
||||
spin_unlock(&sta->ps_lock);
|
||||
|
||||
if (!timer_pending(&local->sta_cleanup))
|
||||
mod_timer(&local->sta_cleanup,
|
||||
|
||||
+22
-26
@@ -435,9 +435,8 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
|
||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||
}
|
||||
|
||||
void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs,
|
||||
void (*fn)(void *data), void *data)
|
||||
void ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs)
|
||||
{
|
||||
struct ieee80211_hw *hw = &local->hw;
|
||||
struct sk_buff *skb;
|
||||
@@ -461,9 +460,6 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
|
||||
__skb_queue_tail(&local->pending[queue], skb);
|
||||
}
|
||||
|
||||
if (fn)
|
||||
fn(data);
|
||||
|
||||
for (i = 0; i < hw->queues; i++)
|
||||
__ieee80211_wake_queue(hw, i,
|
||||
IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
|
||||
@@ -1766,6 +1762,26 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
|
||||
|
||||
/*
|
||||
* Reconfigure sched scan if it was interrupted by FW restart or
|
||||
* suspend.
|
||||
*/
|
||||
mutex_lock(&local->mtx);
|
||||
sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
|
||||
lockdep_is_held(&local->mtx));
|
||||
if (sched_scan_sdata && local->sched_scan_req)
|
||||
/*
|
||||
* Sched scan stopped, but we don't want to report it. Instead,
|
||||
* we're trying to reschedule.
|
||||
*/
|
||||
if (__ieee80211_request_sched_scan_start(sched_scan_sdata,
|
||||
local->sched_scan_req))
|
||||
sched_scan_stopped = true;
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
if (sched_scan_stopped)
|
||||
cfg80211_sched_scan_stopped(local->hw.wiphy);
|
||||
|
||||
/*
|
||||
* If this is for hw restart things are still running.
|
||||
* We may want to change that later, however.
|
||||
@@ -1794,26 +1810,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
WARN_ON(1);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Reconfigure sched scan if it was interrupted by FW restart or
|
||||
* suspend.
|
||||
*/
|
||||
mutex_lock(&local->mtx);
|
||||
sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
|
||||
lockdep_is_held(&local->mtx));
|
||||
if (sched_scan_sdata && local->sched_scan_req)
|
||||
/*
|
||||
* Sched scan stopped, but we don't want to report it. Instead,
|
||||
* we're trying to reschedule.
|
||||
*/
|
||||
if (__ieee80211_request_sched_scan_start(sched_scan_sdata,
|
||||
local->sched_scan_req))
|
||||
sched_scan_stopped = true;
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
if (sched_scan_stopped)
|
||||
cfg80211_sched_scan_stopped(local->hw.wiphy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -154,6 +154,11 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
|
||||
return IEEE80211_AC_BE;
|
||||
}
|
||||
|
||||
if (skb->protocol == sdata->control_port_protocol) {
|
||||
skb->priority = 7;
|
||||
return ieee80211_downgrade_queue(sdata, skb);
|
||||
}
|
||||
|
||||
/* use the data classifier to determine what 802.1d tag the
|
||||
* data frame has */
|
||||
rcu_read_lock();
|
||||
|
||||
@@ -1310,27 +1310,22 @@ ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[])
|
||||
}
|
||||
|
||||
static int
|
||||
ctnetlink_change_nat(struct nf_conn *ct, const struct nlattr * const cda[])
|
||||
ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[])
|
||||
{
|
||||
#ifdef CONFIG_NF_NAT_NEEDED
|
||||
int ret;
|
||||
|
||||
if (cda[CTA_NAT_DST]) {
|
||||
ret = ctnetlink_parse_nat_setup(ct,
|
||||
NF_NAT_MANIP_DST,
|
||||
cda[CTA_NAT_DST]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
if (cda[CTA_NAT_SRC]) {
|
||||
ret = ctnetlink_parse_nat_setup(ct,
|
||||
NF_NAT_MANIP_SRC,
|
||||
cda[CTA_NAT_SRC]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_DST,
|
||||
cda[CTA_NAT_DST]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_SRC,
|
||||
cda[CTA_NAT_SRC]);
|
||||
return ret;
|
||||
#else
|
||||
if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC])
|
||||
return 0;
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
@@ -1659,11 +1654,9 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
|
||||
goto err2;
|
||||
}
|
||||
|
||||
if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
|
||||
err = ctnetlink_change_nat(ct, cda);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
}
|
||||
err = ctnetlink_setup_nat(ct, cda);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
|
||||
nf_ct_acct_ext_add(ct, GFP_ATOMIC);
|
||||
nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
|
||||
|
||||
+35
-21
@@ -432,15 +432,15 @@ nf_nat_setup_info(struct nf_conn *ct,
|
||||
}
|
||||
EXPORT_SYMBOL(nf_nat_setup_info);
|
||||
|
||||
unsigned int
|
||||
nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
|
||||
static unsigned int
|
||||
__nf_nat_alloc_null_binding(struct nf_conn *ct, enum nf_nat_manip_type manip)
|
||||
{
|
||||
/* Force range to this IP; let proto decide mapping for
|
||||
* per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
|
||||
* Use reply in case it's already been mangled (eg local packet).
|
||||
*/
|
||||
union nf_inet_addr ip =
|
||||
(HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ?
|
||||
(manip == NF_NAT_MANIP_SRC ?
|
||||
ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3 :
|
||||
ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3);
|
||||
struct nf_nat_range range = {
|
||||
@@ -448,7 +448,13 @@ nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
|
||||
.min_addr = ip,
|
||||
.max_addr = ip,
|
||||
};
|
||||
return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
|
||||
return nf_nat_setup_info(ct, &range, manip);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
|
||||
{
|
||||
return __nf_nat_alloc_null_binding(ct, HOOK2MANIP(hooknum));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_nat_alloc_null_binding);
|
||||
|
||||
@@ -702,9 +708,9 @@ static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
|
||||
|
||||
static int
|
||||
nfnetlink_parse_nat(const struct nlattr *nat,
|
||||
const struct nf_conn *ct, struct nf_nat_range *range)
|
||||
const struct nf_conn *ct, struct nf_nat_range *range,
|
||||
const struct nf_nat_l3proto *l3proto)
|
||||
{
|
||||
const struct nf_nat_l3proto *l3proto;
|
||||
struct nlattr *tb[CTA_NAT_MAX+1];
|
||||
int err;
|
||||
|
||||
@@ -714,38 +720,46 @@ nfnetlink_parse_nat(const struct nlattr *nat,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
rcu_read_lock();
|
||||
l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct));
|
||||
if (l3proto == NULL) {
|
||||
err = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
err = l3proto->nlattr_to_range(tb, range);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
return err;
|
||||
|
||||
if (!tb[CTA_NAT_PROTO])
|
||||
goto out;
|
||||
return 0;
|
||||
|
||||
err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return err;
|
||||
return nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range);
|
||||
}
|
||||
|
||||
/* This function is called under rcu_read_lock() */
|
||||
static int
|
||||
nfnetlink_parse_nat_setup(struct nf_conn *ct,
|
||||
enum nf_nat_manip_type manip,
|
||||
const struct nlattr *attr)
|
||||
{
|
||||
struct nf_nat_range range;
|
||||
const struct nf_nat_l3proto *l3proto;
|
||||
int err;
|
||||
|
||||
err = nfnetlink_parse_nat(attr, ct, &range);
|
||||
/* Should not happen, restricted to creating new conntracks
|
||||
* via ctnetlink.
|
||||
*/
|
||||
if (WARN_ON_ONCE(nf_nat_initialized(ct, manip)))
|
||||
return -EEXIST;
|
||||
|
||||
/* Make sure that L3 NAT is there by when we call nf_nat_setup_info to
|
||||
* attach the null binding, otherwise this may oops.
|
||||
*/
|
||||
l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct));
|
||||
if (l3proto == NULL)
|
||||
return -EAGAIN;
|
||||
|
||||
/* No NAT information has been passed, allocate the null-binding */
|
||||
if (attr == NULL)
|
||||
return __nf_nat_alloc_null_binding(ct, manip);
|
||||
|
||||
err = nfnetlink_parse_nat(attr, ct, &range, l3proto);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (nf_nat_initialized(ct, manip))
|
||||
return -EEXIST;
|
||||
|
||||
return nf_nat_setup_info(ct, &range, manip);
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ static void nft_meta_get_eval(const struct nft_expr *expr,
|
||||
skb->sk->sk_socket->file->f_cred->fsgid);
|
||||
read_unlock_bh(&skb->sk->sk_callback_lock);
|
||||
break;
|
||||
#ifdef CONFIG_NET_CLS_ROUTE
|
||||
#ifdef CONFIG_IP_ROUTE_CLASSID
|
||||
case NFT_META_RTCLASSID: {
|
||||
const struct dst_entry *dst = skb_dst(skb);
|
||||
|
||||
@@ -199,7 +199,7 @@ static int nft_meta_init_validate_get(uint32_t key)
|
||||
case NFT_META_OIFTYPE:
|
||||
case NFT_META_SKUID:
|
||||
case NFT_META_SKGID:
|
||||
#ifdef CONFIG_NET_CLS_ROUTE
|
||||
#ifdef CONFIG_IP_ROUTE_CLASSID
|
||||
case NFT_META_RTCLASSID:
|
||||
#endif
|
||||
#ifdef CONFIG_NETWORK_SECMARK
|
||||
|
||||
@@ -135,7 +135,8 @@ nft_payload_select_ops(const struct nft_ctx *ctx,
|
||||
if (len == 0 || len > FIELD_SIZEOF(struct nft_data, data))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (len <= 4 && IS_ALIGNED(offset, len) && base != NFT_PAYLOAD_LL_HEADER)
|
||||
if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) &&
|
||||
base != NFT_PAYLOAD_LL_HEADER)
|
||||
return &nft_payload_fast_ops;
|
||||
else
|
||||
return &nft_payload_ops;
|
||||
|
||||
@@ -21,9 +21,9 @@ static void nft_reject_inet_eval(const struct nft_expr *expr,
|
||||
{
|
||||
switch (pkt->ops->pf) {
|
||||
case NFPROTO_IPV4:
|
||||
nft_reject_ipv4_eval(expr, data, pkt);
|
||||
return nft_reject_ipv4_eval(expr, data, pkt);
|
||||
case NFPROTO_IPV6:
|
||||
nft_reject_ipv6_eval(expr, data, pkt);
|
||||
return nft_reject_ipv6_eval(expr, data, pkt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1489,8 +1489,8 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
|
||||
if (addr->sa_family != AF_NETLINK)
|
||||
return -EINVAL;
|
||||
|
||||
/* Only superuser is allowed to send multicasts */
|
||||
if (nladdr->nl_groups && !netlink_capable(sock, NL_CFG_F_NONROOT_SEND))
|
||||
if ((nladdr->nl_groups || nladdr->nl_pid) &&
|
||||
!netlink_capable(sock, NL_CFG_F_NONROOT_SEND))
|
||||
return -EPERM;
|
||||
|
||||
if (!nlk->portid)
|
||||
|
||||
+1
-1
@@ -301,7 +301,7 @@ static int nci_open_device(struct nci_dev *ndev)
|
||||
rc = __nci_request(ndev, nci_reset_req, 0,
|
||||
msecs_to_jiffies(NCI_RESET_TIMEOUT));
|
||||
|
||||
if (ndev->ops->setup(ndev))
|
||||
if (ndev->ops->setup)
|
||||
ndev->ops->setup(ndev);
|
||||
|
||||
if (!rc) {
|
||||
|
||||
+12
-12
@@ -338,18 +338,6 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
|
||||
qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate,
|
||||
tb[TCA_TBF_PTAB]));
|
||||
|
||||
if (q->qdisc != &noop_qdisc) {
|
||||
err = fifo_set_limit(q->qdisc, qopt->limit);
|
||||
if (err)
|
||||
goto done;
|
||||
} else if (qopt->limit > 0) {
|
||||
child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit);
|
||||
if (IS_ERR(child)) {
|
||||
err = PTR_ERR(child);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U);
|
||||
mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U);
|
||||
|
||||
@@ -396,6 +384,18 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (q->qdisc != &noop_qdisc) {
|
||||
err = fifo_set_limit(q->qdisc, qopt->limit);
|
||||
if (err)
|
||||
goto done;
|
||||
} else if (qopt->limit > 0) {
|
||||
child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit);
|
||||
if (IS_ERR(child)) {
|
||||
err = PTR_ERR(child);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
sch_tree_lock(sch);
|
||||
if (child) {
|
||||
qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
|
||||
|
||||
+89
-60
@@ -1239,78 +1239,107 @@ void sctp_assoc_update(struct sctp_association *asoc,
|
||||
}
|
||||
|
||||
/* Update the retran path for sending a retransmitted packet.
|
||||
* Round-robin through the active transports, else round-robin
|
||||
* through the inactive transports as this is the next best thing
|
||||
* we can try.
|
||||
* See also RFC4960, 6.4. Multi-Homed SCTP Endpoints:
|
||||
*
|
||||
* When there is outbound data to send and the primary path
|
||||
* becomes inactive (e.g., due to failures), or where the
|
||||
* SCTP user explicitly requests to send data to an
|
||||
* inactive destination transport address, before reporting
|
||||
* an error to its ULP, the SCTP endpoint should try to send
|
||||
* the data to an alternate active destination transport
|
||||
* address if one exists.
|
||||
*
|
||||
* When retransmitting data that timed out, if the endpoint
|
||||
* is multihomed, it should consider each source-destination
|
||||
* address pair in its retransmission selection policy.
|
||||
* When retransmitting timed-out data, the endpoint should
|
||||
* attempt to pick the most divergent source-destination
|
||||
* pair from the original source-destination pair to which
|
||||
* the packet was transmitted.
|
||||
*
|
||||
* Note: Rules for picking the most divergent source-destination
|
||||
* pair are an implementation decision and are not specified
|
||||
* within this document.
|
||||
*
|
||||
* Our basic strategy is to round-robin transports in priorities
|
||||
* according to sctp_state_prio_map[] e.g., if no such
|
||||
* transport with state SCTP_ACTIVE exists, round-robin through
|
||||
* SCTP_UNKNOWN, etc. You get the picture.
|
||||
*/
|
||||
void sctp_assoc_update_retran_path(struct sctp_association *asoc)
|
||||
static const u8 sctp_trans_state_to_prio_map[] = {
|
||||
[SCTP_ACTIVE] = 3, /* best case */
|
||||
[SCTP_UNKNOWN] = 2,
|
||||
[SCTP_PF] = 1,
|
||||
[SCTP_INACTIVE] = 0, /* worst case */
|
||||
};
|
||||
|
||||
static u8 sctp_trans_score(const struct sctp_transport *trans)
|
||||
{
|
||||
struct sctp_transport *t, *next;
|
||||
struct list_head *head = &asoc->peer.transport_addr_list;
|
||||
struct list_head *pos;
|
||||
|
||||
if (asoc->peer.transport_count == 1)
|
||||
return;
|
||||
|
||||
/* Find the next transport in a round-robin fashion. */
|
||||
t = asoc->peer.retran_path;
|
||||
pos = &t->transports;
|
||||
next = NULL;
|
||||
|
||||
while (1) {
|
||||
/* Skip the head. */
|
||||
if (pos->next == head)
|
||||
pos = head->next;
|
||||
else
|
||||
pos = pos->next;
|
||||
|
||||
t = list_entry(pos, struct sctp_transport, transports);
|
||||
|
||||
/* We have exhausted the list, but didn't find any
|
||||
* other active transports. If so, use the next
|
||||
* transport.
|
||||
*/
|
||||
if (t == asoc->peer.retran_path) {
|
||||
t = next;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try to find an active transport. */
|
||||
|
||||
if ((t->state == SCTP_ACTIVE) ||
|
||||
(t->state == SCTP_UNKNOWN)) {
|
||||
break;
|
||||
} else {
|
||||
/* Keep track of the next transport in case
|
||||
* we don't find any active transport.
|
||||
*/
|
||||
if (t->state != SCTP_UNCONFIRMED && !next)
|
||||
next = t;
|
||||
}
|
||||
}
|
||||
|
||||
if (t)
|
||||
asoc->peer.retran_path = t;
|
||||
else
|
||||
t = asoc->peer.retran_path;
|
||||
|
||||
pr_debug("%s: association:%p addr:%pISpc\n", __func__, asoc,
|
||||
&t->ipaddr.sa);
|
||||
return sctp_trans_state_to_prio_map[trans->state];
|
||||
}
|
||||
|
||||
/* Choose the transport for sending retransmit packet. */
|
||||
struct sctp_transport *sctp_assoc_choose_alter_transport(
|
||||
struct sctp_association *asoc, struct sctp_transport *last_sent_to)
|
||||
static struct sctp_transport *sctp_trans_elect_best(struct sctp_transport *curr,
|
||||
struct sctp_transport *best)
|
||||
{
|
||||
if (best == NULL)
|
||||
return curr;
|
||||
|
||||
return sctp_trans_score(curr) > sctp_trans_score(best) ? curr : best;
|
||||
}
|
||||
|
||||
void sctp_assoc_update_retran_path(struct sctp_association *asoc)
|
||||
{
|
||||
struct sctp_transport *trans = asoc->peer.retran_path;
|
||||
struct sctp_transport *trans_next = NULL;
|
||||
|
||||
/* We're done as we only have the one and only path. */
|
||||
if (asoc->peer.transport_count == 1)
|
||||
return;
|
||||
/* If active_path and retran_path are the same and active,
|
||||
* then this is the only active path. Use it.
|
||||
*/
|
||||
if (asoc->peer.active_path == asoc->peer.retran_path &&
|
||||
asoc->peer.active_path->state == SCTP_ACTIVE)
|
||||
return;
|
||||
|
||||
/* Iterate from retran_path's successor back to retran_path. */
|
||||
for (trans = list_next_entry(trans, transports); 1;
|
||||
trans = list_next_entry(trans, transports)) {
|
||||
/* Manually skip the head element. */
|
||||
if (&trans->transports == &asoc->peer.transport_addr_list)
|
||||
continue;
|
||||
if (trans->state == SCTP_UNCONFIRMED)
|
||||
continue;
|
||||
trans_next = sctp_trans_elect_best(trans, trans_next);
|
||||
/* Active is good enough for immediate return. */
|
||||
if (trans_next->state == SCTP_ACTIVE)
|
||||
break;
|
||||
/* We've reached the end, time to update path. */
|
||||
if (trans == asoc->peer.retran_path)
|
||||
break;
|
||||
}
|
||||
|
||||
if (trans_next != NULL)
|
||||
asoc->peer.retran_path = trans_next;
|
||||
|
||||
pr_debug("%s: association:%p updated new path to addr:%pISpc\n",
|
||||
__func__, asoc, &asoc->peer.retran_path->ipaddr.sa);
|
||||
}
|
||||
|
||||
struct sctp_transport *
|
||||
sctp_assoc_choose_alter_transport(struct sctp_association *asoc,
|
||||
struct sctp_transport *last_sent_to)
|
||||
{
|
||||
/* If this is the first time packet is sent, use the active path,
|
||||
* else use the retran path. If the last packet was sent over the
|
||||
* retran path, update the retran path and use it.
|
||||
*/
|
||||
if (!last_sent_to)
|
||||
if (last_sent_to == NULL) {
|
||||
return asoc->peer.active_path;
|
||||
else {
|
||||
} else {
|
||||
if (last_sent_to == asoc->peer.retran_path)
|
||||
sctp_assoc_update_retran_path(asoc);
|
||||
|
||||
return asoc->peer.retran_path;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,11 +495,12 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands,
|
||||
}
|
||||
|
||||
/* If the transport error count is greater than the pf_retrans
|
||||
* threshold, and less than pathmaxrtx, then mark this transport
|
||||
* as Partially Failed, ee SCTP Quick Failover Draft, secon 5.1,
|
||||
* point 1
|
||||
* threshold, and less than pathmaxrtx, and if the current state
|
||||
* is not SCTP_UNCONFIRMED, then mark this transport as Partially
|
||||
* Failed, see SCTP Quick Failover Draft, section 5.1
|
||||
*/
|
||||
if ((transport->state != SCTP_PF) &&
|
||||
(transport->state != SCTP_UNCONFIRMED) &&
|
||||
(asoc->pf_retrans < transport->pathmaxrxt) &&
|
||||
(transport->error_count > asoc->pf_retrans)) {
|
||||
|
||||
|
||||
@@ -758,6 +758,13 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net,
|
||||
struct sctp_chunk auth;
|
||||
sctp_ierror_t ret;
|
||||
|
||||
/* Make sure that we and the peer are AUTH capable */
|
||||
if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) {
|
||||
kfree_skb(chunk->auth_chunk);
|
||||
sctp_association_free(new_asoc);
|
||||
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
|
||||
}
|
||||
|
||||
/* set-up our fake chunk so that we can process it */
|
||||
auth.skb = chunk->auth_chunk;
|
||||
auth.asoc = chunk->asoc;
|
||||
|
||||
@@ -108,6 +108,7 @@ struct gss_auth {
|
||||
static DEFINE_SPINLOCK(pipe_version_lock);
|
||||
static struct rpc_wait_queue pipe_version_rpc_waitqueue;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue);
|
||||
static void gss_put_auth(struct gss_auth *gss_auth);
|
||||
|
||||
static void gss_free_ctx(struct gss_cl_ctx *);
|
||||
static const struct rpc_pipe_ops gss_upcall_ops_v0;
|
||||
@@ -320,6 +321,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
|
||||
if (gss_msg->ctx != NULL)
|
||||
gss_put_ctx(gss_msg->ctx);
|
||||
rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue);
|
||||
gss_put_auth(gss_msg->auth);
|
||||
kfree(gss_msg);
|
||||
}
|
||||
|
||||
@@ -498,9 +500,12 @@ gss_alloc_msg(struct gss_auth *gss_auth,
|
||||
default:
|
||||
err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name);
|
||||
if (err)
|
||||
goto err_free_msg;
|
||||
goto err_put_pipe_version;
|
||||
};
|
||||
kref_get(&gss_auth->kref);
|
||||
return gss_msg;
|
||||
err_put_pipe_version:
|
||||
put_pipe_version(gss_auth->net);
|
||||
err_free_msg:
|
||||
kfree(gss_msg);
|
||||
err:
|
||||
@@ -991,6 +996,8 @@ gss_create_new(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
|
||||
gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
|
||||
if (gss_auth->service == 0)
|
||||
goto err_put_mech;
|
||||
if (!gssd_running(gss_auth->net))
|
||||
goto err_put_mech;
|
||||
auth = &gss_auth->rpc_auth;
|
||||
auth->au_cslack = GSS_CRED_SLACK >> 2;
|
||||
auth->au_rslack = GSS_VERF_SLACK >> 2;
|
||||
@@ -1061,6 +1068,12 @@ gss_free_callback(struct kref *kref)
|
||||
gss_free(gss_auth);
|
||||
}
|
||||
|
||||
static void
|
||||
gss_put_auth(struct gss_auth *gss_auth)
|
||||
{
|
||||
kref_put(&gss_auth->kref, gss_free_callback);
|
||||
}
|
||||
|
||||
static void
|
||||
gss_destroy(struct rpc_auth *auth)
|
||||
{
|
||||
@@ -1082,7 +1095,7 @@ gss_destroy(struct rpc_auth *auth)
|
||||
gss_auth->gss_pipe[1] = NULL;
|
||||
rpcauth_destroy_credcache(auth);
|
||||
|
||||
kref_put(&gss_auth->kref, gss_free_callback);
|
||||
gss_put_auth(gss_auth);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1253,7 +1266,7 @@ gss_destroy_nullcred(struct rpc_cred *cred)
|
||||
call_rcu(&cred->cr_rcu, gss_free_cred_callback);
|
||||
if (ctx)
|
||||
gss_put_ctx(ctx);
|
||||
kref_put(&gss_auth->kref, gss_free_callback);
|
||||
gss_put_auth(gss_auth);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -64,7 +64,6 @@ static void xprt_free_allocation(struct rpc_rqst *req)
|
||||
free_page((unsigned long)xbufp->head[0].iov_base);
|
||||
xbufp = &req->rq_snd_buf;
|
||||
free_page((unsigned long)xbufp->head[0].iov_base);
|
||||
list_del(&req->rq_bc_pa_list);
|
||||
kfree(req);
|
||||
}
|
||||
|
||||
@@ -168,8 +167,10 @@ out_free:
|
||||
/*
|
||||
* Memory allocation failed, free the temporary list
|
||||
*/
|
||||
list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list)
|
||||
list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) {
|
||||
list_del(&req->rq_bc_pa_list);
|
||||
xprt_free_allocation(req);
|
||||
}
|
||||
|
||||
dprintk("RPC: setup backchannel transport failed\n");
|
||||
return -ENOMEM;
|
||||
@@ -198,6 +199,7 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs)
|
||||
xprt_dec_alloc_count(xprt, max_reqs);
|
||||
list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) {
|
||||
dprintk("RPC: req=%p\n", req);
|
||||
list_del(&req->rq_bc_pa_list);
|
||||
xprt_free_allocation(req);
|
||||
if (--max_reqs == 0)
|
||||
break;
|
||||
|
||||
@@ -510,6 +510,7 @@ static int xs_nospace(struct rpc_task *task)
|
||||
struct rpc_rqst *req = task->tk_rqstp;
|
||||
struct rpc_xprt *xprt = req->rq_xprt;
|
||||
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
|
||||
struct sock *sk = transport->inet;
|
||||
int ret = -EAGAIN;
|
||||
|
||||
dprintk("RPC: %5u xmit incomplete (%u left of %u)\n",
|
||||
@@ -527,7 +528,7 @@ static int xs_nospace(struct rpc_task *task)
|
||||
* window size
|
||||
*/
|
||||
set_bit(SOCK_NOSPACE, &transport->sock->flags);
|
||||
transport->inet->sk_write_pending++;
|
||||
sk->sk_write_pending++;
|
||||
/* ...and wait for more buffer space */
|
||||
xprt_wait_for_buffer_space(task, xs_nospace_callback);
|
||||
}
|
||||
@@ -537,6 +538,9 @@ static int xs_nospace(struct rpc_task *task)
|
||||
}
|
||||
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
|
||||
/* Race breaker in case memory is freed before above code is called */
|
||||
sk->sk_write_space(sk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -586,8 +586,13 @@ static struct notifier_block notifier = {
|
||||
|
||||
int tipc_bearer_setup(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = register_netdevice_notifier(¬ifier);
|
||||
if (err)
|
||||
return err;
|
||||
dev_add_pack(&tipc_packet_type);
|
||||
return register_netdevice_notifier(¬ifier);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tipc_bearer_cleanup(void)
|
||||
|
||||
+1
-1
@@ -181,7 +181,7 @@ static struct sk_buff *cfg_set_own_addr(void)
|
||||
if (tipc_own_addr)
|
||||
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
|
||||
" (cannot change node address once assigned)");
|
||||
tipc_core_start_net(addr);
|
||||
tipc_net_start(addr);
|
||||
return tipc_cfg_reply_none();
|
||||
}
|
||||
|
||||
|
||||
+59
-50
@@ -76,38 +76,14 @@ struct sk_buff *tipc_buf_acquire(u32 size)
|
||||
return skb;
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_core_stop_net - shut down TIPC networking sub-systems
|
||||
*/
|
||||
static void tipc_core_stop_net(void)
|
||||
{
|
||||
tipc_net_stop();
|
||||
tipc_bearer_cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* start_net - start TIPC networking sub-systems
|
||||
*/
|
||||
int tipc_core_start_net(unsigned long addr)
|
||||
{
|
||||
int res;
|
||||
|
||||
tipc_net_start(addr);
|
||||
res = tipc_bearer_setup();
|
||||
if (res < 0)
|
||||
goto err;
|
||||
return res;
|
||||
|
||||
err:
|
||||
tipc_core_stop_net();
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode
|
||||
*/
|
||||
static void tipc_core_stop(void)
|
||||
{
|
||||
tipc_handler_stop();
|
||||
tipc_net_stop();
|
||||
tipc_bearer_cleanup();
|
||||
tipc_netlink_stop();
|
||||
tipc_cfg_stop();
|
||||
tipc_subscr_stop();
|
||||
@@ -122,30 +98,65 @@ static void tipc_core_stop(void)
|
||||
*/
|
||||
static int tipc_core_start(void)
|
||||
{
|
||||
int res;
|
||||
int err;
|
||||
|
||||
get_random_bytes(&tipc_random, sizeof(tipc_random));
|
||||
|
||||
res = tipc_handler_start();
|
||||
if (!res)
|
||||
res = tipc_ref_table_init(tipc_max_ports, tipc_random);
|
||||
if (!res)
|
||||
res = tipc_nametbl_init();
|
||||
if (!res)
|
||||
res = tipc_netlink_start();
|
||||
if (!res)
|
||||
res = tipc_socket_init();
|
||||
if (!res)
|
||||
res = tipc_register_sysctl();
|
||||
if (!res)
|
||||
res = tipc_subscr_start();
|
||||
if (!res)
|
||||
res = tipc_cfg_init();
|
||||
if (res) {
|
||||
tipc_handler_stop();
|
||||
tipc_core_stop();
|
||||
}
|
||||
return res;
|
||||
err = tipc_handler_start();
|
||||
if (err)
|
||||
goto out_handler;
|
||||
|
||||
err = tipc_ref_table_init(tipc_max_ports, tipc_random);
|
||||
if (err)
|
||||
goto out_reftbl;
|
||||
|
||||
err = tipc_nametbl_init();
|
||||
if (err)
|
||||
goto out_nametbl;
|
||||
|
||||
err = tipc_netlink_start();
|
||||
if (err)
|
||||
goto out_netlink;
|
||||
|
||||
err = tipc_socket_init();
|
||||
if (err)
|
||||
goto out_socket;
|
||||
|
||||
err = tipc_register_sysctl();
|
||||
if (err)
|
||||
goto out_sysctl;
|
||||
|
||||
err = tipc_subscr_start();
|
||||
if (err)
|
||||
goto out_subscr;
|
||||
|
||||
err = tipc_cfg_init();
|
||||
if (err)
|
||||
goto out_cfg;
|
||||
|
||||
err = tipc_bearer_setup();
|
||||
if (err)
|
||||
goto out_bearer;
|
||||
|
||||
return 0;
|
||||
out_bearer:
|
||||
tipc_cfg_stop();
|
||||
out_cfg:
|
||||
tipc_subscr_stop();
|
||||
out_subscr:
|
||||
tipc_unregister_sysctl();
|
||||
out_sysctl:
|
||||
tipc_socket_stop();
|
||||
out_socket:
|
||||
tipc_netlink_stop();
|
||||
out_netlink:
|
||||
tipc_nametbl_stop();
|
||||
out_nametbl:
|
||||
tipc_ref_table_stop();
|
||||
out_reftbl:
|
||||
tipc_handler_stop();
|
||||
out_handler:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __init tipc_init(void)
|
||||
@@ -174,8 +185,6 @@ static int __init tipc_init(void)
|
||||
|
||||
static void __exit tipc_exit(void)
|
||||
{
|
||||
tipc_handler_stop();
|
||||
tipc_core_stop_net();
|
||||
tipc_core_stop();
|
||||
pr_info("Deactivated\n");
|
||||
}
|
||||
|
||||
@@ -90,7 +90,6 @@ extern int tipc_random __read_mostly;
|
||||
/*
|
||||
* Routines available to privileged subsystems
|
||||
*/
|
||||
int tipc_core_start_net(unsigned long);
|
||||
int tipc_handler_start(void);
|
||||
void tipc_handler_stop(void);
|
||||
int tipc_netlink_start(void);
|
||||
|
||||
@@ -945,9 +945,6 @@ void tipc_nametbl_stop(void)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
if (!table.types)
|
||||
return;
|
||||
|
||||
/* Verify name table is empty, then release it */
|
||||
write_lock_bh(&tipc_nametbl_lock);
|
||||
for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {
|
||||
|
||||
@@ -83,8 +83,6 @@ static struct genl_ops tipc_genl_ops[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int tipc_genl_family_registered;
|
||||
|
||||
int tipc_netlink_start(void)
|
||||
{
|
||||
int res;
|
||||
@@ -94,16 +92,10 @@ int tipc_netlink_start(void)
|
||||
pr_err("Failed to register netlink interface\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
tipc_genl_family_registered = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tipc_netlink_stop(void)
|
||||
{
|
||||
if (!tipc_genl_family_registered)
|
||||
return;
|
||||
|
||||
genl_unregister_family(&tipc_genl_family);
|
||||
tipc_genl_family_registered = 0;
|
||||
}
|
||||
|
||||
@@ -126,9 +126,6 @@ int tipc_ref_table_init(u32 requested_size, u32 start)
|
||||
*/
|
||||
void tipc_ref_table_stop(void)
|
||||
{
|
||||
if (!tipc_ref_table.entries)
|
||||
return;
|
||||
|
||||
vfree(tipc_ref_table.entries);
|
||||
tipc_ref_table.entries = NULL;
|
||||
}
|
||||
|
||||
@@ -573,7 +573,6 @@ int tipc_server_start(struct tipc_server *s)
|
||||
kmem_cache_destroy(s->rcvbuf_cache);
|
||||
return ret;
|
||||
}
|
||||
s->enabled = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -583,10 +582,6 @@ void tipc_server_stop(struct tipc_server *s)
|
||||
int total = 0;
|
||||
int id;
|
||||
|
||||
if (!s->enabled)
|
||||
return;
|
||||
|
||||
s->enabled = 0;
|
||||
spin_lock_bh(&s->idr_lock);
|
||||
for (id = 0; total < s->idr_in_use; id++) {
|
||||
con = idr_find(&s->conn_idr, id);
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
* @name: server name
|
||||
* @imp: message importance
|
||||
* @type: socket type
|
||||
* @enabled: identify whether server is launched or not
|
||||
*/
|
||||
struct tipc_server {
|
||||
struct idr conn_idr;
|
||||
@@ -74,7 +73,6 @@ struct tipc_server {
|
||||
const char name[TIPC_SERVER_NAME_LEN];
|
||||
int imp;
|
||||
int type;
|
||||
int enabled;
|
||||
};
|
||||
|
||||
int tipc_conn_sendmsg(struct tipc_server *s, int conid,
|
||||
|
||||
@@ -70,8 +70,6 @@ static const struct proto_ops msg_ops;
|
||||
static struct proto tipc_proto;
|
||||
static struct proto tipc_proto_kern;
|
||||
|
||||
static int sockets_enabled;
|
||||
|
||||
/*
|
||||
* Revised TIPC socket locking policy:
|
||||
*
|
||||
@@ -2029,8 +2027,6 @@ int tipc_socket_init(void)
|
||||
proto_unregister(&tipc_proto);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sockets_enabled = 1;
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
@@ -2040,10 +2036,6 @@ int tipc_socket_init(void)
|
||||
*/
|
||||
void tipc_socket_stop(void)
|
||||
{
|
||||
if (!sockets_enabled)
|
||||
return;
|
||||
|
||||
sockets_enabled = 0;
|
||||
sock_unregister(tipc_family_ops.family);
|
||||
proto_unregister(&tipc_proto);
|
||||
}
|
||||
|
||||
+10
-2
@@ -1788,7 +1788,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
||||
return;
|
||||
case NL80211_REGDOM_SET_BY_USER:
|
||||
treatment = reg_process_hint_user(reg_request);
|
||||
if (treatment == REG_REQ_OK ||
|
||||
if (treatment == REG_REQ_IGNORE ||
|
||||
treatment == REG_REQ_ALREADY_SET)
|
||||
return;
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
@@ -2481,6 +2481,7 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd,
|
||||
int set_regdom(const struct ieee80211_regdomain *rd)
|
||||
{
|
||||
struct regulatory_request *lr;
|
||||
bool user_reset = false;
|
||||
int r;
|
||||
|
||||
if (!reg_is_valid_request(rd->alpha2)) {
|
||||
@@ -2497,6 +2498,7 @@ int set_regdom(const struct ieee80211_regdomain *rd)
|
||||
break;
|
||||
case NL80211_REGDOM_SET_BY_USER:
|
||||
r = reg_set_rd_user(rd, lr);
|
||||
user_reset = true;
|
||||
break;
|
||||
case NL80211_REGDOM_SET_BY_DRIVER:
|
||||
r = reg_set_rd_driver(rd, lr);
|
||||
@@ -2510,8 +2512,14 @@ int set_regdom(const struct ieee80211_regdomain *rd)
|
||||
}
|
||||
|
||||
if (r) {
|
||||
if (r == -EALREADY)
|
||||
switch (r) {
|
||||
case -EALREADY:
|
||||
reg_set_request_processed();
|
||||
break;
|
||||
default:
|
||||
/* Back to world regulatory in case of errors */
|
||||
restore_regulatory_settings(user_reset);
|
||||
}
|
||||
|
||||
kfree(rd);
|
||||
return r;
|
||||
|
||||
@@ -1156,7 +1156,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
|
||||
if (hlist_unhashed(&pol->bydst))
|
||||
return NULL;
|
||||
|
||||
hlist_del(&pol->bydst);
|
||||
hlist_del_init(&pol->bydst);
|
||||
hlist_del(&pol->byidx);
|
||||
list_del(&pol->walk.all);
|
||||
net->xfrm.policy_count[dir]--;
|
||||
|
||||
+17
-6
@@ -1171,6 +1171,11 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
|
||||
}
|
||||
x->props.aalgo = orig->props.aalgo;
|
||||
|
||||
if (orig->aead) {
|
||||
x->aead = xfrm_algo_aead_clone(orig->aead);
|
||||
if (!x->aead)
|
||||
goto error;
|
||||
}
|
||||
if (orig->ealg) {
|
||||
x->ealg = xfrm_algo_clone(orig->ealg);
|
||||
if (!x->ealg)
|
||||
@@ -1211,6 +1216,9 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
|
||||
x->props.flags = orig->props.flags;
|
||||
x->props.extra_flags = orig->props.extra_flags;
|
||||
|
||||
x->tfcpad = orig->tfcpad;
|
||||
x->replay_maxdiff = orig->replay_maxdiff;
|
||||
x->replay_maxage = orig->replay_maxage;
|
||||
x->curlft.add_time = orig->curlft.add_time;
|
||||
x->km.state = orig->km.state;
|
||||
x->km.seq = orig->km.seq;
|
||||
@@ -1223,11 +1231,12 @@ out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* net->xfrm.xfrm_state_lock is held */
|
||||
struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net)
|
||||
{
|
||||
unsigned int h;
|
||||
struct xfrm_state *x;
|
||||
struct xfrm_state *x = NULL;
|
||||
|
||||
spin_lock_bh(&net->xfrm.xfrm_state_lock);
|
||||
|
||||
if (m->reqid) {
|
||||
h = xfrm_dst_hash(net, &m->old_daddr, &m->old_saddr,
|
||||
@@ -1244,7 +1253,7 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
|
||||
m->old_family))
|
||||
continue;
|
||||
xfrm_state_hold(x);
|
||||
return x;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
h = xfrm_src_hash(net, &m->old_daddr, &m->old_saddr,
|
||||
@@ -1259,11 +1268,13 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
|
||||
m->old_family))
|
||||
continue;
|
||||
xfrm_state_hold(x);
|
||||
return x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
|
||||
|
||||
return x;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_migrate_state_find);
|
||||
|
||||
@@ -1458,7 +1469,7 @@ xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
|
||||
{
|
||||
int err = 0;
|
||||
struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
|
||||
struct net *net = xs_net(*dst);
|
||||
struct net *net = xs_net(*src);
|
||||
|
||||
if (!afinfo)
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
@@ -32,11 +32,6 @@
|
||||
#include <linux/in6.h>
|
||||
#endif
|
||||
|
||||
static inline int aead_len(struct xfrm_algo_aead *alg)
|
||||
{
|
||||
return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
|
||||
}
|
||||
|
||||
static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type)
|
||||
{
|
||||
struct nlattr *rt = attrs[type];
|
||||
|
||||
Reference in New Issue
Block a user