#include <net/transp_v6.h>
#include <net/addrconf.h>
#include <net/ip6_route.h>
+#include <net/ip6_checksum.h>
#include <net/inet_ecn.h>
#include <net/protocol.h>
#include <net/xfrm.h>
static __inline__ int tcp_v6_iif(struct sk_buff *skb)
{
- struct inet6_skb_parm *opt = (struct inet6_skb_parm *) skb->cb;
- return opt->iif;
+ return IP6CB(skb)->iif;
}
static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
np->rxopt.bits.srcrt == 2 &&
req->af.v6_req.pktopts) {
struct sk_buff *pktopts = req->af.v6_req.pktopts;
- struct inet6_skb_parm *rxopt = (struct inet6_skb_parm *)pktopts->cb;
+ struct inet6_skb_parm *rxopt = IP6CB(pktopts);
if (rxopt->srcrt)
opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(pktopts->nh.raw + rxopt->srcrt));
}
static int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
{
struct ipv6_pinfo *np = inet6_sk(sk);
- struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
+ struct inet6_skb_parm *opt = IP6CB(skb);
if (np->rxopt.all) {
if ((opt->hop && np->rxopt.bits.hopopts) ||
lopt->syn_table[h] = req;
write_unlock(&tp->syn_wait_lock);
+#ifdef CONFIG_ACCEPT_QUEUES
+ tcp_synq_added(sk, req);
+#else
tcp_synq_added(sk);
+#endif
}
struct tcp_opt tmptp, *tp = tcp_sk(sk);
struct open_request *req = NULL;
__u32 isn = TCP_SKB_CB(skb)->when;
+#ifdef CONFIG_ACCEPT_QUEUES
+ int class = 0;
+#endif
if (skb->protocol == htons(ETH_P_IP))
return tcp_v4_conn_request(sk, skb);
if (!ipv6_unicast_destination(skb))
goto drop;
+
/*
* There are no SYN attacks on IPv6, yet...
*/
goto drop;
}
- if (tcp_acceptq_is_full(sk) && tcp_synq_young(sk) > 1)
+#ifdef CONFIG_ACCEPT_QUEUES
+ class = (skb->nfmark <= 0) ? 0 :
+ ((skb->nfmark >= NUM_ACCEPT_QUEUES) ? 0: skb->nfmark);
+ /*
+ * Accept only if the class has shares set or if the default class
+ * i.e. class 0 has shares
+ */
+ if (!(tcp_sk(sk)->acceptq[class].aq_ratio)) {
+ if (tcp_sk(sk)->acceptq[0].aq_ratio)
+ class = 0;
+ else
+ goto drop;
+ }
+
+ if (sk_acceptq_is_full(sk, class) && tcp_synq_young(sk, class) > 1)
+#else
+ if (sk_acceptq_is_full(sk) && tcp_synq_young(sk) > 1)
+#endif
goto drop;
+
req = tcp_openreq_alloc();
if (req == NULL)
goto drop;
tmptp.tstamp_ok = tmptp.saw_tstamp;
tcp_openreq_init(req, &tmptp, skb);
-
+#ifdef CONFIG_ACCEPT_QUEUES
+ req->acceptq_class = class;
+ req->acceptq_time_stamp = jiffies;
+#endif
req->class = &or_ipv6;
ipv6_addr_copy(&req->af.v6_req.rmt_addr, &skb->nh.ipv6h->saddr);
ipv6_addr_copy(&req->af.v6_req.loc_addr, &skb->nh.ipv6h->daddr);
opt = np->opt;
- if (tcp_acceptq_is_full(sk))
+#ifdef CONFIG_ACCEPT_QUEUES
+ if (sk_acceptq_is_full(sk, req->acceptq_class))
+#else
+ if (sk_acceptq_is_full(sk))
+#endif
goto out_overflow;
if (np->rxopt.bits.srcrt == 2 &&
opt == NULL && req->af.v6_req.pktopts) {
- struct inet6_skb_parm *rxopt = (struct inet6_skb_parm *)req->af.v6_req.pktopts->cb;
+ struct inet6_skb_parm *rxopt = IP6CB(req->af.v6_req.pktopts);
if (rxopt->srcrt)
opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(req->af.v6_req.pktopts->nh.raw+rxopt->srcrt));
}
tp->af_specific = &ipv6_specific;
- sk->sk_write_space = tcp_write_space;
+ sk->sk_write_space = sk_stream_write_space;
sk->sk_use_write_queue = 1;
sk->sk_sndbuf = sysctl_tcp_wmem[1];
static int tcp_v6_destroy_sock(struct sock *sk)
{
- struct tcp_opt *tp = tcp_sk(sk);
- struct inet_opt *inet = inet_sk(sk);
-
- tcp_clear_xmit_timers(sk);
-
- /* Cleanup up the write buffer. */
- tcp_writequeue_purge(sk);
-
- /* Cleans up our, hopefully empty, out_of_order_queue. */
- __skb_queue_purge(&tp->out_of_order_queue);
-
- /* Clean prequeue, it must be empty really */
- __skb_queue_purge(&tp->ucopy.prequeue);
-
- /* Clean up a referenced TCP bind bucket. */
- if (tcp_sk(sk)->bind_hash)
- tcp_put_port(sk);
-
- /* If sendmsg cached page exists, toss it. */
- if (inet->sndmsg_page != NULL)
- __free_page(inet->sndmsg_page);
-
- atomic_dec(&tcp_sockets_allocated);
+ extern int tcp_v4_destroy_sock(struct sock *sk);
+ tcp_v4_destroy_sock(sk);
return inet6_destroy_sock(sk);
}
#endif
struct proto tcpv6_prot = {
- .name = "TCPv6",
- .close = tcp_close,
- .connect = tcp_v6_connect,
- .disconnect = tcp_disconnect,
- .accept = tcp_accept,
- .ioctl = tcp_ioctl,
- .init = tcp_v6_init_sock,
- .destroy = tcp_v6_destroy_sock,
- .shutdown = tcp_shutdown,
- .setsockopt = tcp_setsockopt,
- .getsockopt = tcp_getsockopt,
- .sendmsg = tcp_sendmsg,
- .recvmsg = tcp_recvmsg,
- .backlog_rcv = tcp_v6_do_rcv,
- .hash = tcp_v6_hash,
- .unhash = tcp_unhash,
- .get_port = tcp_v6_get_port,
+ .name = "TCPv6",
+ .close = tcp_close,
+ .connect = tcp_v6_connect,
+ .disconnect = tcp_disconnect,
+ .accept = tcp_accept,
+ .ioctl = tcp_ioctl,
+ .init = tcp_v6_init_sock,
+ .destroy = tcp_v6_destroy_sock,
+ .shutdown = tcp_shutdown,
+ .setsockopt = tcp_setsockopt,
+ .getsockopt = tcp_getsockopt,
+ .sendmsg = tcp_sendmsg,
+ .recvmsg = tcp_recvmsg,
+ .backlog_rcv = tcp_v6_do_rcv,
+ .hash = tcp_v6_hash,
+ .unhash = tcp_unhash,
+ .get_port = tcp_v6_get_port,
+ .enter_memory_pressure = tcp_enter_memory_pressure,
+ .sockets_allocated = &tcp_sockets_allocated,
+ .memory_allocated = &tcp_memory_allocated,
+ .memory_pressure = &tcp_memory_pressure,
+ .sysctl_mem = sysctl_tcp_mem,
+ .sysctl_wmem = sysctl_tcp_wmem,
+ .sysctl_rmem = sysctl_tcp_rmem,
+ .max_header = MAX_TCP_HEADER,
};
static struct inet6_protocol tcpv6_protocol = {