This reverts "Merge branch 'dccp' of git://eden-feed.erg.abdn.ac.uk/dccp_exp"
as it accentally contained the wrong set of patches. These will be
submitted separately.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
···45454646Socket options4747==============4848-DCCP_SOCKOPT_QPOLICY_ID sets the dequeuing policy for outgoing packets. It takes4949-a policy ID as argument and can only be set before the connection (i.e. changes5050-during an established connection are not supported). Currently, two policies are5151-defined: the "simple" policy (DCCPQ_POLICY_SIMPLE), which does nothing special,5252-and a priority-based variant (DCCPQ_POLICY_PRIO). The latter allows to pass an5353-u32 priority value as ancillary data to sendmsg(), where higher numbers indicate5454-a higher packet priority (similar to SO_PRIORITY). This ancillary data needs to5555-be formatted using a cmsg(3) message header filled in as follows:5656- cmsg->cmsg_level = SOL_DCCP;5757- cmsg->cmsg_type = DCCP_SCM_PRIORITY;5858- cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t)); /* or CMSG_LEN(4) */5959-6060-DCCP_SOCKOPT_QPOLICY_TXQLEN sets the maximum length of the output queue. A zero6161-value is always interpreted as unbounded queue length. If different from zero,6262-the interpretation of this parameter depends on the current dequeuing policy6363-(see above): the "simple" policy will enforce a fixed queue size by returning6464-EAGAIN, whereas the "prio" policy enforces a fixed queue length by dropping the6565-lowest-priority packet first. The default value for this parameter is6666-initialised from /proc/sys/net/dccp/default/tx_qlen.67486849DCCP_SOCKOPT_SERVICE sets the service. The specification mandates use of6950service codes (RFC 4340, sec. 8.1.2); if this socket option is not set,···56755776DCCP_SOCKOPT_GET_CUR_MPS is read-only and retrieves the current maximum packet5877size (application payload size) in bytes, see RFC 4340, section 14.5959-6060-DCCP_SOCKOPT_AVAILABLE_CCIDS is also read-only and returns the list of CCIDs6161-supported by the endpoint (see include/linux/dccp.h for symbolic constants).6262-The caller needs to provide a sufficiently large (> 2) array of type uint8_t.6363-6464-DCCP_SOCKOPT_CCID is write-only and sets both the TX and RX CCIDs at the same6565-time, combining the operation of the next two socket options. This option is6666-preferrable over the latter two, since often applications will use the same6767-type of CCID for both directions; and mixed use of CCIDs is not currently well6868-understood. This socket option takes as argument at least one uint8_t value, or6969-an array of uint8_t values, which must match available CCIDS (see above). CCIDs7070-must be registered on the socket before calling connect() or listen().7171-7272-DCCP_SOCKOPT_TX_CCID is read/write. It returns the current CCID (if set) or sets7373-the preference list for the TX CCID, using the same format as DCCP_SOCKOPT_CCID.7474-Please note that the getsockopt argument type here is `int', not uint8_t.7575-7676-DCCP_SOCKOPT_RX_CCID is analogous to DCCP_SOCKOPT_TX_CCID, but for the RX CCID.77787879DCCP_SOCKOPT_SERVER_TIMEWAIT enables the server (listening socket) to hold7980timewait state when closing the connection (RFC 4340, 8.3). The usual case is···115152 importance for retransmitted acknowledgments and feature negotiation,116153 data packets are never retransmitted. Analogue of tcp_retries2.117154155155+send_ndp = 1156156+ Whether or not to send NDP count options (sec. 7.7.2).157157+158158+send_ackvec = 1159159+ Whether or not to send Ack Vector options (sec. 11.5).160160+161161+ack_ratio = 2162162+ The default Ack Ratio (sec. 11.3) to use.163163+118164tx_ccid = 2119119- Default CCID for the sender-receiver half-connection. Depending on the120120- choice of CCID, the Send Ack Vector feature is enabled automatically.165165+ Default CCID for the sender-receiver half-connection.121166122167rx_ccid = 2123123- Default CCID for the receiver-sender half-connection; see tx_ccid.168168+ Default CCID for the receiver-sender half-connection.124169125170seq_window = 100126126- The initial sequence window (sec. 7.5.2) of the sender. This influences127127- the local ackno validity and the remote seqno validity windows (7.5.1).171171+ The initial sequence window (sec. 7.5.2).128172129173tx_qlen = 5130174 The size of the transmit buffer in packets. A value of 0 corresponds
+71-51
include/linux/dccp.h
···165165 DCCPO_TIMESTAMP_ECHO = 42,166166 DCCPO_ELAPSED_TIME = 43,167167 DCCPO_MAX = 45,168168- DCCPO_MIN_RX_CCID_SPECIFIC = 128, /* from sender to receiver */169169- DCCPO_MAX_RX_CCID_SPECIFIC = 191,170170- DCCPO_MIN_TX_CCID_SPECIFIC = 192, /* from receiver to sender */171171- DCCPO_MAX_TX_CCID_SPECIFIC = 255,168168+ DCCPO_MIN_CCID_SPECIFIC = 128,169169+ DCCPO_MAX_CCID_SPECIFIC = 255,172170};173173-/* maximum size of a single TLV-encoded DCCP option (sans type/len bytes) */174174-#define DCCP_SINGLE_OPT_MAXLEN 253175171176172/* DCCP CCIDS */177173enum {···176180};177181178182/* DCCP features (RFC 4340 section 6.4) */179179-enum dccp_feature_numbers {183183+enum {180184 DCCPF_RESERVED = 0,181185 DCCPF_CCID = 1,182182- DCCPF_SHORT_SEQNOS = 2,186186+ DCCPF_SHORT_SEQNOS = 2, /* XXX: not yet implemented */183187 DCCPF_SEQUENCE_WINDOW = 3,184184- DCCPF_ECN_INCAPABLE = 4,188188+ DCCPF_ECN_INCAPABLE = 4, /* XXX: not yet implemented */185189 DCCPF_ACK_RATIO = 5,186190 DCCPF_SEND_ACK_VECTOR = 6,187191 DCCPF_SEND_NDP_COUNT = 7,188192 DCCPF_MIN_CSUM_COVER = 8,189189- DCCPF_DATA_CHECKSUM = 9,193193+ DCCPF_DATA_CHECKSUM = 9, /* XXX: not yet implemented */190194 /* 10-127 reserved */191195 DCCPF_MIN_CCID_SPECIFIC = 128,192192- DCCPF_SEND_LEV_RATE = 192, /* RFC 4342, sec. 8.4 */193196 DCCPF_MAX_CCID_SPECIFIC = 255,194197};195198196196-/* DCCP socket control message types for cmsg */197197-enum dccp_cmsg_type {198198- DCCP_SCM_PRIORITY = 1,199199- DCCP_SCM_QPOLICY_MAX = 0xFFFF,200200- /* ^-- Up to here reserved exclusively for qpolicy parameters */201201- DCCP_SCM_MAX202202-};203203-204204-/* DCCP priorities for outgoing/queued packets */205205-enum dccp_packet_dequeueing_policy {206206- DCCPQ_POLICY_SIMPLE,207207- DCCPQ_POLICY_PRIO,208208- DCCPQ_POLICY_MAX199199+/* this structure is argument to DCCP_SOCKOPT_CHANGE_X */200200+struct dccp_so_feat {201201+ __u8 dccpsf_feat;202202+ __u8 __user *dccpsf_val;203203+ __u8 dccpsf_len;209204};210205211206/* DCCP socket options */···208221#define DCCP_SOCKOPT_SERVER_TIMEWAIT 6209222#define DCCP_SOCKOPT_SEND_CSCOV 10210223#define DCCP_SOCKOPT_RECV_CSCOV 11211211-#define DCCP_SOCKOPT_AVAILABLE_CCIDS 12212212-#define DCCP_SOCKOPT_CCID 13213213-#define DCCP_SOCKOPT_TX_CCID 14214214-#define DCCP_SOCKOPT_RX_CCID 15215215-#define DCCP_SOCKOPT_QPOLICY_ID 16216216-#define DCCP_SOCKOPT_QPOLICY_TXQLEN 17217224#define DCCP_SOCKOPT_CCID_RX_INFO 128218225#define DCCP_SOCKOPT_CCID_TX_INFO 192219226···355374 return __dccp_hdr_len(dccp_hdr(skb));356375}357376377377+378378+/* initial values for each feature */379379+#define DCCPF_INITIAL_SEQUENCE_WINDOW 100380380+#define DCCPF_INITIAL_ACK_RATIO 2381381+#define DCCPF_INITIAL_CCID DCCPC_CCID2382382+#define DCCPF_INITIAL_SEND_ACK_VECTOR 1383383+/* FIXME: for now we're default to 1 but it should really be 0 */384384+#define DCCPF_INITIAL_SEND_NDP_COUNT 1385385+386386+/**387387+ * struct dccp_minisock - Minimal DCCP connection representation388388+ *389389+ * Will be used to pass the state from dccp_request_sock to dccp_sock.390390+ *391391+ * @dccpms_sequence_window - Sequence Window Feature (section 7.5.2)392392+ * @dccpms_ccid - Congestion Control Id (CCID) (section 10)393393+ * @dccpms_send_ack_vector - Send Ack Vector Feature (section 11.5)394394+ * @dccpms_send_ndp_count - Send NDP Count Feature (7.7.2)395395+ * @dccpms_ack_ratio - Ack Ratio Feature (section 11.3)396396+ * @dccpms_pending - List of features being negotiated397397+ * @dccpms_conf -398398+ */399399+struct dccp_minisock {400400+ __u64 dccpms_sequence_window;401401+ __u8 dccpms_rx_ccid;402402+ __u8 dccpms_tx_ccid;403403+ __u8 dccpms_send_ack_vector;404404+ __u8 dccpms_send_ndp_count;405405+ __u8 dccpms_ack_ratio;406406+ struct list_head dccpms_pending;407407+ struct list_head dccpms_conf;408408+};409409+410410+struct dccp_opt_conf {411411+ __u8 *dccpoc_val;412412+ __u8 dccpoc_len;413413+};414414+415415+struct dccp_opt_pend {416416+ struct list_head dccpop_node;417417+ __u8 dccpop_type;418418+ __u8 dccpop_feat;419419+ __u8 *dccpop_val;420420+ __u8 dccpop_len;421421+ int dccpop_conf;422422+ struct dccp_opt_conf *dccpop_sc;423423+};424424+425425+extern void dccp_minisock_init(struct dccp_minisock *dmsk);426426+358427/**359428 * struct dccp_request_sock - represent DCCP-specific connection request360429 * @dreq_inet_rsk: structure inherited from361430 * @dreq_iss: initial sequence number sent on the Response (RFC 4340, 7.1)362431 * @dreq_isr: initial sequence number received on the Request363432 * @dreq_service: service code present on the Request (there is just one)364364- * @dreq_featneg: feature negotiation options for this connection365433 * The following two fields are analogous to the ones in dccp_sock:366434 * @dreq_timestamp_echo: last received timestamp to echo (13.1)367435 * @dreq_timestamp_echo: the time of receiving the last @dreq_timestamp_echo···420390 __u64 dreq_iss;421391 __u64 dreq_isr;422392 __be32 dreq_service;423423- struct list_head dreq_featneg;424393 __u32 dreq_timestamp_echo;425394 __u32 dreq_timestamp_time;426395};···491462 * @dccps_timestamp_time - time of receiving latest @dccps_timestamp_echo492463 * @dccps_l_ack_ratio - feature-local Ack Ratio493464 * @dccps_r_ack_ratio - feature-remote Ack Ratio494494- * @dccps_l_seq_win - local Sequence Window (influences ack number validity)495495- * @dccps_r_seq_win - remote Sequence Window (influences seq number validity)496465 * @dccps_pcslen - sender partial checksum coverage (via sockopt)497466 * @dccps_pcrlen - receiver partial checksum coverage (via sockopt)498498- * @dccps_send_ndp_count - local Send NDP Count feature (7.7.2)499467 * @dccps_ndp_count - number of Non Data Packets since last data packet500468 * @dccps_mss_cache - current value of MSS (path MTU minus header sizes)501469 * @dccps_rate_last - timestamp for rate-limiting DCCP-Sync (RFC 4340, 7.5.4)502502- * @dccps_featneg - tracks feature-negotiation state (mostly during handshake)470470+ * @dccps_minisock - associated minisock (accessed via dccp_msk)503471 * @dccps_hc_rx_ackvec - rx half connection ack vector504472 * @dccps_hc_rx_ccid - CCID used for the receiver (or receiving half-connection)505473 * @dccps_hc_tx_ccid - CCID used for the sender (or sending half-connection)506474 * @dccps_options_received - parsed set of retrieved options507507- * @dccps_qpolicy - TX dequeueing policy, one of %dccp_packet_dequeueing_policy508508- * @dccps_tx_qlen - maximum length of the TX queue509475 * @dccps_role - role of this sock, one of %dccp_role510476 * @dccps_hc_rx_insert_options - receiver wants to add options when acking511477 * @dccps_hc_tx_insert_options - sender wants to add options when sending512478 * @dccps_server_timewait - server holds timewait state on close (RFC 4340, 8.3)513513- * @dccps_sync_scheduled - flag which signals "send out-of-band message soon"514514- * @dccps_xmitlet - tasklet scheduled by the TX CCID to dequeue data packets515515- * @dccps_xmit_timer - used by the TX CCID to delay sending (rate-based pacing)479479+ * @dccps_xmit_timer - timer for when CCID is not ready to send516480 * @dccps_syn_rtt - RTT sample from Request/Response exchange (in usecs)517481 */518482struct dccp_sock {···529507 __u32 dccps_timestamp_time;530508 __u16 dccps_l_ack_ratio;531509 __u16 dccps_r_ack_ratio;532532- __u64 dccps_l_seq_win:48;533533- __u64 dccps_r_seq_win:48;534534- __u8 dccps_pcslen:4;535535- __u8 dccps_pcrlen:4;536536- __u8 dccps_send_ndp_count:1;510510+ __u16 dccps_pcslen;511511+ __u16 dccps_pcrlen;537512 __u64 dccps_ndp_count:48;538513 unsigned long dccps_rate_last;539539- struct list_head dccps_featneg;514514+ struct dccp_minisock dccps_minisock;540515 struct dccp_ackvec *dccps_hc_rx_ackvec;541516 struct ccid *dccps_hc_rx_ccid;542517 struct ccid *dccps_hc_tx_ccid;543518 struct dccp_options_received dccps_options_received;544544- __u8 dccps_qpolicy;545545- __u32 dccps_tx_qlen;546519 enum dccp_role dccps_role:2;547520 __u8 dccps_hc_rx_insert_options:1;548521 __u8 dccps_hc_tx_insert_options:1;549522 __u8 dccps_server_timewait:1;550550- __u8 dccps_sync_scheduled:1;551551- struct tasklet_struct dccps_xmitlet;552523 struct timer_list dccps_xmit_timer;553524};554525555526static inline struct dccp_sock *dccp_sk(const struct sock *sk)556527{557528 return (struct dccp_sock *)sk;529529+}530530+531531+static inline struct dccp_minisock *dccp_msk(const struct sock *sk)532532+{533533+ return (struct dccp_minisock *)&dccp_sk(sk)->dccps_minisock;558534}559535560536static inline const char *dccp_role(const struct sock *sk)
-15
include/net/tcp.h
···782782/* Use define here intentionally to get WARN_ON location shown at the caller */783783#define tcp_verify_left_out(tp) WARN_ON(tcp_left_out(tp) > tp->packets_out)784784785785-/*786786- * Convert RFC3390 larger initial windows into an equivalent number of packets.787787- *788788- * John Heffner states:789789- *790790- * The RFC specifies a window of no more than 4380 bytes791791- * unless 2*MSS > 4380. Reading the pseudocode in the RFC792792- * is a bit misleading because they use a clamp at 4380 bytes793793- * rather than a multiplier in the relevant range.794794- */795795-static inline u32 rfc3390_bytes_to_packets(const u32 bytes)796796-{797797- return bytes <= 1095 ? 4 : (bytes > 1460 ? 2 : 3);798798-}799799-800785extern void tcp_enter_cwr(struct sock *sk, const int set_ssthresh);801786extern __u32 tcp_init_cwnd(struct tcp_sock *tp, struct dst_entry *dst);802787
+3
net/dccp/Kconfig
···2525 def_tristate y if (IP_DCCP = y && INET_DIAG = y)2626 def_tristate m27272828+config IP_DCCP_ACKVEC2929+ bool3030+2831source "net/dccp/ccids/Kconfig"29323033menu "DCCP Kernel Hacking"
+3-2
net/dccp/Makefile
···11obj-$(CONFIG_IP_DCCP) += dccp.o dccp_ipv4.o2233-dccp-y := ccid.o feat.o input.o minisocks.o options.o \44- qpolicy.o output.o proto.o timer.o ackvec.o33+dccp-y := ccid.o feat.o input.o minisocks.o options.o output.o proto.o timer.o5465dccp_ipv4-y := ipv4.o7687# build dccp_ipv6 as module whenever either IPv6 or DCCP is a module98obj-$(subst y,$(CONFIG_IP_DCCP),$(CONFIG_IPV6)) += dccp_ipv6.o109dccp_ipv6-y := ipv6.o1010+1111+dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o11121213obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o1314obj-$(CONFIG_NET_DCCPPROBE) += dccp_probe.o
+390-319
net/dccp/ackvec.c
···11/*22 * net/dccp/ackvec.c33 *44- * An implementation of Ack Vectors for the DCCP protocol55- * Copyright (c) 2007 University of Aberdeen, Scotland, UK44+ * An implementation of the DCCP protocol65 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>76 *87 * This program is free software; you can redistribute it and/or modify it98 * under the terms of the GNU General Public License as published by the109 * Free Software Foundation; version 2 of the License;1110 */1111+1212+#include "ackvec.h"1213#include "dccp.h"1414+1515+#include <linux/dccp.h>1616+#include <linux/init.h>1717+#include <linux/errno.h>1318#include <linux/kernel.h>1919+#include <linux/skbuff.h>1420#include <linux/slab.h>2121+2222+#include <net/sock.h>15231624static struct kmem_cache *dccp_ackvec_slab;1725static struct kmem_cache *dccp_ackvec_record_slab;18261919-struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)2727+static struct dccp_ackvec_record *dccp_ackvec_record_new(void)2028{2121- struct dccp_ackvec *av = kmem_cache_zalloc(dccp_ackvec_slab, priority);2929+ struct dccp_ackvec_record *avr =3030+ kmem_cache_alloc(dccp_ackvec_record_slab, GFP_ATOMIC);22312323- if (av != NULL) {2424- av->av_buf_head = av->av_buf_tail = DCCPAV_MAX_ACKVEC_LEN - 1;2525- INIT_LIST_HEAD(&av->av_records);2626- }2727- return av;3232+ if (avr != NULL)3333+ INIT_LIST_HEAD(&avr->avr_node);3434+3535+ return avr;2836}29373030-static void dccp_ackvec_purge_records(struct dccp_ackvec *av)3838+static void dccp_ackvec_record_delete(struct dccp_ackvec_record *avr)3139{3232- struct dccp_ackvec_record *cur, *next;4040+ if (unlikely(avr == NULL))4141+ return;4242+ /* Check if deleting a linked record */4343+ WARN_ON(!list_empty(&avr->avr_node));4444+ kmem_cache_free(dccp_ackvec_record_slab, avr);4545+}33463434- list_for_each_entry_safe(cur, next, &av->av_records, avr_node)3535- kmem_cache_free(dccp_ackvec_record_slab, cur);3636- INIT_LIST_HEAD(&av->av_records);4747+static void dccp_ackvec_insert_avr(struct dccp_ackvec *av,4848+ struct dccp_ackvec_record *avr)4949+{5050+ /*5151+ * AVRs are sorted by seqno. Since we are sending them in order, we5252+ * just add the AVR at the head of the list.5353+ * -sorbo.5454+ */5555+ if (!list_empty(&av->av_records)) {5656+ const struct dccp_ackvec_record *head =5757+ list_entry(av->av_records.next,5858+ struct dccp_ackvec_record,5959+ avr_node);6060+ BUG_ON(before48(avr->avr_ack_seqno, head->avr_ack_seqno));6161+ }6262+6363+ list_add(&avr->avr_node, &av->av_records);6464+}6565+6666+int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)6767+{6868+ struct dccp_sock *dp = dccp_sk(sk);6969+ struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;7070+ /* Figure out how many options do we need to represent the ackvec */7171+ const u16 nr_opts = DIV_ROUND_UP(av->av_vec_len, DCCP_MAX_ACKVEC_OPT_LEN);7272+ u16 len = av->av_vec_len + 2 * nr_opts, i;7373+ u32 elapsed_time;7474+ const unsigned char *tail, *from;7575+ unsigned char *to;7676+ struct dccp_ackvec_record *avr;7777+ suseconds_t delta;7878+7979+ if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)8080+ return -1;8181+8282+ delta = ktime_us_delta(ktime_get_real(), av->av_time);8383+ elapsed_time = delta / 10;8484+8585+ if (elapsed_time != 0 &&8686+ dccp_insert_option_elapsed_time(sk, skb, elapsed_time))8787+ return -1;8888+8989+ avr = dccp_ackvec_record_new();9090+ if (avr == NULL)9191+ return -1;9292+9393+ DCCP_SKB_CB(skb)->dccpd_opt_len += len;9494+9595+ to = skb_push(skb, len);9696+ len = av->av_vec_len;9797+ from = av->av_buf + av->av_buf_head;9898+ tail = av->av_buf + DCCP_MAX_ACKVEC_LEN;9999+100100+ for (i = 0; i < nr_opts; ++i) {101101+ int copylen = len;102102+103103+ if (len > DCCP_MAX_ACKVEC_OPT_LEN)104104+ copylen = DCCP_MAX_ACKVEC_OPT_LEN;105105+106106+ *to++ = DCCPO_ACK_VECTOR_0;107107+ *to++ = copylen + 2;108108+109109+ /* Check if buf_head wraps */110110+ if (from + copylen > tail) {111111+ const u16 tailsize = tail - from;112112+113113+ memcpy(to, from, tailsize);114114+ to += tailsize;115115+ len -= tailsize;116116+ copylen -= tailsize;117117+ from = av->av_buf;118118+ }119119+120120+ memcpy(to, from, copylen);121121+ from += copylen;122122+ to += copylen;123123+ len -= copylen;124124+ }125125+126126+ /*127127+ * From RFC 4340, A.2:128128+ *129129+ * For each acknowledgement it sends, the HC-Receiver will add an130130+ * acknowledgement record. ack_seqno will equal the HC-Receiver131131+ * sequence number it used for the ack packet; ack_ptr will equal132132+ * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will133133+ * equal buf_nonce.134134+ */135135+ avr->avr_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq;136136+ avr->avr_ack_ptr = av->av_buf_head;137137+ avr->avr_ack_ackno = av->av_buf_ackno;138138+ avr->avr_ack_nonce = av->av_buf_nonce;139139+ avr->avr_sent_len = av->av_vec_len;140140+141141+ dccp_ackvec_insert_avr(av, avr);142142+143143+ dccp_pr_debug("%s ACK Vector 0, len=%d, ack_seqno=%llu, "144144+ "ack_ackno=%llu\n",145145+ dccp_role(sk), avr->avr_sent_len,146146+ (unsigned long long)avr->avr_ack_seqno,147147+ (unsigned long long)avr->avr_ack_ackno);148148+ return 0;149149+}150150+151151+struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)152152+{153153+ struct dccp_ackvec *av = kmem_cache_alloc(dccp_ackvec_slab, priority);154154+155155+ if (av != NULL) {156156+ av->av_buf_head = DCCP_MAX_ACKVEC_LEN - 1;157157+ av->av_buf_ackno = UINT48_MAX + 1;158158+ av->av_buf_nonce = 0;159159+ av->av_time = ktime_set(0, 0);160160+ av->av_vec_len = 0;161161+ INIT_LIST_HEAD(&av->av_records);162162+ }163163+164164+ return av;37165}3816639167void dccp_ackvec_free(struct dccp_ackvec *av)40168{4141- if (likely(av != NULL)) {4242- dccp_ackvec_purge_records(av);4343- kmem_cache_free(dccp_ackvec_slab, av);169169+ if (unlikely(av == NULL))170170+ return;171171+172172+ if (!list_empty(&av->av_records)) {173173+ struct dccp_ackvec_record *avr, *next;174174+175175+ list_for_each_entry_safe(avr, next, &av->av_records, avr_node) {176176+ list_del_init(&avr->avr_node);177177+ dccp_ackvec_record_delete(avr);178178+ }44179 }180180+181181+ kmem_cache_free(dccp_ackvec_slab, av);45182}461834747-/**4848- * dccp_ackvec_update_records - Record information about sent Ack Vectors4949- * @av: Ack Vector records to update5050- * @seqno: Sequence number of the packet carrying the Ack Vector just sent5151- * @nonce_sum: The sum of all buffer nonces contained in the Ack Vector5252- */5353-int dccp_ackvec_update_records(struct dccp_ackvec *av, u64 seqno, u8 nonce_sum)184184+static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av,185185+ const u32 index)54186{5555- struct dccp_ackvec_record *avr;5656-5757- avr = kmem_cache_alloc(dccp_ackvec_record_slab, GFP_ATOMIC);5858- if (avr == NULL)5959- return -ENOBUFS;6060-6161- avr->avr_ack_seqno = seqno;6262- avr->avr_ack_ptr = av->av_buf_head;6363- avr->avr_ack_ackno = av->av_buf_ackno;6464- avr->avr_ack_nonce = nonce_sum;6565- avr->avr_ack_runlen = dccp_ackvec_runlen(av->av_buf + av->av_buf_head);6666- /*6767- * When the buffer overflows, we keep no more than one record. This is6868- * the simplest way of disambiguating sender-Acks dating from before the6969- * overflow from sender-Acks which refer to after the overflow; a simple7070- * solution is preferable here since we are handling an exception.7171- */7272- if (av->av_overflow)7373- dccp_ackvec_purge_records(av);7474- /*7575- * Since GSS is incremented for each packet, the list is automatically7676- * arranged in descending order of @ack_seqno.7777- */7878- list_add(&avr->avr_node, &av->av_records);7979-8080- dccp_pr_debug("Added Vector, ack_seqno=%llu, ack_ackno=%llu (rl=%u)\n",8181- (unsigned long long)avr->avr_ack_seqno,8282- (unsigned long long)avr->avr_ack_ackno,8383- avr->avr_ack_runlen);8484- return 0;187187+ return av->av_buf[index] & DCCP_ACKVEC_STATE_MASK;85188}861898787-static struct dccp_ackvec_record *dccp_ackvec_lookup(struct list_head *av_list,8888- const u64 ackno)190190+static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av,191191+ const u32 index)89192{9090- struct dccp_ackvec_record *avr;9191- /*9292- * Exploit that records are inserted in descending order of sequence9393- * number, start with the oldest record first. If @ackno is `before'9494- * the earliest ack_ackno, the packet is too old to be considered.9595- */9696- list_for_each_entry_reverse(avr, av_list, avr_node) {9797- if (avr->avr_ack_seqno == ackno)9898- return avr;9999- if (before48(ackno, avr->avr_ack_seqno))100100- break;101101- }102102- return NULL;193193+ return av->av_buf[index] & DCCP_ACKVEC_LEN_MASK;103194}104195105196/*106106- * Buffer index and length computation using modulo-buffersize arithmetic.107107- * Note that, as pointers move from right to left, head is `before' tail.197197+ * If several packets are missing, the HC-Receiver may prefer to enter multiple198198+ * bytes with run length 0, rather than a single byte with a larger run length;199199+ * this simplifies table updates if one of the missing packets arrives.108200 */109109-static inline u16 __ackvec_idx_add(const u16 a, const u16 b)201201+static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av,202202+ const unsigned int packets,203203+ const unsigned char state)110204{111111- return (a + b) % DCCPAV_MAX_ACKVEC_LEN;112112-}205205+ unsigned int gap;206206+ long new_head;113207114114-static inline u16 __ackvec_idx_sub(const u16 a, const u16 b)115115-{116116- return __ackvec_idx_add(a, DCCPAV_MAX_ACKVEC_LEN - b);117117-}208208+ if (av->av_vec_len + packets > DCCP_MAX_ACKVEC_LEN)209209+ return -ENOBUFS;118210119119-u16 dccp_ackvec_buflen(const struct dccp_ackvec *av)120120-{121121- if (unlikely(av->av_overflow))122122- return DCCPAV_MAX_ACKVEC_LEN;123123- return __ackvec_idx_sub(av->av_buf_tail, av->av_buf_head);124124-}211211+ gap = packets - 1;212212+ new_head = av->av_buf_head - packets;125213126126-/**127127- * dccp_ackvec_update_old - Update previous state as per RFC 4340, 11.4.1128128- * @av: non-empty buffer to update129129- * @distance: negative or zero distance of @seqno from buf_ackno downward130130- * @seqno: the (old) sequence number whose record is to be updated131131- * @state: state in which packet carrying @seqno was received132132- */133133-static void dccp_ackvec_update_old(struct dccp_ackvec *av, s64 distance,134134- u64 seqno, enum dccp_ackvec_states state)135135-{136136- u16 ptr = av->av_buf_head;137137-138138- BUG_ON(distance > 0);139139- if (unlikely(dccp_ackvec_is_empty(av)))140140- return;141141-142142- do {143143- u8 runlen = dccp_ackvec_runlen(av->av_buf + ptr);144144-145145- if (distance + runlen >= 0) {146146- /*147147- * Only update the state if packet has not been received148148- * yet. This is OK as per the second table in RFC 4340,149149- * 11.4.1; i.e. here we are using the following table:150150- * RECEIVED151151- * 0 1 3152152- * S +---+---+---+153153- * T 0 | 0 | 0 | 0 |154154- * O +---+---+---+155155- * R 1 | 1 | 1 | 1 |156156- * E +---+---+---+157157- * D 3 | 0 | 1 | 3 |158158- * +---+---+---+159159- * The "Not Received" state was set by reserve_seats().160160- */161161- if (av->av_buf[ptr] == DCCPAV_NOT_RECEIVED)162162- av->av_buf[ptr] = state;163163- else164164- dccp_pr_debug("Not changing %llu state to %u\n",165165- (unsigned long long)seqno, state);166166- break;214214+ if (new_head < 0) {215215+ if (gap > 0) {216216+ memset(av->av_buf, DCCP_ACKVEC_STATE_NOT_RECEIVED,217217+ gap + new_head + 1);218218+ gap = -new_head;167219 }168168-169169- distance += runlen + 1;170170- ptr = __ackvec_idx_add(ptr, 1);171171-172172- } while (ptr != av->av_buf_tail);173173-}174174-175175-/* Mark @num entries after buf_head as "Not yet received". */176176-static void dccp_ackvec_reserve_seats(struct dccp_ackvec *av, u16 num)177177-{178178- u16 start = __ackvec_idx_add(av->av_buf_head, 1),179179- len = DCCPAV_MAX_ACKVEC_LEN - start;180180-181181- /* check for buffer wrap-around */182182- if (num > len) {183183- memset(av->av_buf + start, DCCPAV_NOT_RECEIVED, len);184184- start = 0;185185- num -= len;186186- }187187- if (num)188188- memset(av->av_buf + start, DCCPAV_NOT_RECEIVED, num);189189-}190190-191191-/**192192- * dccp_ackvec_add_new - Record one or more new entries in Ack Vector buffer193193- * @av: container of buffer to update (can be empty or non-empty)194194- * @num_packets: number of packets to register (must be >= 1)195195- * @seqno: sequence number of the first packet in @num_packets196196- * @state: state in which packet carrying @seqno was received197197- */198198-static void dccp_ackvec_add_new(struct dccp_ackvec *av, u32 num_packets,199199- u64 seqno, enum dccp_ackvec_states state)200200-{201201- u32 num_cells = num_packets;202202-203203- if (num_packets > DCCPAV_BURST_THRESH) {204204- u32 lost_packets = num_packets - 1;205205-206206- DCCP_WARN("Warning: large burst loss (%u)\n", lost_packets);207207- /*208208- * We received 1 packet and have a loss of size "num_packets-1"209209- * which we squeeze into num_cells-1 rather than reserving an210210- * entire byte for each lost packet.211211- * The reason is that the vector grows in O(burst_length); when212212- * it grows too large there will no room left for the payload.213213- * This is a trade-off: if a few packets out of the burst show214214- * up later, their state will not be changed; it is simply too215215- * costly to reshuffle/reallocate/copy the buffer each time.216216- * Should such problems persist, we will need to switch to a217217- * different underlying data structure.218218- */219219- for (num_packets = num_cells = 1; lost_packets; ++num_cells) {220220- u8 len = min(lost_packets, (u32)DCCPAV_MAX_RUNLEN);221221-222222- av->av_buf_head = __ackvec_idx_sub(av->av_buf_head, 1);223223- av->av_buf[av->av_buf_head] = DCCPAV_NOT_RECEIVED | len;224224-225225- lost_packets -= len;226226- }220220+ new_head += DCCP_MAX_ACKVEC_LEN;227221 }228222229229- if (num_cells + dccp_ackvec_buflen(av) >= DCCPAV_MAX_ACKVEC_LEN) {230230- DCCP_CRIT("Ack Vector buffer overflow: dropping old entries\n");231231- av->av_overflow = true;232232- }223223+ av->av_buf_head = new_head;233224234234- av->av_buf_head = __ackvec_idx_sub(av->av_buf_head, num_packets);235235- if (av->av_overflow)236236- av->av_buf_tail = av->av_buf_head;225225+ if (gap > 0)226226+ memset(av->av_buf + av->av_buf_head + 1,227227+ DCCP_ACKVEC_STATE_NOT_RECEIVED, gap);237228238229 av->av_buf[av->av_buf_head] = state;239239- av->av_buf_ackno = seqno;240240-241241- if (num_packets > 1)242242- dccp_ackvec_reserve_seats(av, num_packets - 1);243243-}244244-245245-/**246246- * dccp_ackvec_input - Register incoming packet in the buffer247247- */248248-void dccp_ackvec_input(struct dccp_ackvec *av, struct sk_buff *skb)249249-{250250- u64 seqno = DCCP_SKB_CB(skb)->dccpd_seq;251251- enum dccp_ackvec_states state = DCCPAV_RECEIVED;252252-253253- if (dccp_ackvec_is_empty(av)) {254254- dccp_ackvec_add_new(av, 1, seqno, state);255255- av->av_tail_ackno = seqno;256256-257257- } else {258258- s64 num_packets = dccp_delta_seqno(av->av_buf_ackno, seqno);259259- u8 *current_head = av->av_buf + av->av_buf_head;260260-261261- if (num_packets == 1 &&262262- dccp_ackvec_state(current_head) == state &&263263- dccp_ackvec_runlen(current_head) < DCCPAV_MAX_RUNLEN) {264264-265265- *current_head += 1;266266- av->av_buf_ackno = seqno;267267-268268- } else if (num_packets > 0) {269269- dccp_ackvec_add_new(av, num_packets, seqno, state);270270- } else {271271- dccp_ackvec_update_old(av, num_packets, seqno, state);272272- }273273- }274274-}275275-276276-/**277277- * dccp_ackvec_clear_state - Perform house-keeping / garbage-collection278278- * This routine is called when the peer acknowledges the receipt of Ack Vectors279279- * up to and including @ackno. While based on on section A.3 of RFC 4340, here280280- * are additional precautions to prevent corrupted buffer state. In particular,281281- * we use tail_ackno to identify outdated records; it always marks the earliest282282- * packet of group (2) in 11.4.2.283283- */284284-void dccp_ackvec_clear_state(struct dccp_ackvec *av, const u64 ackno)285285- {286286- struct dccp_ackvec_record *avr, *next;287287- u8 runlen_now, eff_runlen;288288- s64 delta;289289-290290- avr = dccp_ackvec_lookup(&av->av_records, ackno);291291- if (avr == NULL)292292- return;293293- /*294294- * Deal with outdated acknowledgments: this arises when e.g. there are295295- * several old records and the acks from the peer come in slowly. In296296- * that case we may still have records that pre-date tail_ackno.297297- */298298- delta = dccp_delta_seqno(av->av_tail_ackno, avr->avr_ack_ackno);299299- if (delta < 0)300300- goto free_records;301301- /*302302- * Deal with overlapping Ack Vectors: don't subtract more than the303303- * number of packets between tail_ackno and ack_ackno.304304- */305305- eff_runlen = delta < avr->avr_ack_runlen ? delta : avr->avr_ack_runlen;306306-307307- runlen_now = dccp_ackvec_runlen(av->av_buf + avr->avr_ack_ptr);308308- /*309309- * The run length of Ack Vector cells does not decrease over time. If310310- * the run length is the same as at the time the Ack Vector was sent, we311311- * free the ack_ptr cell. That cell can however not be freed if the run312312- * length has increased: in this case we need to move the tail pointer313313- * backwards (towards higher indices), to its next-oldest neighbour.314314- */315315- if (runlen_now > eff_runlen) {316316-317317- av->av_buf[avr->avr_ack_ptr] -= eff_runlen + 1;318318- av->av_buf_tail = __ackvec_idx_add(avr->avr_ack_ptr, 1);319319-320320- /* This move may not have cleared the overflow flag. */321321- if (av->av_overflow)322322- av->av_overflow = (av->av_buf_head == av->av_buf_tail);323323- } else {324324- av->av_buf_tail = avr->avr_ack_ptr;325325- /*326326- * We have made sure that avr points to a valid cell within the327327- * buffer. This cell is either older than head, or equals head328328- * (empty buffer): in both cases we no longer have any overflow.329329- */330330- av->av_overflow = 0;331331- }332332-333333- /*334334- * The peer has acknowledged up to and including ack_ackno. Hence the335335- * first packet in group (2) of 11.4.2 is the successor of ack_ackno.336336- */337337- av->av_tail_ackno = ADD48(avr->avr_ack_ackno, 1);338338-339339-free_records:340340- list_for_each_entry_safe_from(avr, next, &av->av_records, avr_node) {341341- list_del(&avr->avr_node);342342- kmem_cache_free(dccp_ackvec_record_slab, avr);343343- }230230+ av->av_vec_len += packets;231231+ return 0;344232}345233346234/*347347- * Routines to keep track of Ack Vectors received in an skb235235+ * Implements the RFC 4340, Appendix A348236 */349349-int dccp_ackvec_parsed_add(struct list_head *head, u8 *vec, u8 len, u8 nonce)237237+int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,238238+ const u64 ackno, const u8 state)350239{351351- struct dccp_ackvec_parsed *new = kmalloc(sizeof(*new), GFP_ATOMIC);240240+ /*241241+ * Check at the right places if the buffer is full, if it is, tell the242242+ * caller to start dropping packets till the HC-Sender acks our ACK243243+ * vectors, when we will free up space in av_buf.244244+ *245245+ * We may well decide to do buffer compression, etc, but for now lets246246+ * just drop.247247+ *248248+ * From Appendix A.1.1 (`New Packets'):249249+ *250250+ * Of course, the circular buffer may overflow, either when the251251+ * HC-Sender is sending data at a very high rate, when the252252+ * HC-Receiver's acknowledgements are not reaching the HC-Sender,253253+ * or when the HC-Sender is forgetting to acknowledge those acks254254+ * (so the HC-Receiver is unable to clean up old state). In this255255+ * case, the HC-Receiver should either compress the buffer (by256256+ * increasing run lengths when possible), transfer its state to257257+ * a larger buffer, or, as a last resort, drop all received258258+ * packets, without processing them whatsoever, until its buffer259259+ * shrinks again.260260+ */352261353353- if (new == NULL)354354- return -ENOBUFS;355355- new->vec = vec;356356- new->len = len;357357- new->nonce = nonce;262262+ /* See if this is the first ackno being inserted */263263+ if (av->av_vec_len == 0) {264264+ av->av_buf[av->av_buf_head] = state;265265+ av->av_vec_len = 1;266266+ } else if (after48(ackno, av->av_buf_ackno)) {267267+ const u64 delta = dccp_delta_seqno(av->av_buf_ackno, ackno);358268359359- list_add_tail(&new->node, head);269269+ /*270270+ * Look if the state of this packet is the same as the271271+ * previous ackno and if so if we can bump the head len.272272+ */273273+ if (delta == 1 &&274274+ dccp_ackvec_state(av, av->av_buf_head) == state &&275275+ dccp_ackvec_len(av, av->av_buf_head) < DCCP_ACKVEC_LEN_MASK)276276+ av->av_buf[av->av_buf_head]++;277277+ else if (dccp_ackvec_set_buf_head_state(av, delta, state))278278+ return -ENOBUFS;279279+ } else {280280+ /*281281+ * A.1.2. Old Packets282282+ *283283+ * When a packet with Sequence Number S <= buf_ackno284284+ * arrives, the HC-Receiver will scan the table for285285+ * the byte corresponding to S. (Indexing structures286286+ * could reduce the complexity of this scan.)287287+ */288288+ u64 delta = dccp_delta_seqno(ackno, av->av_buf_ackno);289289+ u32 index = av->av_buf_head;290290+291291+ while (1) {292292+ const u8 len = dccp_ackvec_len(av, index);293293+ const u8 av_state = dccp_ackvec_state(av, index);294294+ /*295295+ * valid packets not yet in av_buf have a reserved296296+ * entry, with a len equal to 0.297297+ */298298+ if (av_state == DCCP_ACKVEC_STATE_NOT_RECEIVED &&299299+ len == 0 && delta == 0) { /* Found our300300+ reserved seat! */301301+ dccp_pr_debug("Found %llu reserved seat!\n",302302+ (unsigned long long)ackno);303303+ av->av_buf[index] = state;304304+ goto out;305305+ }306306+ /* len == 0 means one packet */307307+ if (delta < len + 1)308308+ goto out_duplicate;309309+310310+ delta -= len + 1;311311+ if (++index == DCCP_MAX_ACKVEC_LEN)312312+ index = 0;313313+ }314314+ }315315+316316+ av->av_buf_ackno = ackno;317317+ av->av_time = ktime_get_real();318318+out:319319+ return 0;320320+321321+out_duplicate:322322+ /* Duplicate packet */323323+ dccp_pr_debug("Received a dup or already considered lost "324324+ "packet: %llu\n", (unsigned long long)ackno);325325+ return -EILSEQ;326326+}327327+328328+static void dccp_ackvec_throw_record(struct dccp_ackvec *av,329329+ struct dccp_ackvec_record *avr)330330+{331331+ struct dccp_ackvec_record *next;332332+333333+ /* sort out vector length */334334+ if (av->av_buf_head <= avr->avr_ack_ptr)335335+ av->av_vec_len = avr->avr_ack_ptr - av->av_buf_head;336336+ else337337+ av->av_vec_len = DCCP_MAX_ACKVEC_LEN - 1 -338338+ av->av_buf_head + avr->avr_ack_ptr;339339+340340+ /* free records */341341+ list_for_each_entry_safe_from(avr, next, &av->av_records, avr_node) {342342+ list_del_init(&avr->avr_node);343343+ dccp_ackvec_record_delete(avr);344344+ }345345+}346346+347347+void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk,348348+ const u64 ackno)349349+{350350+ struct dccp_ackvec_record *avr;351351+352352+ /*353353+ * If we traverse backwards, it should be faster when we have large354354+ * windows. We will be receiving ACKs for stuff we sent a while back355355+ * -sorbo.356356+ */357357+ list_for_each_entry_reverse(avr, &av->av_records, avr_node) {358358+ if (ackno == avr->avr_ack_seqno) {359359+ dccp_pr_debug("%s ACK packet 0, len=%d, ack_seqno=%llu, "360360+ "ack_ackno=%llu, ACKED!\n",361361+ dccp_role(sk), 1,362362+ (unsigned long long)avr->avr_ack_seqno,363363+ (unsigned long long)avr->avr_ack_ackno);364364+ dccp_ackvec_throw_record(av, avr);365365+ break;366366+ } else if (avr->avr_ack_seqno > ackno)367367+ break; /* old news */368368+ }369369+}370370+371371+static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,372372+ struct sock *sk, u64 *ackno,373373+ const unsigned char len,374374+ const unsigned char *vector)375375+{376376+ unsigned char i;377377+ struct dccp_ackvec_record *avr;378378+379379+ /* Check if we actually sent an ACK vector */380380+ if (list_empty(&av->av_records))381381+ return;382382+383383+ i = len;384384+ /*385385+ * XXX386386+ * I think it might be more efficient to work backwards. See comment on387387+ * rcv_ackno. -sorbo.388388+ */389389+ avr = list_entry(av->av_records.next, struct dccp_ackvec_record, avr_node);390390+ while (i--) {391391+ const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;392392+ u64 ackno_end_rl;393393+394394+ dccp_set_seqno(&ackno_end_rl, *ackno - rl);395395+396396+ /*397397+ * If our AVR sequence number is greater than the ack, go398398+ * forward in the AVR list until it is not so.399399+ */400400+ list_for_each_entry_from(avr, &av->av_records, avr_node) {401401+ if (!after48(avr->avr_ack_seqno, *ackno))402402+ goto found;403403+ }404404+ /* End of the av_records list, not found, exit */405405+ break;406406+found:407407+ if (between48(avr->avr_ack_seqno, ackno_end_rl, *ackno)) {408408+ const u8 state = *vector & DCCP_ACKVEC_STATE_MASK;409409+ if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) {410410+ dccp_pr_debug("%s ACK vector 0, len=%d, "411411+ "ack_seqno=%llu, ack_ackno=%llu, "412412+ "ACKED!\n",413413+ dccp_role(sk), len,414414+ (unsigned long long)415415+ avr->avr_ack_seqno,416416+ (unsigned long long)417417+ avr->avr_ack_ackno);418418+ dccp_ackvec_throw_record(av, avr);419419+ break;420420+ }421421+ /*422422+ * If it wasn't received, continue scanning... we might423423+ * find another one.424424+ */425425+ }426426+427427+ dccp_set_seqno(ackno, ackno_end_rl - 1);428428+ ++vector;429429+ }430430+}431431+432432+int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,433433+ u64 *ackno, const u8 opt, const u8 *value, const u8 len)434434+{435435+ if (len > DCCP_MAX_ACKVEC_OPT_LEN)436436+ return -1;437437+438438+ /* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */439439+ dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec, sk,440440+ ackno, len, value);360441 return 0;361442}362362-EXPORT_SYMBOL_GPL(dccp_ackvec_parsed_add);363363-364364-void dccp_ackvec_parsed_cleanup(struct list_head *parsed_chunks)365365-{366366- struct dccp_ackvec_parsed *cur, *next;367367-368368- list_for_each_entry_safe(cur, next, parsed_chunks, node)369369- kfree(cur);370370- INIT_LIST_HEAD(parsed_chunks);371371-}372372-EXPORT_SYMBOL_GPL(dccp_ackvec_parsed_cleanup);373443374444int __init dccp_ackvec_init(void)375445{···449379 if (dccp_ackvec_slab == NULL)450380 goto out_err;451381452452- dccp_ackvec_record_slab = kmem_cache_create("dccp_ackvec_record",453453- sizeof(struct dccp_ackvec_record),454454- 0, SLAB_HWCACHE_ALIGN, NULL);382382+ dccp_ackvec_record_slab =383383+ kmem_cache_create("dccp_ackvec_record",384384+ sizeof(struct dccp_ackvec_record),385385+ 0, SLAB_HWCACHE_ALIGN, NULL);455386 if (dccp_ackvec_record_slab == NULL)456387 goto out_destroy_slab;457388
+113-91
net/dccp/ackvec.h
···33/*44 * net/dccp/ackvec.h55 *66- * An implementation of Ack Vectors for the DCCP protocol77- * Copyright (c) 2007 University of Aberdeen, Scotland, UK66+ * An implementation of the DCCP protocol87 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@mandriva.com>88+ *99 * This program is free software; you can redistribute it and/or modify it1010 * under the terms of the GNU General Public License version 2 as1111 * published by the Free Software Foundation.1212 */13131414-#include <linux/dccp.h>1514#include <linux/compiler.h>1515+#include <linux/ktime.h>1616#include <linux/list.h>1717#include <linux/types.h>18181919-/*2020- * Ack Vector buffer space is static, in multiples of %DCCP_SINGLE_OPT_MAXLEN,2121- * the maximum size of a single Ack Vector. Setting %DCCPAV_NUM_ACKVECS to 12222- * will be sufficient for most cases of low Ack Ratios, using a value of 2 gives2323- * more headroom if Ack Ratio is higher or when the sender acknowledges slowly.2424- * The maximum value is bounded by the u16 types for indices and functions.2525- */2626-#define DCCPAV_NUM_ACKVECS 22727-#define DCCPAV_MAX_ACKVEC_LEN (DCCP_SINGLE_OPT_MAXLEN * DCCPAV_NUM_ACKVECS)1919+/* Read about the ECN nonce to see why it is 253 */2020+#define DCCP_MAX_ACKVEC_OPT_LEN 2532121+/* We can spread an ack vector across multiple options */2222+#define DCCP_MAX_ACKVEC_LEN (DCCP_MAX_ACKVEC_OPT_LEN * 2)28232929-/* Estimated minimum average Ack Vector length - used for updating MPS */3030-#define DCCPAV_MIN_OPTLEN 162424+#define DCCP_ACKVEC_STATE_RECEIVED 02525+#define DCCP_ACKVEC_STATE_ECN_MARKED (1 << 6)2626+#define DCCP_ACKVEC_STATE_NOT_RECEIVED (3 << 6)31273232-/* Threshold for coping with large bursts of losses */3333-#define DCCPAV_BURST_THRESH (DCCPAV_MAX_ACKVEC_LEN / 8)2828+#define DCCP_ACKVEC_STATE_MASK 0xC0 /* 11000000 */2929+#define DCCP_ACKVEC_LEN_MASK 0x3F /* 00111111 */34303535-enum dccp_ackvec_states {3636- DCCPAV_RECEIVED = 0x00,3737- DCCPAV_ECN_MARKED = 0x40,3838- DCCPAV_RESERVED = 0x80,3939- DCCPAV_NOT_RECEIVED = 0xC04040-};4141-#define DCCPAV_MAX_RUNLEN 0x3F4242-4343-static inline u8 dccp_ackvec_runlen(const u8 *cell)4444-{4545- return *cell & DCCPAV_MAX_RUNLEN;4646-}4747-4848-static inline u8 dccp_ackvec_state(const u8 *cell)4949-{5050- return *cell & ~DCCPAV_MAX_RUNLEN;5151-}5252-5353-/** struct dccp_ackvec - Ack Vector main data structure3131+/** struct dccp_ackvec - ack vector5432 *5555- * This implements a fixed-size circular buffer within an array and is largely5656- * based on Appendix A of RFC 4340.3333+ * This data structure is the one defined in RFC 4340, Appendix A.5734 *5858- * @av_buf: circular buffer storage area5959- * @av_buf_head: head index; begin of live portion in @av_buf6060- * @av_buf_tail: tail index; first index _after_ the live portion in @av_buf6161- * @av_buf_ackno: highest seqno of acknowledgeable packet recorded in @av_buf6262- * @av_tail_ackno: lowest seqno of acknowledgeable packet recorded in @av_buf6363- * @av_buf_nonce: ECN nonce sums, each covering subsequent segments of up to6464- * %DCCP_SINGLE_OPT_MAXLEN cells in the live portion of @av_buf6565- * @av_overflow: if 1 then buf_head == buf_tail indicates buffer wraparound6666- * @av_records: list of %dccp_ackvec_record (Ack Vectors sent previously)3535+ * @av_buf_head - circular buffer head3636+ * @av_buf_tail - circular buffer tail3737+ * @av_buf_ackno - ack # of the most recent packet acknowledgeable in the3838+ * buffer (i.e. %av_buf_head)3939+ * @av_buf_nonce - the one-bit sum of the ECN Nonces on all packets acked4040+ * by the buffer with State 04141+ *4242+ * Additionally, the HC-Receiver must keep some information about the4343+ * Ack Vectors it has recently sent. For each packet sent carrying an4444+ * Ack Vector, it remembers four variables:4545+ *4646+ * @av_records - list of dccp_ackvec_record4747+ * @av_ack_nonce - the one-bit sum of the ECN Nonces for all State 0.4848+ *4949+ * @av_time - the time in usecs5050+ * @av_buf - circular buffer of acknowledgeable packets6751 */6852struct dccp_ackvec {6969- u8 av_buf[DCCPAV_MAX_ACKVEC_LEN];7070- u16 av_buf_head;7171- u16 av_buf_tail;7272- u64 av_buf_ackno:48;7373- u64 av_tail_ackno:48;7474- bool av_buf_nonce[DCCPAV_NUM_ACKVECS];7575- u8 av_overflow:1;5353+ u64 av_buf_ackno;7654 struct list_head av_records;5555+ ktime_t av_time;5656+ u16 av_buf_head;5757+ u16 av_vec_len;5858+ u8 av_buf_nonce;5959+ u8 av_ack_nonce;6060+ u8 av_buf[DCCP_MAX_ACKVEC_LEN];7761};78627979-/** struct dccp_ackvec_record - Records information about sent Ack Vectors6363+/** struct dccp_ackvec_record - ack vector record8064 *8181- * These list entries define the additional information which the HC-Receiver8282- * keeps about recently-sent Ack Vectors; again refer to RFC 4340, Appendix A.6565+ * ACK vector record as defined in Appendix A of spec.8366 *8484- * @avr_node: the list node in @av_records8585- * @avr_ack_seqno: sequence number of the packet the Ack Vector was sent on8686- * @avr_ack_ackno: the Ack number that this record/Ack Vector refers to8787- * @avr_ack_ptr: pointer into @av_buf where this record starts8888- * @avr_ack_runlen: run length of @avr_ack_ptr at the time of sending8989- * @avr_ack_nonce: the sum of @av_buf_nonce's at the time this record was sent6767+ * The list is sorted by avr_ack_seqno9068 *9191- * The list as a whole is sorted in descending order by @avr_ack_seqno.6969+ * @avr_node - node in av_records7070+ * @avr_ack_seqno - sequence number of the packet this record was sent on7171+ * @avr_ack_ackno - sequence number being acknowledged7272+ * @avr_ack_ptr - pointer into av_buf where this record starts7373+ * @avr_ack_nonce - av_ack_nonce at the time this record was sent7474+ * @avr_sent_len - lenght of the record in av_buf9275 */9376struct dccp_ackvec_record {9477 struct list_head avr_node;9595- u64 avr_ack_seqno:48;9696- u64 avr_ack_ackno:48;7878+ u64 avr_ack_seqno;7979+ u64 avr_ack_ackno;9780 u16 avr_ack_ptr;9898- u8 avr_ack_runlen;9999- u8 avr_ack_nonce:1;8181+ u16 avr_sent_len;8282+ u8 avr_ack_nonce;10083};10184102102-extern int dccp_ackvec_init(void);8585+struct sock;8686+struct sk_buff;8787+8888+#ifdef CONFIG_IP_DCCP_ACKVEC8989+extern int dccp_ackvec_init(void);10390extern void dccp_ackvec_exit(void);1049110592extern struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority);10693extern void dccp_ackvec_free(struct dccp_ackvec *av);10794108108-extern void dccp_ackvec_input(struct dccp_ackvec *av, struct sk_buff *skb);109109-extern int dccp_ackvec_update_records(struct dccp_ackvec *av, u64 seq, u8 sum);110110-extern void dccp_ackvec_clear_state(struct dccp_ackvec *av, const u64 ackno);111111-extern u16 dccp_ackvec_buflen(const struct dccp_ackvec *av);9595+extern int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,9696+ const u64 ackno, const u8 state);11297113113-static inline bool dccp_ackvec_is_empty(const struct dccp_ackvec *av)9898+extern void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av,9999+ struct sock *sk, const u64 ackno);100100+extern int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,101101+ u64 *ackno, const u8 opt,102102+ const u8 *value, const u8 len);103103+104104+extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb);105105+106106+static inline int dccp_ackvec_pending(const struct dccp_ackvec *av)114107{115115- return av->av_overflow == 0 && av->av_buf_head == av->av_buf_tail;108108+ return av->av_vec_len;109109+}110110+#else /* CONFIG_IP_DCCP_ACKVEC */111111+static inline int dccp_ackvec_init(void)112112+{113113+ return 0;116114}117115118118-/**119119- * struct dccp_ackvec_parsed - Record offsets of Ack Vectors in skb120120- * @vec: start of vector (offset into skb)121121- * @len: length of @vec122122- * @nonce: whether @vec had an ECN nonce of 0 or 1123123- * @node: FIFO - arranged in descending order of ack_ackno124124- * This structure is used by CCIDs to access Ack Vectors in a received skb.125125- */126126-struct dccp_ackvec_parsed {127127- u8 *vec,128128- len,129129- nonce:1;130130- struct list_head node;131131-};116116+static inline void dccp_ackvec_exit(void)117117+{118118+}132119133133-extern int dccp_ackvec_parsed_add(struct list_head *head,134134- u8 *vec, u8 len, u8 nonce);135135-extern void dccp_ackvec_parsed_cleanup(struct list_head *parsed_chunks);120120+static inline struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)121121+{122122+ return NULL;123123+}124124+125125+static inline void dccp_ackvec_free(struct dccp_ackvec *av)126126+{127127+}128128+129129+static inline int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,130130+ const u64 ackno, const u8 state)131131+{132132+ return -1;133133+}134134+135135+static inline void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av,136136+ struct sock *sk, const u64 ackno)137137+{138138+}139139+140140+static inline int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,141141+ const u64 *ackno, const u8 opt,142142+ const u8 *value, const u8 len)143143+{144144+ return -1;145145+}146146+147147+static inline int dccp_insert_option_ackvec(const struct sock *sk,148148+ const struct sk_buff *skb)149149+{150150+ return -1;151151+}152152+153153+static inline int dccp_ackvec_pending(const struct dccp_ackvec *av)154154+{155155+ return 0;156156+}157157+#endif /* CONFIG_IP_DCCP_ACKVEC */136158#endif /* _ACKVEC_H */
+24-77
net/dccp/ccid.c
···13131414#include "ccid.h"15151616-static u8 builtin_ccids[] = {1717- DCCPC_CCID2, /* CCID2 is supported by default */1818-#if defined(CONFIG_IP_DCCP_CCID3) || defined(CONFIG_IP_DCCP_CCID3_MODULE)1919- DCCPC_CCID3,2020-#endif2121-};2222-2316static struct ccid_operations *ccids[CCID_MAX];2417#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)2518static atomic_t ccids_lockct = ATOMIC_INIT(0);···8693 }8794}88958989-/* check that up to @array_len members in @ccid_array are supported */9090-bool ccid_support_check(u8 const *ccid_array, u8 array_len)9191-{9292- u8 i, j, found;9393-9494- for (i = 0, found = 0; i < array_len; i++, found = 0) {9595- for (j = 0; !found && j < ARRAY_SIZE(builtin_ccids); j++)9696- found = (ccid_array[i] == builtin_ccids[j]);9797- if (!found)9898- return false;9999- }100100- return true;101101-}102102-103103-/**104104- * ccid_get_builtin_ccids - Provide copy of `builtin' CCID array105105- * @ccid_array: pointer to copy into106106- * @array_len: value to return length into107107- * This function allocates memory - caller must see that it is freed after use.108108- */109109-int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len)110110-{111111- *ccid_array = kmemdup(builtin_ccids, sizeof(builtin_ccids), gfp_any());112112- if (*ccid_array == NULL)113113- return -ENOBUFS;114114- *array_len = ARRAY_SIZE(builtin_ccids);115115- return 0;116116-}117117-118118-int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,119119- char __user *optval, int __user *optlen)120120-{121121- if (len < sizeof(builtin_ccids))122122- return -EINVAL;123123-124124- if (put_user(sizeof(builtin_ccids), optlen) ||125125- copy_to_user(optval, builtin_ccids, sizeof(builtin_ccids)))126126- return -EFAULT;127127- return 0;128128-}129129-13096int ccid_register(struct ccid_operations *ccid_ops)13197{13298 int err = -ENOBUFS;···148196149197EXPORT_SYMBOL_GPL(ccid_unregister);150198151151-/**152152- * ccid_request_module - Pre-load CCID module for later use153153- * This should be called only from process context (e.g. during connection154154- * setup) and is necessary for later calls to ccid_new (typically in software155155- * interrupt), so that it has the modules available when they are needed.156156- */157157-static int ccid_request_module(u8 id)158158-{159159- if (!in_atomic()) {160160- ccids_read_lock();161161- if (ccids[id] == NULL) {162162- ccids_read_unlock();163163- return request_module("net-dccp-ccid-%d", id);164164- }165165- ccids_read_unlock();166166- }167167- return 0;168168-}169169-170170-int ccid_request_modules(u8 const *ccid_array, u8 array_len)171171-{172172-#ifdef CONFIG_KMOD173173- while (array_len--)174174- if (ccid_request_module(ccid_array[array_len]))175175- return -1;176176-#endif177177- return 0;178178-}179179-180199struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp)181200{182201 struct ccid_operations *ccid_ops;183202 struct ccid *ccid = NULL;184203185204 ccids_read_lock();205205+#ifdef CONFIG_KMOD206206+ if (ccids[id] == NULL) {207207+ /* We only try to load if in process context */208208+ ccids_read_unlock();209209+ if (gfp & GFP_ATOMIC)210210+ goto out;211211+ request_module("net-dccp-ccid-%d", id);212212+ ccids_read_lock();213213+ }214214+#endif186215 ccid_ops = ccids[id];187216 if (ccid_ops == NULL)188217 goto out_unlock;···204271}205272206273EXPORT_SYMBOL_GPL(ccid_new);274274+275275+struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk, gfp_t gfp)276276+{277277+ return ccid_new(id, sk, 1, gfp);278278+}279279+280280+EXPORT_SYMBOL_GPL(ccid_hc_rx_new);281281+282282+struct ccid *ccid_hc_tx_new(unsigned char id,struct sock *sk, gfp_t gfp)283283+{284284+ return ccid_new(id, sk, 0, gfp);285285+}286286+287287+EXPORT_SYMBOL_GPL(ccid_hc_tx_new);207288208289static void ccid_delete(struct ccid *ccid, struct sock *sk, int rx)209290{
+33-80
net/dccp/ccid.h
···6060 void (*ccid_hc_tx_exit)(struct sock *sk);6161 void (*ccid_hc_rx_packet_recv)(struct sock *sk,6262 struct sk_buff *skb);6363- int (*ccid_hc_rx_parse_options)(struct sock *sk, u8 pkt,6464- u8 opt, u8 *val, u8 len);6363+ int (*ccid_hc_rx_parse_options)(struct sock *sk,6464+ unsigned char option,6565+ unsigned char len, u16 idx,6666+ unsigned char* value);6567 int (*ccid_hc_rx_insert_options)(struct sock *sk,6668 struct sk_buff *skb);6769 void (*ccid_hc_tx_packet_recv)(struct sock *sk,6870 struct sk_buff *skb);6969- int (*ccid_hc_tx_parse_options)(struct sock *sk, u8 pkt,7070- u8 opt, u8 *val, u8 len);7171+ int (*ccid_hc_tx_parse_options)(struct sock *sk,7272+ unsigned char option,7373+ unsigned char len, u16 idx,7474+ unsigned char* value);7175 int (*ccid_hc_tx_send_packet)(struct sock *sk,7276 struct sk_buff *skb);7377 void (*ccid_hc_tx_packet_sent)(struct sock *sk,7474- unsigned int len);7878+ int more, unsigned int len);7579 void (*ccid_hc_rx_get_info)(struct sock *sk,7680 struct tcp_info *info);7781 void (*ccid_hc_tx_get_info)(struct sock *sk,···10399 return (void *)ccid->ccid_priv;104100}105101106106-extern bool ccid_support_check(u8 const *ccid_array, u8 array_len);107107-extern int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len);108108-extern int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,109109- char __user *, int __user *);110110-111111-extern int ccid_request_modules(u8 const *ccid_array, u8 array_len);112102extern struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx,113103 gfp_t gfp);114104115115-static inline int ccid_get_current_rx_ccid(struct dccp_sock *dp)116116-{117117- struct ccid *ccid = dp->dccps_hc_rx_ccid;118118-119119- if (ccid == NULL || ccid->ccid_ops == NULL)120120- return -1;121121- return ccid->ccid_ops->ccid_id;122122-}123123-124124-static inline int ccid_get_current_tx_ccid(struct dccp_sock *dp)125125-{126126- struct ccid *ccid = dp->dccps_hc_tx_ccid;127127-128128- if (ccid == NULL || ccid->ccid_ops == NULL)129129- return -1;130130- return ccid->ccid_ops->ccid_id;131131-}105105+extern struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk,106106+ gfp_t gfp);107107+extern struct ccid *ccid_hc_tx_new(unsigned char id, struct sock *sk,108108+ gfp_t gfp);132109133110extern void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk);134111extern void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk);135112136136-/*137137- * Congestion control of queued data packets via CCID decision.138138- *139139- * The TX CCID performs its congestion-control by indicating whether and when a140140- * queued packet may be sent, using the return code of ccid_hc_tx_send_packet().141141- * The following modes are supported via the symbolic constants below:142142- * - timer-based pacing (CCID returns a delay value in milliseconds);143143- * - autonomous dequeueing (CCID internally schedules dccps_xmitlet).144144- */145145-146146-enum ccid_dequeueing_decision {147147- CCID_PACKET_SEND_AT_ONCE = 0x00000, /* "green light": no delay */148148- CCID_PACKET_DELAY_MAX = 0x0FFFF, /* maximum delay in msecs */149149- CCID_PACKET_DELAY = 0x10000, /* CCID msec-delay mode */150150- CCID_PACKET_WILL_DEQUEUE_LATER = 0x20000, /* CCID autonomous mode */151151- CCID_PACKET_ERR = 0xF0000, /* error condition */152152-};153153-154154-static inline int ccid_packet_dequeue_eval(const int return_code)155155-{156156- if (return_code < 0)157157- return CCID_PACKET_ERR;158158- if (return_code == 0)159159- return CCID_PACKET_SEND_AT_ONCE;160160- if (return_code <= CCID_PACKET_DELAY_MAX)161161- return CCID_PACKET_DELAY;162162- return return_code;163163-}164164-165113static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,166114 struct sk_buff *skb)167115{116116+ int rc = 0;168117 if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL)169169- return ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb);170170- return CCID_PACKET_SEND_AT_ONCE;118118+ rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb);119119+ return rc;171120}172121173122static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,174174- unsigned int len)123123+ int more, unsigned int len)175124{176125 if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)177177- ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, len);126126+ ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, more, len);178127}179128180129static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,···144187 ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);145188}146189147147-/**148148- * ccid_hc_tx_parse_options - Parse CCID-specific options sent by the receiver149149- * @pkt: type of packet that @opt appears on (RFC 4340, 5.1)150150- * @opt: the CCID-specific option type (RFC 4340, 5.8 and 10.3)151151- * @val: value of @opt152152- * @len: length of @val in bytes153153- */154190static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,155155- u8 pkt, u8 opt, u8 *val, u8 len)191191+ unsigned char option,192192+ unsigned char len, u16 idx,193193+ unsigned char* value)156194{157157- if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL)158158- return 0;159159- return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);195195+ int rc = 0;196196+ if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL)197197+ rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx,198198+ value);199199+ return rc;160200}161201162162-/**163163- * ccid_hc_rx_parse_options - Parse CCID-specific options sent by the sender164164- * Arguments are analogous to ccid_hc_tx_parse_options()165165- */166202static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,167167- u8 pkt, u8 opt, u8 *val, u8 len)203203+ unsigned char option,204204+ unsigned char len, u16 idx,205205+ unsigned char* value)168206{169169- if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL)170170- return 0;171171- return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);207207+ int rc = 0;208208+ if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL)209209+ rc = ccid->ccid_ops->ccid_hc_rx_parse_options(sk, option, len, idx, value);210210+ return rc;172211}173212174213static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
+6-24
net/dccp/ccids/Kconfig
···11menu "DCCP CCIDs Configuration (EXPERIMENTAL)"22+ depends on EXPERIMENTAL2334config IP_DCCP_CCID244- tristate "CCID2 (TCP-Like)"55+ tristate "CCID2 (TCP-Like) (EXPERIMENTAL)"56 def_tristate IP_DCCP77+ select IP_DCCP_ACKVEC68 ---help---79 CCID 2, TCP-like Congestion Control, denotes Additive Increase,810 Multiplicative Decrease (AIMD) congestion control with behavior···3634 If in doubt, say N.37353836config IP_DCCP_CCID33939- tristate "CCID3 (TCP-Friendly)"3737+ tristate "CCID3 (TCP-Friendly) (EXPERIMENTAL)"4038 def_tristate IP_DCCP4139 select IP_DCCP_TFRC_LIB4240 ---help---···64626563 If in doubt, say M.66646767-if IP_DCCP_CCID36865config IP_DCCP_CCID3_DEBUG6966 bool "CCID3 debugging messages"6767+ depends on IP_DCCP_CCID37068 ---help---7169 Enable CCID3-specific debugging messages.7270···76747775 If in doubt, say N.78767979-choice8080- prompt "Select method for measuring the packet size s"8181- default IP_DCCP_CCID3_MEASURE_S_AS_MPS8282-8383-config IP_DCCP_CCID3_MEASURE_S_AS_MPS8484- bool "Always use MPS in place of s"8585- ---help---8686- This use is recommended as it is consistent with the initialisation8787- of X and suggested when s varies (rfc3448bis, (1) in section 4.1).8888-config IP_DCCP_CCID3_MEASURE_S_AS_AVG8989- bool "Use moving average"9090- ---help---9191- An alternative way of tracking s, also supported by rfc3448bis.9292- This used to be the default for CCID-3 in previous kernels.9393-config IP_DCCP_CCID3_MEASURE_S_AS_MAX9494- bool "Track the maximum payload length"9595- ---help---9696- An experimental method based on tracking the maximum packet size.9797-endchoice9898-9977config IP_DCCP_CCID3_RTO10078 int "Use higher bound for nofeedback timer"10179 default 1008080+ depends on IP_DCCP_CCID3 && EXPERIMENTAL10281 ---help---10382 Use higher lower bound for nofeedback timer expiration.10483···106123 The purpose of the nofeedback timer is to slow DCCP down when there107124 is serious network congestion: experimenting with larger values should108125 therefore not be performed on WANs.109109-endif # IP_DCCP_CCID3110126111127config IP_DCCP_TFRC_LIB112128 tristate
+369-247
net/dccp/ccids/ccid2.c
···2525/*2626 * This implementation should follow RFC 43412727 */2828-#include "../feat.h"2828+2929#include "../ccid.h"3030#include "../dccp.h"3131#include "ccid2.h"···3434#ifdef CONFIG_IP_DCCP_CCID2_DEBUG3535static int ccid2_debug;3636#define ccid2_pr_debug(format, a...) DCCP_PR_DEBUG(ccid2_debug, format, ##a)3737+3838+static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)3939+{4040+ int len = 0;4141+ int pipe = 0;4242+ struct ccid2_seq *seqp = hctx->ccid2hctx_seqh;4343+4444+ /* there is data in the chain */4545+ if (seqp != hctx->ccid2hctx_seqt) {4646+ seqp = seqp->ccid2s_prev;4747+ len++;4848+ if (!seqp->ccid2s_acked)4949+ pipe++;5050+5151+ while (seqp != hctx->ccid2hctx_seqt) {5252+ struct ccid2_seq *prev = seqp->ccid2s_prev;5353+5454+ len++;5555+ if (!prev->ccid2s_acked)5656+ pipe++;5757+5858+ /* packets are sent sequentially */5959+ BUG_ON(dccp_delta_seqno(seqp->ccid2s_seq,6060+ prev->ccid2s_seq ) >= 0);6161+ BUG_ON(time_before(seqp->ccid2s_sent,6262+ prev->ccid2s_sent));6363+6464+ seqp = prev;6565+ }6666+ }6767+6868+ BUG_ON(pipe != hctx->ccid2hctx_pipe);6969+ ccid2_pr_debug("len of chain=%d\n", len);7070+7171+ do {7272+ seqp = seqp->ccid2s_prev;7373+ len++;7474+ } while (seqp != hctx->ccid2hctx_seqh);7575+7676+ ccid2_pr_debug("total len=%d\n", len);7777+ BUG_ON(len != hctx->ccid2hctx_seqbufc * CCID2_SEQBUF_LEN);7878+}3779#else3880#define ccid2_pr_debug(format, a...)8181+#define ccid2_hc_tx_check_sanity(hctx)3982#endif40834184static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx)···8744 int i;88458946 /* check if we have space to preserve the pointer to the buffer */9090- if (hctx->seqbufc >= sizeof(hctx->seqbuf) / sizeof(struct ccid2_seq *))4747+ if (hctx->ccid2hctx_seqbufc >= (sizeof(hctx->ccid2hctx_seqbuf) /4848+ sizeof(struct ccid2_seq*)))9149 return -ENOMEM;92509351 /* allocate buffer and initialize linked list */···10460 seqp->ccid2s_prev = &seqp[CCID2_SEQBUF_LEN - 1];1056110662 /* This is the first allocation. Initiate the head and tail. */107107- if (hctx->seqbufc == 0)108108- hctx->seqh = hctx->seqt = seqp;6363+ if (hctx->ccid2hctx_seqbufc == 0)6464+ hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqt = seqp;10965 else {11066 /* link the existing list with the one we just created */111111- hctx->seqh->ccid2s_next = seqp;112112- seqp->ccid2s_prev = hctx->seqh;6767+ hctx->ccid2hctx_seqh->ccid2s_next = seqp;6868+ seqp->ccid2s_prev = hctx->ccid2hctx_seqh;11369114114- hctx->seqt->ccid2s_prev = &seqp[CCID2_SEQBUF_LEN - 1];115115- seqp[CCID2_SEQBUF_LEN - 1].ccid2s_next = hctx->seqt;7070+ hctx->ccid2hctx_seqt->ccid2s_prev = &seqp[CCID2_SEQBUF_LEN - 1];7171+ seqp[CCID2_SEQBUF_LEN - 1].ccid2s_next = hctx->ccid2hctx_seqt;11672 }1177311874 /* store the original pointer to the buffer so we can free it */119119- hctx->seqbuf[hctx->seqbufc] = seqp;120120- hctx->seqbufc++;7575+ hctx->ccid2hctx_seqbuf[hctx->ccid2hctx_seqbufc] = seqp;7676+ hctx->ccid2hctx_seqbufc++;1217712278 return 0;12379}1248012581static int ccid2_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)12682{127127- if (ccid2_cwnd_network_limited(ccid2_hc_tx_sk(sk)))128128- return CCID_PACKET_WILL_DEQUEUE_LATER;129129- return CCID_PACKET_SEND_AT_ONCE;8383+ struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);8484+8585+ if (hctx->ccid2hctx_pipe < hctx->ccid2hctx_cwnd)8686+ return 0;8787+8888+ return 1; /* XXX CCID should dequeue when ready instead of polling */13089}1319013291static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val)13392{13493 struct dccp_sock *dp = dccp_sk(sk);135135- u32 max_ratio = DIV_ROUND_UP(ccid2_hc_tx_sk(sk)->cwnd, 2);9494+ u32 max_ratio = DIV_ROUND_UP(ccid2_hc_tx_sk(sk)->ccid2hctx_cwnd, 2);1369513796 /*13897 * Ensure that Ack Ratio does not exceed ceil(cwnd/2), which is (2) from···147100 DCCP_WARN("Limiting Ack Ratio (%u) to %u\n", val, max_ratio);148101 val = max_ratio;149102 }150150- if (val > DCCPF_ACK_RATIO_MAX)151151- val = DCCPF_ACK_RATIO_MAX;103103+ if (val > 0xFFFF) /* RFC 4340, 11.3 */104104+ val = 0xFFFF;152105153106 if (val == dp->dccps_l_ack_ratio)154107 return;···157110 dp->dccps_l_ack_ratio = val;158111}159112113113+static void ccid2_change_srtt(struct ccid2_hc_tx_sock *hctx, long val)114114+{115115+ ccid2_pr_debug("change SRTT to %ld\n", val);116116+ hctx->ccid2hctx_srtt = val;117117+}118118+119119+static void ccid2_start_rto_timer(struct sock *sk);120120+160121static void ccid2_hc_tx_rto_expire(unsigned long data)161122{162123 struct sock *sk = (struct sock *)data;163124 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);164164- const bool sender_was_blocked = ccid2_cwnd_network_limited(hctx);125125+ long s;165126166127 bh_lock_sock(sk);167128 if (sock_owned_by_user(sk)) {168168- sk_reset_timer(sk, &hctx->rtotimer, jiffies + HZ / 5);129129+ sk_reset_timer(sk, &hctx->ccid2hctx_rtotimer,130130+ jiffies + HZ / 5);169131 goto out;170132 }171133172134 ccid2_pr_debug("RTO_EXPIRE\n");173135136136+ ccid2_hc_tx_check_sanity(hctx);137137+174138 /* back-off timer */175175- hctx->rto <<= 1;176176- if (hctx->rto > DCCP_RTO_MAX)177177- hctx->rto = DCCP_RTO_MAX;139139+ hctx->ccid2hctx_rto <<= 1;140140+141141+ s = hctx->ccid2hctx_rto / HZ;142142+ if (s > 60)143143+ hctx->ccid2hctx_rto = 60 * HZ;144144+145145+ ccid2_start_rto_timer(sk);178146179147 /* adjust pipe, cwnd etc */180180- hctx->ssthresh = hctx->cwnd / 2;181181- if (hctx->ssthresh < 2)182182- hctx->ssthresh = 2;183183- hctx->cwnd = 1;184184- hctx->pipe = 0;148148+ hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd / 2;149149+ if (hctx->ccid2hctx_ssthresh < 2)150150+ hctx->ccid2hctx_ssthresh = 2;151151+ hctx->ccid2hctx_cwnd = 1;152152+ hctx->ccid2hctx_pipe = 0;185153186154 /* clear state about stuff we sent */187187- hctx->seqt = hctx->seqh;188188- hctx->packets_acked = 0;155155+ hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh;156156+ hctx->ccid2hctx_packets_acked = 0;189157190158 /* clear ack ratio state. */191191- hctx->rpseq = 0;192192- hctx->rpdupack = -1;159159+ hctx->ccid2hctx_rpseq = 0;160160+ hctx->ccid2hctx_rpdupack = -1;193161 ccid2_change_l_ack_ratio(sk, 1);194194-195195- /* if we were blocked before, we may now send cwnd=1 packet */196196- if (sender_was_blocked)197197- tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet);198198- /* restart backed-off timer */199199- sk_reset_timer(sk, &hctx->rtotimer, jiffies + hctx->rto);162162+ ccid2_hc_tx_check_sanity(hctx);200163out:201164 bh_unlock_sock(sk);202165 sock_put(sk);203166}204167205205-static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)168168+static void ccid2_start_rto_timer(struct sock *sk)169169+{170170+ struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);171171+172172+ ccid2_pr_debug("setting RTO timeout=%ld\n", hctx->ccid2hctx_rto);173173+174174+ BUG_ON(timer_pending(&hctx->ccid2hctx_rtotimer));175175+ sk_reset_timer(sk, &hctx->ccid2hctx_rtotimer,176176+ jiffies + hctx->ccid2hctx_rto);177177+}178178+179179+static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len)206180{207181 struct dccp_sock *dp = dccp_sk(sk);208182 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);209183 struct ccid2_seq *next;210184211211- hctx->pipe++;185185+ hctx->ccid2hctx_pipe++;212186213213- hctx->seqh->ccid2s_seq = dp->dccps_gss;214214- hctx->seqh->ccid2s_acked = 0;215215- hctx->seqh->ccid2s_sent = jiffies;187187+ hctx->ccid2hctx_seqh->ccid2s_seq = dp->dccps_gss;188188+ hctx->ccid2hctx_seqh->ccid2s_acked = 0;189189+ hctx->ccid2hctx_seqh->ccid2s_sent = jiffies;216190217217- next = hctx->seqh->ccid2s_next;191191+ next = hctx->ccid2hctx_seqh->ccid2s_next;218192 /* check if we need to alloc more space */219219- if (next == hctx->seqt) {193193+ if (next == hctx->ccid2hctx_seqt) {220194 if (ccid2_hc_tx_alloc_seq(hctx)) {221195 DCCP_CRIT("packet history - out of memory!");222196 /* FIXME: find a more graceful way to bail out */223197 return;224198 }225225- next = hctx->seqh->ccid2s_next;226226- BUG_ON(next == hctx->seqt);199199+ next = hctx->ccid2hctx_seqh->ccid2s_next;200200+ BUG_ON(next == hctx->ccid2hctx_seqt);227201 }228228- hctx->seqh = next;202202+ hctx->ccid2hctx_seqh = next;229203230230- ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->cwnd, hctx->pipe);204204+ ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd,205205+ hctx->ccid2hctx_pipe);231206232207 /*233208 * FIXME: The code below is broken and the variables have been removed···272203 */273204#if 0274205 /* Ack Ratio. Need to maintain a concept of how many windows we sent */275275- hctx->arsent++;206206+ hctx->ccid2hctx_arsent++;276207 /* We had an ack loss in this window... */277277- if (hctx->ackloss) {278278- if (hctx->arsent >= hctx->cwnd) {279279- hctx->arsent = 0;280280- hctx->ackloss = 0;208208+ if (hctx->ccid2hctx_ackloss) {209209+ if (hctx->ccid2hctx_arsent >= hctx->ccid2hctx_cwnd) {210210+ hctx->ccid2hctx_arsent = 0;211211+ hctx->ccid2hctx_ackloss = 0;281212 }282213 } else {283214 /* No acks lost up to now... */···287218 int denom = dp->dccps_l_ack_ratio * dp->dccps_l_ack_ratio -288219 dp->dccps_l_ack_ratio;289220290290- denom = hctx->cwnd * hctx->cwnd / denom;221221+ denom = hctx->ccid2hctx_cwnd * hctx->ccid2hctx_cwnd / denom;291222292292- if (hctx->arsent >= denom) {223223+ if (hctx->ccid2hctx_arsent >= denom) {293224 ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio - 1);294294- hctx->arsent = 0;225225+ hctx->ccid2hctx_arsent = 0;295226 }296227 } else {297228 /* we can't increase ack ratio further [1] */298298- hctx->arsent = 0; /* or maybe set it to cwnd*/229229+ hctx->ccid2hctx_arsent = 0; /* or maybe set it to cwnd*/299230 }300231 }301232#endif302233303234 /* setup RTO timer */304304- if (!timer_pending(&hctx->rtotimer))305305- sk_reset_timer(sk, &hctx->rtotimer, jiffies + hctx->rto);235235+ if (!timer_pending(&hctx->ccid2hctx_rtotimer))236236+ ccid2_start_rto_timer(sk);306237307238#ifdef CONFIG_IP_DCCP_CCID2_DEBUG308239 do {309309- struct ccid2_seq *seqp = hctx->seqt;240240+ struct ccid2_seq *seqp = hctx->ccid2hctx_seqt;310241311311- while (seqp != hctx->seqh) {242242+ while (seqp != hctx->ccid2hctx_seqh) {312243 ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n",313244 (unsigned long long)seqp->ccid2s_seq,314245 seqp->ccid2s_acked, seqp->ccid2s_sent);···316247 }317248 } while (0);318249 ccid2_pr_debug("=========\n");250250+ ccid2_hc_tx_check_sanity(hctx);319251#endif320252}321253322322-/**323323- * ccid2_rtt_estimator - Sample RTT and compute RTO using RFC2988 algorithm324324- * This code is almost identical with TCP's tcp_rtt_estimator(), since325325- * - it has a higher sampling frequency (recommended by RFC 1323),326326- * - the RTO does not collapse into RTT due to RTTVAR going towards zero,327327- * - it is simple (cf. more complex proposals such as Eifel timer or research328328- * which suggests that the gain should be set according to window size),329329- * - in tests it was found to work well with CCID2 [gerrit].254254+/* XXX Lame code duplication!255255+ * returns -1 if none was found.256256+ * else returns the next offset to use in the function call.330257 */331331-static void ccid2_rtt_estimator(struct sock *sk, const long mrtt)258258+static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset,259259+ unsigned char **vec, unsigned char *veclen)332260{333333- struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);334334- long m = mrtt ? : 1;261261+ const struct dccp_hdr *dh = dccp_hdr(skb);262262+ unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);263263+ unsigned char *opt_ptr;264264+ const unsigned char *opt_end = (unsigned char *)dh +265265+ (dh->dccph_doff * 4);266266+ unsigned char opt, len;267267+ unsigned char *value;335268336336- if (hctx->srtt == 0) {337337- /* First measurement m */338338- hctx->srtt = m << 3;339339- hctx->mdev = m << 1;269269+ BUG_ON(offset < 0);270270+ options += offset;271271+ opt_ptr = options;272272+ if (opt_ptr >= opt_end)273273+ return -1;340274341341- hctx->mdev_max = max(TCP_RTO_MIN, hctx->mdev);342342- hctx->rttvar = hctx->mdev_max;343343- hctx->rtt_seq = dccp_sk(sk)->dccps_gss;344344- } else {345345- /* Update scaled SRTT as SRTT += 1/8 * (m - SRTT) */346346- m -= (hctx->srtt >> 3);347347- hctx->srtt += m;275275+ while (opt_ptr != opt_end) {276276+ opt = *opt_ptr++;277277+ len = 0;278278+ value = NULL;348279349349- /* Similarly, update scaled mdev with regard to |m| */350350- if (m < 0) {351351- m = -m;352352- m -= (hctx->mdev >> 2);280280+ /* Check if this isn't a single byte option */281281+ if (opt > DCCPO_MAX_RESERVED) {282282+ if (opt_ptr == opt_end)283283+ goto out_invalid_option;284284+285285+ len = *opt_ptr++;286286+ if (len < 3)287287+ goto out_invalid_option;353288 /*354354- * This neutralises RTO increase when RTT < SRTT - mdev355355- * (see P. Sarolahti, A. Kuznetsov,"Congestion Control356356- * in Linux TCP", USENIX 2002, pp. 49-62).289289+ * Remove the type and len fields, leaving290290+ * just the value size357291 */358358- if (m > 0)359359- m >>= 3;360360- } else {361361- m -= (hctx->mdev >> 2);362362- }363363- hctx->mdev += m;292292+ len -= 2;293293+ value = opt_ptr;294294+ opt_ptr += len;364295365365- if (hctx->mdev > hctx->mdev_max) {366366- hctx->mdev_max = hctx->mdev;367367- if (hctx->mdev_max > hctx->rttvar)368368- hctx->rttvar = hctx->mdev_max;296296+ if (opt_ptr > opt_end)297297+ goto out_invalid_option;369298 }370299371371- /*372372- * Decay RTTVAR at most once per flight, exploiting that373373- * 1) pipe <= cwnd <= Sequence_Window = W (RFC 4340, 7.5.2)374374- * 2) AWL = GSS-W+1 <= GAR <= GSS (RFC 4340, 7.5.1)375375- * GAR is a useful bound for FlightSize = pipe, AWL is probably376376- * too low as it over-estimates pipe.377377- */378378- if (after48(dccp_sk(sk)->dccps_gar, hctx->rtt_seq)) {379379- if (hctx->mdev_max < hctx->rttvar)380380- hctx->rttvar -= (hctx->rttvar -381381- hctx->mdev_max) >> 2;382382- hctx->rtt_seq = dccp_sk(sk)->dccps_gss;383383- hctx->mdev_max = TCP_RTO_MIN;300300+ switch (opt) {301301+ case DCCPO_ACK_VECTOR_0:302302+ case DCCPO_ACK_VECTOR_1:303303+ *vec = value;304304+ *veclen = len;305305+ return offset + (opt_ptr - options);384306 }385307 }386308387387- /*388388- * Set RTO from SRTT and RTTVAR389389- * Clock granularity is ignored since the minimum error for RTTVAR is390390- * clamped to 50msec (corresponding to HZ=20). This leads to a minimum391391- * RTO of 200msec. This agrees with TCP and RFC 4341, 5.: "Because DCCP392392- * does not retransmit data, DCCP does not require TCP's recommended393393- * minimum timeout of one second".394394- */395395- hctx->rto = (hctx->srtt >> 3) + hctx->rttvar;309309+ return -1;396310397397- if (hctx->rto > DCCP_RTO_MAX)398398- hctx->rto = DCCP_RTO_MAX;311311+out_invalid_option:312312+ DCCP_BUG("Invalid option - this should not happen (previous parsing)!");313313+ return -1;399314}400315401401-static void ccid2_new_ack(struct sock *sk, struct ccid2_seq *seqp,402402- unsigned int *maxincr)316316+static void ccid2_hc_tx_kill_rto_timer(struct sock *sk)403317{404318 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);405319406406- if (hctx->cwnd < hctx->ssthresh) {407407- if (*maxincr > 0 && ++hctx->packets_acked == 2) {408408- hctx->cwnd += 1;409409- *maxincr -= 1;410410- hctx->packets_acked = 0;320320+ sk_stop_timer(sk, &hctx->ccid2hctx_rtotimer);321321+ ccid2_pr_debug("deleted RTO timer\n");322322+}323323+324324+static inline void ccid2_new_ack(struct sock *sk,325325+ struct ccid2_seq *seqp,326326+ unsigned int *maxincr)327327+{328328+ struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);329329+330330+ if (hctx->ccid2hctx_cwnd < hctx->ccid2hctx_ssthresh) {331331+ if (*maxincr > 0 && ++hctx->ccid2hctx_packets_acked == 2) {332332+ hctx->ccid2hctx_cwnd += 1;333333+ *maxincr -= 1;334334+ hctx->ccid2hctx_packets_acked = 0;411335 }412412- } else if (++hctx->packets_acked >= hctx->cwnd) {413413- hctx->cwnd += 1;414414- hctx->packets_acked = 0;336336+ } else if (++hctx->ccid2hctx_packets_acked >= hctx->ccid2hctx_cwnd) {337337+ hctx->ccid2hctx_cwnd += 1;338338+ hctx->ccid2hctx_packets_acked = 0;415339 }416416- /*417417- * FIXME: RTT is sampled several times per acknowledgment (for each418418- * entry in the Ack Vector), instead of once per Ack (as in TCP SACK).419419- * This causes the RTT to be over-estimated, since the older entries420420- * in the Ack Vector have earlier sending times.421421- * The cleanest solution is to not use the ccid2s_sent field at all422422- * and instead use DCCP timestamps - need to be resolved at some time.423423- */424424- ccid2_rtt_estimator(sk, jiffies - seqp->ccid2s_sent);340340+341341+ /* update RTO */342342+ if (hctx->ccid2hctx_srtt == -1 ||343343+ time_after(jiffies, hctx->ccid2hctx_lastrtt + hctx->ccid2hctx_srtt)) {344344+ unsigned long r = (long)jiffies - (long)seqp->ccid2s_sent;345345+ int s;346346+347347+ /* first measurement */348348+ if (hctx->ccid2hctx_srtt == -1) {349349+ ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",350350+ r, jiffies,351351+ (unsigned long long)seqp->ccid2s_seq);352352+ ccid2_change_srtt(hctx, r);353353+ hctx->ccid2hctx_rttvar = r >> 1;354354+ } else {355355+ /* RTTVAR */356356+ long tmp = hctx->ccid2hctx_srtt - r;357357+ long srtt;358358+359359+ if (tmp < 0)360360+ tmp *= -1;361361+362362+ tmp >>= 2;363363+ hctx->ccid2hctx_rttvar *= 3;364364+ hctx->ccid2hctx_rttvar >>= 2;365365+ hctx->ccid2hctx_rttvar += tmp;366366+367367+ /* SRTT */368368+ srtt = hctx->ccid2hctx_srtt;369369+ srtt *= 7;370370+ srtt >>= 3;371371+ tmp = r >> 3;372372+ srtt += tmp;373373+ ccid2_change_srtt(hctx, srtt);374374+ }375375+ s = hctx->ccid2hctx_rttvar << 2;376376+ /* clock granularity is 1 when based on jiffies */377377+ if (!s)378378+ s = 1;379379+ hctx->ccid2hctx_rto = hctx->ccid2hctx_srtt + s;380380+381381+ /* must be at least a second */382382+ s = hctx->ccid2hctx_rto / HZ;383383+ /* DCCP doesn't require this [but I like it cuz my code sux] */384384+#if 1385385+ if (s < 1)386386+ hctx->ccid2hctx_rto = HZ;387387+#endif388388+ /* max 60 seconds */389389+ if (s > 60)390390+ hctx->ccid2hctx_rto = HZ * 60;391391+392392+ hctx->ccid2hctx_lastrtt = jiffies;393393+394394+ ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n",395395+ hctx->ccid2hctx_srtt, hctx->ccid2hctx_rttvar,396396+ hctx->ccid2hctx_rto, HZ, r);397397+ }398398+399399+ /* we got a new ack, so re-start RTO timer */400400+ ccid2_hc_tx_kill_rto_timer(sk);401401+ ccid2_start_rto_timer(sk);402402+}403403+404404+static void ccid2_hc_tx_dec_pipe(struct sock *sk)405405+{406406+ struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);407407+408408+ if (hctx->ccid2hctx_pipe == 0)409409+ DCCP_BUG("pipe == 0");410410+ else411411+ hctx->ccid2hctx_pipe--;412412+413413+ if (hctx->ccid2hctx_pipe == 0)414414+ ccid2_hc_tx_kill_rto_timer(sk);425415}426416427417static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp)428418{429419 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);430420431431- if (time_before(seqp->ccid2s_sent, hctx->last_cong)) {421421+ if (time_before(seqp->ccid2s_sent, hctx->ccid2hctx_last_cong)) {432422 ccid2_pr_debug("Multiple losses in an RTT---treating as one\n");433423 return;434424 }435425436436- hctx->last_cong = jiffies;426426+ hctx->ccid2hctx_last_cong = jiffies;437427438438- hctx->cwnd = hctx->cwnd / 2 ? : 1U;439439- hctx->ssthresh = max(hctx->cwnd, 2U);428428+ hctx->ccid2hctx_cwnd = hctx->ccid2hctx_cwnd / 2 ? : 1U;429429+ hctx->ccid2hctx_ssthresh = max(hctx->ccid2hctx_cwnd, 2U);440430441431 /* Avoid spurious timeouts resulting from Ack Ratio > cwnd */442442- if (dccp_sk(sk)->dccps_l_ack_ratio > hctx->cwnd)443443- ccid2_change_l_ack_ratio(sk, hctx->cwnd);444444-}445445-446446-static int ccid2_hc_tx_parse_options(struct sock *sk, u8 packet_type,447447- u8 option, u8 *optval, u8 optlen)448448-{449449- struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);450450-451451- switch (option) {452452- case DCCPO_ACK_VECTOR_0:453453- case DCCPO_ACK_VECTOR_1:454454- return dccp_ackvec_parsed_add(&hctx->av_chunks, optval, optlen,455455- option - DCCPO_ACK_VECTOR_0);456456- }457457- return 0;432432+ if (dccp_sk(sk)->dccps_l_ack_ratio > hctx->ccid2hctx_cwnd)433433+ ccid2_change_l_ack_ratio(sk, hctx->ccid2hctx_cwnd);458434}459435460436static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)461437{462438 struct dccp_sock *dp = dccp_sk(sk);463439 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);464464- const bool sender_was_blocked = ccid2_cwnd_network_limited(hctx);465465- struct dccp_ackvec_parsed *avp;466440 u64 ackno, seqno;467441 struct ccid2_seq *seqp;442442+ unsigned char *vector;443443+ unsigned char veclen;444444+ int offset = 0;468445 int done = 0;469446 unsigned int maxincr = 0;470447448448+ ccid2_hc_tx_check_sanity(hctx);471449 /* check reverse path congestion */472450 seqno = DCCP_SKB_CB(skb)->dccpd_seq;473451···523407 * -sorbo.524408 */525409 /* need to bootstrap */526526- if (hctx->rpdupack == -1) {527527- hctx->rpdupack = 0;528528- hctx->rpseq = seqno;410410+ if (hctx->ccid2hctx_rpdupack == -1) {411411+ hctx->ccid2hctx_rpdupack = 0;412412+ hctx->ccid2hctx_rpseq = seqno;529413 } else {530414 /* check if packet is consecutive */531531- if (dccp_delta_seqno(hctx->rpseq, seqno) == 1)532532- hctx->rpseq = seqno;415415+ if (dccp_delta_seqno(hctx->ccid2hctx_rpseq, seqno) == 1)416416+ hctx->ccid2hctx_rpseq = seqno;533417 /* it's a later packet */534534- else if (after48(seqno, hctx->rpseq)) {535535- hctx->rpdupack++;418418+ else if (after48(seqno, hctx->ccid2hctx_rpseq)) {419419+ hctx->ccid2hctx_rpdupack++;536420537421 /* check if we got enough dupacks */538538- if (hctx->rpdupack >= NUMDUPACK) {539539- hctx->rpdupack = -1; /* XXX lame */540540- hctx->rpseq = 0;422422+ if (hctx->ccid2hctx_rpdupack >= NUMDUPACK) {423423+ hctx->ccid2hctx_rpdupack = -1; /* XXX lame */424424+ hctx->ccid2hctx_rpseq = 0;541425542426 ccid2_change_l_ack_ratio(sk, 2 * dp->dccps_l_ack_ratio);543427 }···545429 }546430547431 /* check forward path congestion */548548- if (dccp_packet_without_ack(skb))432432+ /* still didn't send out new data packets */433433+ if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt)549434 return;550435551551- /* still didn't send out new data packets */552552- if (hctx->seqh == hctx->seqt)553553- goto done;436436+ switch (DCCP_SKB_CB(skb)->dccpd_type) {437437+ case DCCP_PKT_ACK:438438+ case DCCP_PKT_DATAACK:439439+ break;440440+ default:441441+ return;442442+ }554443555444 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;556556- if (after48(ackno, hctx->high_ack))557557- hctx->high_ack = ackno;445445+ if (after48(ackno, hctx->ccid2hctx_high_ack))446446+ hctx->ccid2hctx_high_ack = ackno;558447559559- seqp = hctx->seqt;448448+ seqp = hctx->ccid2hctx_seqt;560449 while (before48(seqp->ccid2s_seq, ackno)) {561450 seqp = seqp->ccid2s_next;562562- if (seqp == hctx->seqh) {563563- seqp = hctx->seqh->ccid2s_prev;451451+ if (seqp == hctx->ccid2hctx_seqh) {452452+ seqp = hctx->ccid2hctx_seqh->ccid2s_prev;564453 break;565454 }566455 }···575454 * packets per acknowledgement. Rounding up avoids that cwnd is not576455 * advanced when Ack Ratio is 1 and gives a slight edge otherwise.577456 */578578- if (hctx->cwnd < hctx->ssthresh)457457+ if (hctx->ccid2hctx_cwnd < hctx->ccid2hctx_ssthresh)579458 maxincr = DIV_ROUND_UP(dp->dccps_l_ack_ratio, 2);580459581460 /* go through all ack vectors */582582- list_for_each_entry(avp, &hctx->av_chunks, node) {461461+ while ((offset = ccid2_ackvector(sk, skb, offset,462462+ &vector, &veclen)) != -1) {583463 /* go through this ack vector */584584- for (; avp->len--; avp->vec++) {585585- u64 ackno_end_rl = SUB48(ackno,586586- dccp_ackvec_runlen(avp->vec));464464+ while (veclen--) {465465+ const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;466466+ u64 ackno_end_rl = SUB48(ackno, rl);587467588588- ccid2_pr_debug("ackvec %llu |%u,%u|\n",468468+ ccid2_pr_debug("ackvec start:%llu end:%llu\n",589469 (unsigned long long)ackno,590590- dccp_ackvec_state(avp->vec) >> 6,591591- dccp_ackvec_runlen(avp->vec));470470+ (unsigned long long)ackno_end_rl);592471 /* if the seqno we are analyzing is larger than the593472 * current ackno, then move towards the tail of our594473 * seqnos.595474 */596475 while (after48(seqp->ccid2s_seq, ackno)) {597597- if (seqp == hctx->seqt) {476476+ if (seqp == hctx->ccid2hctx_seqt) {598477 done = 1;599478 break;600479 }···607486 * run length608487 */609488 while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) {610610- const u8 state = dccp_ackvec_state(avp->vec);489489+ const u8 state = *vector &490490+ DCCP_ACKVEC_STATE_MASK;611491612492 /* new packet received or marked */613613- if (state != DCCPAV_NOT_RECEIVED &&493493+ if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED &&614494 !seqp->ccid2s_acked) {615615- if (state == DCCPAV_ECN_MARKED)495495+ if (state ==496496+ DCCP_ACKVEC_STATE_ECN_MARKED) {616497 ccid2_congestion_event(sk,617498 seqp);618618- else499499+ } else619500 ccid2_new_ack(sk, seqp,620501 &maxincr);621502622503 seqp->ccid2s_acked = 1;623504 ccid2_pr_debug("Got ack for %llu\n",624505 (unsigned long long)seqp->ccid2s_seq);625625- hctx->pipe--;506506+ ccid2_hc_tx_dec_pipe(sk);626507 }627627- if (seqp == hctx->seqt) {508508+ if (seqp == hctx->ccid2hctx_seqt) {628509 done = 1;629510 break;630511 }···636513 break;637514638515 ackno = SUB48(ackno_end_rl, 1);516516+ vector++;639517 }640518 if (done)641519 break;···645521 /* The state about what is acked should be correct now646522 * Check for NUMDUPACK647523 */648648- seqp = hctx->seqt;649649- while (before48(seqp->ccid2s_seq, hctx->high_ack)) {524524+ seqp = hctx->ccid2hctx_seqt;525525+ while (before48(seqp->ccid2s_seq, hctx->ccid2hctx_high_ack)) {650526 seqp = seqp->ccid2s_next;651651- if (seqp == hctx->seqh) {652652- seqp = hctx->seqh->ccid2s_prev;527527+ if (seqp == hctx->ccid2hctx_seqh) {528528+ seqp = hctx->ccid2hctx_seqh->ccid2s_prev;653529 break;654530 }655531 }···660536 if (done == NUMDUPACK)661537 break;662538 }663663- if (seqp == hctx->seqt)539539+ if (seqp == hctx->ccid2hctx_seqt)664540 break;665541 seqp = seqp->ccid2s_prev;666542 }···681557 * one ack vector.682558 */683559 ccid2_congestion_event(sk, seqp);684684- hctx->pipe--;560560+ ccid2_hc_tx_dec_pipe(sk);685561 }686686- if (seqp == hctx->seqt)562562+ if (seqp == hctx->ccid2hctx_seqt)687563 break;688564 seqp = seqp->ccid2s_prev;689565 }690566691691- hctx->seqt = last_acked;567567+ hctx->ccid2hctx_seqt = last_acked;692568 }693569694570 /* trim acked packets in tail */695695- while (hctx->seqt != hctx->seqh) {696696- if (!hctx->seqt->ccid2s_acked)571571+ while (hctx->ccid2hctx_seqt != hctx->ccid2hctx_seqh) {572572+ if (!hctx->ccid2hctx_seqt->ccid2s_acked)697573 break;698574699699- hctx->seqt = hctx->seqt->ccid2s_next;575575+ hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqt->ccid2s_next;700576 }701577702702- /* restart RTO timer if not all outstanding data has been acked */703703- if (hctx->pipe == 0)704704- sk_stop_timer(sk, &hctx->rtotimer);705705- else706706- sk_reset_timer(sk, &hctx->rtotimer, jiffies + hctx->rto);707707-done:708708- /* check if incoming Acks allow pending packets to be sent */709709- if (sender_was_blocked && !ccid2_cwnd_network_limited(hctx))710710- tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet);711711- dccp_ackvec_parsed_cleanup(&hctx->av_chunks);578578+ ccid2_hc_tx_check_sanity(hctx);712579}713580714581static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)···709594 u32 max_ratio;710595711596 /* RFC 4341, 5: initialise ssthresh to arbitrarily high (max) value */712712- hctx->ssthresh = ~0U;597597+ hctx->ccid2hctx_ssthresh = ~0U;713598714714- /* Use larger initial windows (RFC 3390, rfc2581bis) */715715- hctx->cwnd = rfc3390_bytes_to_packets(dp->dccps_mss_cache);599599+ /*600600+ * RFC 4341, 5: "The cwnd parameter is initialized to at most four601601+ * packets for new connections, following the rules from [RFC3390]".602602+ * We need to convert the bytes of RFC3390 into the packets of RFC 4341.603603+ */604604+ hctx->ccid2hctx_cwnd = clamp(4380U / dp->dccps_mss_cache, 2U, 4U);716605717606 /* Make sure that Ack Ratio is enabled and within bounds. */718718- max_ratio = DIV_ROUND_UP(hctx->cwnd, 2);607607+ max_ratio = DIV_ROUND_UP(hctx->ccid2hctx_cwnd, 2);719608 if (dp->dccps_l_ack_ratio == 0 || dp->dccps_l_ack_ratio > max_ratio)720609 dp->dccps_l_ack_ratio = max_ratio;721610···727608 if (ccid2_hc_tx_alloc_seq(hctx))728609 return -ENOMEM;729610730730- hctx->rto = DCCP_TIMEOUT_INIT;731731- hctx->rpdupack = -1;732732- hctx->last_cong = jiffies;733733- setup_timer(&hctx->rtotimer, ccid2_hc_tx_rto_expire, (unsigned long)sk);734734- INIT_LIST_HEAD(&hctx->av_chunks);611611+ hctx->ccid2hctx_rto = 3 * HZ;612612+ ccid2_change_srtt(hctx, -1);613613+ hctx->ccid2hctx_rttvar = -1;614614+ hctx->ccid2hctx_rpdupack = -1;615615+ hctx->ccid2hctx_last_cong = jiffies;616616+ setup_timer(&hctx->ccid2hctx_rtotimer, ccid2_hc_tx_rto_expire,617617+ (unsigned long)sk);618618+619619+ ccid2_hc_tx_check_sanity(hctx);735620 return 0;736621}737622···744621 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);745622 int i;746623747747- sk_stop_timer(sk, &hctx->rtotimer);624624+ ccid2_hc_tx_kill_rto_timer(sk);748625749749- for (i = 0; i < hctx->seqbufc; i++)750750- kfree(hctx->seqbuf[i]);751751- hctx->seqbufc = 0;626626+ for (i = 0; i < hctx->ccid2hctx_seqbufc; i++)627627+ kfree(hctx->ccid2hctx_seqbuf[i]);628628+ hctx->ccid2hctx_seqbufc = 0;752629}753630754631static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)···759636 switch (DCCP_SKB_CB(skb)->dccpd_type) {760637 case DCCP_PKT_DATA:761638 case DCCP_PKT_DATAACK:762762- hcrx->data++;763763- if (hcrx->data >= dp->dccps_r_ack_ratio) {639639+ hcrx->ccid2hcrx_data++;640640+ if (hcrx->ccid2hcrx_data >= dp->dccps_r_ack_ratio) {764641 dccp_send_ack(sk);765765- hcrx->data = 0;642642+ hcrx->ccid2hcrx_data = 0;766643 }767644 break;768645 }769646}770647771648static struct ccid_operations ccid2 = {772772- .ccid_id = DCCPC_CCID2,773773- .ccid_name = "TCP-like",774774- .ccid_owner = THIS_MODULE,775775- .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock),776776- .ccid_hc_tx_init = ccid2_hc_tx_init,777777- .ccid_hc_tx_exit = ccid2_hc_tx_exit,778778- .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet,779779- .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent,780780- .ccid_hc_tx_parse_options = ccid2_hc_tx_parse_options,781781- .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv,782782- .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock),783783- .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv,649649+ .ccid_id = DCCPC_CCID2,650650+ .ccid_name = "TCP-like",651651+ .ccid_owner = THIS_MODULE,652652+ .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock),653653+ .ccid_hc_tx_init = ccid2_hc_tx_init,654654+ .ccid_hc_tx_exit = ccid2_hc_tx_exit,655655+ .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet,656656+ .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent,657657+ .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv,658658+ .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock),659659+ .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv,784660};785661786662#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
+24-39
net/dccp/ccids/ccid2.h
···42424343/** struct ccid2_hc_tx_sock - CCID2 TX half connection4444 *4545- * @{cwnd,ssthresh,pipe}: as per RFC 4341, section 54646- * @packets_acked: Ack counter for deriving cwnd growth (RFC 3465)4747- * @srtt: smoothed RTT estimate, scaled by 2^34848- * @mdev: smoothed RTT variation, scaled by 2^24949- * @mdev_max: maximum of @mdev during one flight5050- * @rttvar: moving average/maximum of @mdev_max5151- * @rto: RTO value deriving from SRTT and RTTVAR (RFC 2988)5252- * @rtt_seq: to decay RTTVAR at most once per flight5353- * @rpseq: last consecutive seqno5454- * @rpdupack: dupacks since rpseq5555- * @av_chunks: list of Ack Vectors received on current skb5656- */4545+ * @ccid2hctx_{cwnd,ssthresh,pipe}: as per RFC 4341, section 54646+ * @ccid2hctx_packets_acked - Ack counter for deriving cwnd growth (RFC 3465)4747+ * @ccid2hctx_lastrtt -time RTT was last measured4848+ * @ccid2hctx_rpseq - last consecutive seqno4949+ * @ccid2hctx_rpdupack - dupacks since rpseq5050+*/5751struct ccid2_hc_tx_sock {5858- u32 cwnd;5959- u32 ssthresh;6060- u32 pipe;6161- u32 packets_acked;6262- struct ccid2_seq *seqbuf[CCID2_SEQBUF_MAX];6363- int seqbufc;6464- struct ccid2_seq *seqh;6565- struct ccid2_seq *seqt;6666- /* RTT measurement: variables/principles are the same as in TCP */6767- u32 srtt,6868- mdev,6969- mdev_max,7070- rttvar,7171- rto;7272- u64 rtt_seq:48;7373- struct timer_list rtotimer;7474- u64 rpseq;7575- int rpdupack;7676- unsigned long last_cong;7777- u64 high_ack;7878- struct list_head av_chunks;5252+ u32 ccid2hctx_cwnd;5353+ u32 ccid2hctx_ssthresh;5454+ u32 ccid2hctx_pipe;5555+ u32 ccid2hctx_packets_acked;5656+ struct ccid2_seq *ccid2hctx_seqbuf[CCID2_SEQBUF_MAX];5757+ int ccid2hctx_seqbufc;5858+ struct ccid2_seq *ccid2hctx_seqh;5959+ struct ccid2_seq *ccid2hctx_seqt;6060+ long ccid2hctx_rto;6161+ long ccid2hctx_srtt;6262+ long ccid2hctx_rttvar;6363+ unsigned long ccid2hctx_lastrtt;6464+ struct timer_list ccid2hctx_rtotimer;6565+ u64 ccid2hctx_rpseq;6666+ int ccid2hctx_rpdupack;6767+ unsigned long ccid2hctx_last_cong;6868+ u64 ccid2hctx_high_ack;7969};80708181-static inline bool ccid2_cwnd_network_limited(struct ccid2_hc_tx_sock *hctx)8282-{8383- return (hctx->pipe >= hctx->cwnd);8484-}8585-8671struct ccid2_hc_rx_sock {8787- int data;7272+ int ccid2hcrx_data;8873};89749075static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk)
+465-305
net/dccp/ccids/ccid3.c
···4949/*5050 * Transmitter Half-Connection Routines5151 */5252-/* Oscillation Prevention/Reduction: recommended by rfc3448bis, on by default */5353-static int do_osc_prev = true;5252+#ifdef CONFIG_IP_DCCP_CCID3_DEBUG5353+static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)5454+{5555+ static char *ccid3_state_names[] = {5656+ [TFRC_SSTATE_NO_SENT] = "NO_SENT",5757+ [TFRC_SSTATE_NO_FBACK] = "NO_FBACK",5858+ [TFRC_SSTATE_FBACK] = "FBACK",5959+ [TFRC_SSTATE_TERM] = "TERM",6060+ };6161+6262+ return ccid3_state_names[state];6363+}6464+#endif6565+6666+static void ccid3_hc_tx_set_state(struct sock *sk,6767+ enum ccid3_hc_tx_states state)6868+{6969+ struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);7070+ enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state;7171+7272+ ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",7373+ dccp_role(sk), sk, ccid3_tx_state_name(oldstate),7474+ ccid3_tx_state_name(state));7575+ WARN_ON(state == oldstate);7676+ hctx->ccid3hctx_state = state;7777+}54785579/*5680 * Compute the initial sending rate X_init in the manner of RFC 3390:5781 *5858- * X_init = min(4 * MPS, max(2 * MPS, 4380 bytes)) / RTT8282+ * X_init = min(4 * s, max(2 * s, 4380 bytes)) / RTT5983 *8484+ * Note that RFC 3390 uses MSS, RFC 4342 refers to RFC 3390, and rfc3448bis8585+ * (rev-02) clarifies the use of RFC 3390 with regard to the above formula.6086 * For consistency with other parts of the code, X_init is scaled by 2^6.6187 */6288static inline u64 rfc3390_initial_rate(struct sock *sk)6389{6464- const u32 mps = dccp_sk(sk)->dccps_mss_cache,6565- w_init = clamp(4380U, 2 * mps, 4 * mps);9090+ const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);9191+ const __u32 w_init = clamp_t(__u32, 4380U,9292+ 2 * hctx->ccid3hctx_s, 4 * hctx->ccid3hctx_s);66936767- return scaled_div(w_init << 6, ccid3_hc_tx_sk(sk)->rtt);9494+ return scaled_div(w_init << 6, hctx->ccid3hctx_rtt);6895}69967070-/**7171- * ccid3_update_send_interval - Calculate new t_ipi = s / X7272- * This respects the granularity of X (64 * bytes/second) and enforces the7373- * scaled minimum of s * 64 / t_mbi = `s' bytes/second as per RFC 3448/4342.9797+/*9898+ * Recalculate t_ipi and delta (should be called whenever X changes)7499 */75100static void ccid3_update_send_interval(struct ccid3_hc_tx_sock *hctx)76101{7777- if (unlikely(hctx->x <= hctx->s))7878- hctx->x = hctx->s;7979- hctx->t_ipi = scaled_div32(((u64)hctx->s) << 6, hctx->x);102102+ /* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */103103+ hctx->ccid3hctx_t_ipi = scaled_div32(((u64)hctx->ccid3hctx_s) << 6,104104+ hctx->ccid3hctx_x);105105+106106+ /* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */107107+ hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2,108108+ TFRC_OPSYS_HALF_TIME_GRAN);109109+110110+ ccid3_pr_debug("t_ipi=%u, delta=%u, s=%u, X=%u\n",111111+ hctx->ccid3hctx_t_ipi, hctx->ccid3hctx_delta,112112+ hctx->ccid3hctx_s, (unsigned)(hctx->ccid3hctx_x >> 6));113113+80114}8111582116static u32 ccid3_hc_tx_idle_rtt(struct ccid3_hc_tx_sock *hctx, ktime_t now)83117{8484- u32 delta = ktime_us_delta(now, hctx->t_last_win_count);118118+ u32 delta = ktime_us_delta(now, hctx->ccid3hctx_t_last_win_count);851198686- return delta / hctx->rtt;120120+ return delta / hctx->ccid3hctx_rtt;87121}8812289123/**···13399static void ccid3_hc_tx_update_x(struct sock *sk, ktime_t *stamp)134100{135101 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);136136- u64 min_rate = 2 * hctx->x_recv;137137- const u64 old_x = hctx->x;102102+ __u64 min_rate = 2 * hctx->ccid3hctx_x_recv;103103+ const __u64 old_x = hctx->ccid3hctx_x;138104 ktime_t now = stamp ? *stamp : ktime_get_real();139105140106 /*···145111 */146112 if (ccid3_hc_tx_idle_rtt(hctx, now) >= 2) {147113 min_rate = rfc3390_initial_rate(sk);148148- min_rate = max(min_rate, 2 * hctx->x_recv);114114+ min_rate = max(min_rate, 2 * hctx->ccid3hctx_x_recv);149115 }150116151151- if (hctx->p > 0) {117117+ if (hctx->ccid3hctx_p > 0) {152118153153- hctx->x = min(((u64)hctx->x_calc) << 6, min_rate);119119+ hctx->ccid3hctx_x = min(((__u64)hctx->ccid3hctx_x_calc) << 6,120120+ min_rate);121121+ hctx->ccid3hctx_x = max(hctx->ccid3hctx_x,122122+ (((__u64)hctx->ccid3hctx_s) << 6) /123123+ TFRC_T_MBI);154124155155- } else if (ktime_us_delta(now, hctx->t_ld) - (s64)hctx->rtt >= 0) {125125+ } else if (ktime_us_delta(now, hctx->ccid3hctx_t_ld)126126+ - (s64)hctx->ccid3hctx_rtt >= 0) {156127157157- hctx->x = min(2 * hctx->x, min_rate);158158- hctx->x = max(hctx->x,159159- scaled_div(((u64)hctx->s) << 6, hctx->rtt));160160- hctx->t_ld = now;128128+ hctx->ccid3hctx_x = min(2 * hctx->ccid3hctx_x, min_rate);129129+ hctx->ccid3hctx_x = max(hctx->ccid3hctx_x,130130+ scaled_div(((__u64)hctx->ccid3hctx_s) << 6,131131+ hctx->ccid3hctx_rtt));132132+ hctx->ccid3hctx_t_ld = now;161133 }162134163163- if (hctx->x != old_x) {135135+ if (hctx->ccid3hctx_x != old_x) {164136 ccid3_pr_debug("X_prev=%u, X_now=%u, X_calc=%u, "165137 "X_recv=%u\n", (unsigned)(old_x >> 6),166166- (unsigned)(hctx->x >> 6), hctx->x_calc,167167- (unsigned)(hctx->x_recv >> 6));138138+ (unsigned)(hctx->ccid3hctx_x >> 6),139139+ hctx->ccid3hctx_x_calc,140140+ (unsigned)(hctx->ccid3hctx_x_recv >> 6));168141169142 ccid3_update_send_interval(hctx);170143 }171144}172145173146/*174174- * ccid3_hc_tx_measure_packet_size - Measuring the packet size `s' (sec 4.1)175175- * @new_len: DCCP payload size in bytes (not used by all methods)147147+ * Track the mean packet size `s' (cf. RFC 4342, 5.3 and RFC 3448, 4.1)148148+ * @len: DCCP packet payload size in bytes176149 */177177-static u32 ccid3_hc_tx_measure_packet_size(struct sock *sk, const u16 new_len)150150+static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len)178151{179179-#if defined(CONFIG_IP_DCCP_CCID3_MEASURE_S_AS_AVG)180180- return tfrc_ewma(ccid3_hc_tx_sk(sk)->s, new_len, 9);181181-#elif defined(CONFIG_IP_DCCP_CCID3_MEASURE_S_AS_MAX)182182- return max(ccid3_hc_tx_sk(sk)->s, new_len);183183-#else /* CONFIG_IP_DCCP_CCID3_MEASURE_S_AS_MPS */184184- return dccp_sk(sk)->dccps_mss_cache;185185-#endif152152+ const u16 old_s = hctx->ccid3hctx_s;153153+154154+ hctx->ccid3hctx_s = tfrc_ewma(hctx->ccid3hctx_s, len, 9);155155+156156+ if (hctx->ccid3hctx_s != old_s)157157+ ccid3_update_send_interval(hctx);186158}187159188160/*···198158static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx,199159 ktime_t now)200160{201201- u32 delta = ktime_us_delta(now, hctx->t_last_win_count),202202- quarter_rtts = (4 * delta) / hctx->rtt;161161+ u32 delta = ktime_us_delta(now, hctx->ccid3hctx_t_last_win_count),162162+ quarter_rtts = (4 * delta) / hctx->ccid3hctx_rtt;203163204164 if (quarter_rtts > 0) {205205- hctx->t_last_win_count = now;206206- hctx->last_win_count += min(quarter_rtts, 5U);207207- hctx->last_win_count &= 0xF; /* mod 16 */165165+ hctx->ccid3hctx_t_last_win_count = now;166166+ hctx->ccid3hctx_last_win_count += min(quarter_rtts, 5U);167167+ hctx->ccid3hctx_last_win_count &= 0xF; /* mod 16 */208168 }209169}210170···221181 goto restart_timer;222182 }223183224224- ccid3_pr_debug("%s(%p) entry with%s feedback\n", dccp_role(sk), sk,225225- hctx->feedback ? "" : "out");184184+ ccid3_pr_debug("%s(%p, state=%s) - entry \n", dccp_role(sk), sk,185185+ ccid3_tx_state_name(hctx->ccid3hctx_state));226186227227- /* Ignore and do not restart after leaving the established state */228228- if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN))187187+ if (hctx->ccid3hctx_state == TFRC_SSTATE_FBACK)188188+ ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);189189+ else if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK)229190 goto out;230230-231231- /* Reset feedback state to "no feedback received" */232232- hctx->feedback = false;233191234192 /*235193 * Determine new allowed sending rate X as per draft rfc3448bis-00, 4.4236236- * RTO is 0 if and only if no feedback has been received yet.237194 */238238- if (hctx->t_rto == 0 || hctx->p == 0) {195195+ if (hctx->ccid3hctx_t_rto == 0 || /* no feedback received yet */196196+ hctx->ccid3hctx_p == 0) {239197240198 /* halve send rate directly */241241- hctx->x /= 2;199199+ hctx->ccid3hctx_x = max(hctx->ccid3hctx_x / 2,200200+ (((__u64)hctx->ccid3hctx_s) << 6) /201201+ TFRC_T_MBI);242202 ccid3_update_send_interval(hctx);243243-244203 } else {245204 /*246205 * Modify the cached value of X_recv···251212 *252213 * Note that X_recv is scaled by 2^6 while X_calc is not253214 */254254- BUG_ON(hctx->p && !hctx->x_calc);215215+ BUG_ON(hctx->ccid3hctx_p && !hctx->ccid3hctx_x_calc);255216256256- if (hctx->x_calc > (hctx->x_recv >> 5))257257- hctx->x_recv /= 2;217217+ if (hctx->ccid3hctx_x_calc > (hctx->ccid3hctx_x_recv >> 5))218218+ hctx->ccid3hctx_x_recv =219219+ max(hctx->ccid3hctx_x_recv / 2,220220+ (((__u64)hctx->ccid3hctx_s) << 6) /221221+ (2 * TFRC_T_MBI));258222 else {259259- hctx->x_recv = hctx->x_calc;260260- hctx->x_recv <<= 4;223223+ hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc;224224+ hctx->ccid3hctx_x_recv <<= 4;261225 }262226 ccid3_hc_tx_update_x(sk, NULL);263227 }264228 ccid3_pr_debug("Reduced X to %llu/64 bytes/sec\n",265265- (unsigned long long)hctx->x);229229+ (unsigned long long)hctx->ccid3hctx_x);266230267231 /*268232 * Set new timeout for the nofeedback timer.269233 * See comments in packet_recv() regarding the value of t_RTO.270234 */271271- if (unlikely(hctx->t_rto == 0)) /* no feedback received yet */235235+ if (unlikely(hctx->ccid3hctx_t_rto == 0)) /* no feedback yet */272236 t_nfb = TFRC_INITIAL_TIMEOUT;273237 else274274- t_nfb = max(hctx->t_rto, 2 * hctx->t_ipi);238238+ t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);275239276240restart_timer:277277- sk_reset_timer(sk, &hctx->no_feedback_timer,241241+ sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,278242 jiffies + usecs_to_jiffies(t_nfb));279243out:280244 bh_unlock_sock(sk);281245 sock_put(sk);282246}283247284284-/**285285- * ccid3_hc_tx_send_packet - Delay-based dequeueing of TX packets286286- * @skb: next packet candidate to send on @sk287287- * This function uses the convention of ccid_packet_dequeue_eval() and288288- * returns a millisecond-delay value between 0 and t_mbi = 64000 msec.248248+/*249249+ * returns250250+ * > 0: delay (in msecs) that should pass before actually sending251251+ * = 0: can send immediately252252+ * < 0: error condition; do not send packet289253 */290254static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)291255{···305263 if (unlikely(skb->len == 0))306264 return -EBADMSG;307265308308- if (hctx->s == 0) {309309- sk_reset_timer(sk, &hctx->no_feedback_timer, (jiffies +266266+ switch (hctx->ccid3hctx_state) {267267+ case TFRC_SSTATE_NO_SENT:268268+ sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,269269+ (jiffies +310270 usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)));311311- hctx->last_win_count = 0;312312- hctx->t_last_win_count = now;271271+ hctx->ccid3hctx_last_win_count = 0;272272+ hctx->ccid3hctx_t_last_win_count = now;313273314274 /* Set t_0 for initial packet */315315- hctx->t_nom = now;275275+ hctx->ccid3hctx_t_nom = now;276276+277277+ hctx->ccid3hctx_s = skb->len;316278317279 /*318280 * Use initial RTT sample when available: recommended by erratum···325279 */326280 if (dp->dccps_syn_rtt) {327281 ccid3_pr_debug("SYN RTT = %uus\n", dp->dccps_syn_rtt);328328- hctx->rtt = dp->dccps_syn_rtt;329329- hctx->x = rfc3390_initial_rate(sk);330330- hctx->t_ld = now;282282+ hctx->ccid3hctx_rtt = dp->dccps_syn_rtt;283283+ hctx->ccid3hctx_x = rfc3390_initial_rate(sk);284284+ hctx->ccid3hctx_t_ld = now;331285 } else {332286 /*333287 * Sender does not have RTT sample:···335289 * is needed in several parts (e.g. window counter);336290 * - set sending rate X_pps = 1pps as per RFC 3448, 4.2.337291 */338338- hctx->rtt = DCCP_FALLBACK_RTT;339339- hctx->x = dp->dccps_mss_cache;340340- hctx->x <<= 6;292292+ hctx->ccid3hctx_rtt = DCCP_FALLBACK_RTT;293293+ hctx->ccid3hctx_x = hctx->ccid3hctx_s;294294+ hctx->ccid3hctx_x <<= 6;341295 }342342-343343- /* Compute t_ipi = s / X */344344- hctx->s = ccid3_hc_tx_measure_packet_size(sk, skb->len);345296 ccid3_update_send_interval(hctx);346297347347- /* Seed value for Oscillation Prevention (sec. 4.5) */348348- hctx->r_sqmean = tfrc_scaled_sqrt(hctx->rtt);349349-350350- } else {351351- delay = ktime_us_delta(hctx->t_nom, now);298298+ ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);299299+ break;300300+ case TFRC_SSTATE_NO_FBACK:301301+ case TFRC_SSTATE_FBACK:302302+ delay = ktime_us_delta(hctx->ccid3hctx_t_nom, now);352303 ccid3_pr_debug("delay=%ld\n", (long)delay);353304 /*354305 * Scheduling of packet transmissions [RFC 3448, 4.6]···355312 * else356313 * // send the packet in (t_nom - t_now) milliseconds.357314 */358358- if (delay >= TFRC_T_DELTA)359359- return (u32)delay / USEC_PER_MSEC;315315+ if (delay - (s64)hctx->ccid3hctx_delta >= 1000)316316+ return (u32)delay / 1000L;360317361318 ccid3_hc_tx_update_win_count(hctx, now);319319+ break;320320+ case TFRC_SSTATE_TERM:321321+ DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);322322+ return -EINVAL;362323 }363324364325 /* prepare to send now (add options etc.) */365326 dp->dccps_hc_tx_insert_options = 1;366366- DCCP_SKB_CB(skb)->dccpd_ccval = hctx->last_win_count;327327+ DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;367328368329 /* set the nominal send time for the next following packet */369369- hctx->t_nom = ktime_add_us(hctx->t_nom, hctx->t_ipi);370370- return CCID_PACKET_SEND_AT_ONCE;330330+ hctx->ccid3hctx_t_nom = ktime_add_us(hctx->ccid3hctx_t_nom,331331+ hctx->ccid3hctx_t_ipi);332332+ return 0;371333}372334373373-static void ccid3_hc_tx_packet_sent(struct sock *sk, unsigned int len)335335+static void ccid3_hc_tx_packet_sent(struct sock *sk, int more,336336+ unsigned int len)374337{375338 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);376339377377- /* Changes to s will become effective the next time X is computed */378378- hctx->s = ccid3_hc_tx_measure_packet_size(sk, len);340340+ ccid3_hc_tx_update_s(hctx, len);379341380380- if (tfrc_tx_hist_add(&hctx->hist, dccp_sk(sk)->dccps_gss))342342+ if (tfrc_tx_hist_add(&hctx->ccid3hctx_hist, dccp_sk(sk)->dccps_gss))381343 DCCP_CRIT("packet history - out of memory!");382344}383345384346static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)385347{386348 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);387387- struct tfrc_tx_hist_entry *acked;349349+ struct ccid3_options_received *opt_recv;388350 ktime_t now;389351 unsigned long t_nfb;390390- u32 r_sample;352352+ u32 pinv, r_sample;391353392354 /* we are only interested in ACKs */393355 if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK ||394356 DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK))395357 return;396396- /*397397- * Locate the acknowledged packet in the TX history.398398- *399399- * Returning "entry not found" here can for instance happen when400400- * - the host has not sent out anything (e.g. a passive server),401401- * - the Ack is outdated (packet with higher Ack number was received),402402- * - it is a bogus Ack (for a packet not sent on this connection).403403- */404404- acked = tfrc_tx_hist_find_entry(hctx->hist, dccp_hdr_ack_seq(skb));405405- if (acked == NULL)358358+ /* ... and only in the established state */359359+ if (hctx->ccid3hctx_state != TFRC_SSTATE_FBACK &&360360+ hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK)406361 return;407407- /* For the sake of RTT sampling, ignore/remove all older entries */408408- tfrc_tx_hist_purge(&acked->next);409362410410- /* Update the moving average for the RTT estimate (RFC 3448, 4.3) */411411- now = ktime_get_real();412412- r_sample = dccp_sample_rtt(sk, ktime_us_delta(now, acked->stamp));413413- hctx->rtt = tfrc_ewma(hctx->rtt, r_sample, 9);363363+ opt_recv = &hctx->ccid3hctx_options_received;364364+ now = ktime_get_real();414365366366+ /* Estimate RTT from history if ACK number is valid */367367+ r_sample = tfrc_tx_hist_rtt(hctx->ccid3hctx_hist,368368+ DCCP_SKB_CB(skb)->dccpd_ack_seq, now);369369+ if (r_sample == 0) {370370+ DCCP_WARN("%s(%p): %s with bogus ACK-%llu\n", dccp_role(sk), sk,371371+ dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type),372372+ (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq);373373+ return;374374+ }375375+376376+ /* Update receive rate in units of 64 * bytes/second */377377+ hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate;378378+ hctx->ccid3hctx_x_recv <<= 6;379379+380380+ /* Update loss event rate (which is scaled by 1e6) */381381+ pinv = opt_recv->ccid3or_loss_event_rate;382382+ if (pinv == ~0U || pinv == 0) /* see RFC 4342, 8.5 */383383+ hctx->ccid3hctx_p = 0;384384+ else /* can not exceed 100% */385385+ hctx->ccid3hctx_p = scaled_div(1, pinv);386386+ /*387387+ * Validate new RTT sample and update moving average388388+ */389389+ r_sample = dccp_sample_rtt(sk, r_sample);390390+ hctx->ccid3hctx_rtt = tfrc_ewma(hctx->ccid3hctx_rtt, r_sample, 9);415391 /*416392 * Update allowed sending rate X as per draft rfc3448bis-00, 4.2/3417393 */418418- if (!hctx->feedback) {419419- hctx->feedback = true;394394+ if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) {395395+ ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);420396421421- if (hctx->t_rto == 0) {397397+ if (hctx->ccid3hctx_t_rto == 0) {422398 /*423399 * Initial feedback packet: Larger Initial Windows (4.2)424400 */425425- hctx->x = rfc3390_initial_rate(sk);426426- hctx->t_ld = now;401401+ hctx->ccid3hctx_x = rfc3390_initial_rate(sk);402402+ hctx->ccid3hctx_t_ld = now;427403428404 ccid3_update_send_interval(hctx);429405430406 goto done_computing_x;431431- } else if (hctx->p == 0) {407407+ } else if (hctx->ccid3hctx_p == 0) {432408 /*433409 * First feedback after nofeedback timer expiry (4.3)434410 */···456394 }457395458396 /* Update sending rate (step 4 of [RFC 3448, 4.3]) */459459- if (hctx->p > 0)460460- hctx->x_calc = tfrc_calc_x(hctx->s, hctx->rtt, hctx->p);397397+ if (hctx->ccid3hctx_p > 0)398398+ hctx->ccid3hctx_x_calc =399399+ tfrc_calc_x(hctx->ccid3hctx_s,400400+ hctx->ccid3hctx_rtt,401401+ hctx->ccid3hctx_p);461402 ccid3_hc_tx_update_x(sk, &now);462403463404done_computing_x:464405 ccid3_pr_debug("%s(%p), RTT=%uus (sample=%uus), s=%u, "465406 "p=%u, X_calc=%u, X_recv=%u, X=%u\n",466466- dccp_role(sk), sk, hctx->rtt, r_sample,467467- hctx->s, hctx->p, hctx->x_calc,468468- (unsigned)(hctx->x_recv >> 6),469469- (unsigned)(hctx->x >> 6));470470- /*471471- * Oscillation Reduction (RFC 3448, 4.5) - modifying t_ipi according to472472- * RTT changes, multiplying by X/X_inst = sqrt(R_sample)/R_sqmean. This473473- * can be useful if few connections share a link, avoiding that buffer474474- * fill levels (RTT) oscillate as a result of frequent adjustments to X.475475- * A useful presentation with background information is in476476- * Joerg Widmer, "Equation-Based Congestion Control",477477- * MSc Thesis, University of Mannheim, Germany, 2000478478- * (sec. 3.6.4), who calls this ISM ("Inter-packet Space Modulation").479479- */480480- if (do_osc_prev) {481481- r_sample = tfrc_scaled_sqrt(r_sample);482482- /*483483- * The modulation can work in both ways: increase/decrease t_ipi484484- * according to long-term increases/decreases of the RTT. The485485- * former is a useful measure, since it works against queue486486- * build-up. The latter temporarily increases the sending rate,487487- * so that buffers fill up more quickly. This in turn causes488488- * the RTT to increase, so that either later reduction becomes489489- * necessary or the RTT stays at a very high level. Decreasing490490- * t_ipi is therefore not supported.491491- * Furthermore, during the initial slow-start phase the RTT492492- * naturally increases, where using the algorithm would cause493493- * delays. Hence it is disabled during the initial slow-start.494494- */495495- if (r_sample > hctx->r_sqmean && hctx->p > 0)496496- hctx->t_ipi = div_u64((u64)hctx->t_ipi * (u64)r_sample,497497- hctx->r_sqmean);498498- hctx->t_ipi = min_t(u32, hctx->t_ipi, TFRC_T_MBI);499499- /* update R_sqmean _after_ computing the modulation factor */500500- hctx->r_sqmean = tfrc_ewma(hctx->r_sqmean, r_sample, 9);501501- }407407+ dccp_role(sk),408408+ sk, hctx->ccid3hctx_rtt, r_sample,409409+ hctx->ccid3hctx_s, hctx->ccid3hctx_p,410410+ hctx->ccid3hctx_x_calc,411411+ (unsigned)(hctx->ccid3hctx_x_recv >> 6),412412+ (unsigned)(hctx->ccid3hctx_x >> 6));502413503414 /* unschedule no feedback timer */504504- sk_stop_timer(sk, &hctx->no_feedback_timer);415415+ sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);505416506417 /*507418 * As we have calculated new ipi, delta, t_nom it is possible···488453 * This can help avoid triggering the nofeedback timer too489454 * often ('spinning') on LANs with small RTTs.490455 */491491- hctx->t_rto = max_t(u32, 4 * hctx->rtt, (CONFIG_IP_DCCP_CCID3_RTO *492492- (USEC_PER_SEC / 1000)));456456+ hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,457457+ (CONFIG_IP_DCCP_CCID3_RTO *458458+ (USEC_PER_SEC / 1000)));493459 /*494460 * Schedule no feedback timer to expire in495461 * max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi)496462 */497497- t_nfb = max(hctx->t_rto, 2 * hctx->t_ipi);463463+ t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);498464499465 ccid3_pr_debug("%s(%p), Scheduled no feedback timer to "500466 "expire in %lu jiffies (%luus)\n",501501- dccp_role(sk), sk, usecs_to_jiffies(t_nfb), t_nfb);467467+ dccp_role(sk),468468+ sk, usecs_to_jiffies(t_nfb), t_nfb);502469503503- sk_reset_timer(sk, &hctx->no_feedback_timer,470470+ sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,504471 jiffies + usecs_to_jiffies(t_nfb));505472}506473507507-static int ccid3_hc_tx_parse_options(struct sock *sk, u8 packet_type,508508- u8 option, u8 *optval, u8 optlen)474474+static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,475475+ unsigned char len, u16 idx,476476+ unsigned char *value)509477{478478+ int rc = 0;479479+ const struct dccp_sock *dp = dccp_sk(sk);510480 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);481481+ struct ccid3_options_received *opt_recv;511482 __be32 opt_val;512483513513- switch (option) {514514- case TFRC_OPT_RECEIVE_RATE:515515- case TFRC_OPT_LOSS_EVENT_RATE:516516- /* Must be ignored on Data packets, cf. RFC 4342 8.3 and 8.5 */517517- if (packet_type == DCCP_PKT_DATA)518518- break;519519- if (unlikely(optlen != 4)) {520520- DCCP_WARN("%s(%p), invalid len %d for %u\n",521521- dccp_role(sk), sk, optlen, option);522522- return -EINVAL;523523- }524524- opt_val = ntohl(get_unaligned((__be32 *)optval));484484+ opt_recv = &hctx->ccid3hctx_options_received;525485526526- if (option == TFRC_OPT_RECEIVE_RATE) {527527- /* Receive Rate is kept in units of 64 bytes/second */528528- hctx->x_recv = opt_val;529529- hctx->x_recv <<= 6;530530-531531- ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",532532- dccp_role(sk), sk, opt_val);533533- } else {534534- /* Update the fixpoint Loss Event Rate fraction */535535- hctx->p = tfrc_invert_loss_event_rate(opt_val);536536-537537- ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",538538- dccp_role(sk), sk, opt_val);539539- }486486+ if (opt_recv->ccid3or_seqno != dp->dccps_gsr) {487487+ opt_recv->ccid3or_seqno = dp->dccps_gsr;488488+ opt_recv->ccid3or_loss_event_rate = ~0;489489+ opt_recv->ccid3or_loss_intervals_idx = 0;490490+ opt_recv->ccid3or_loss_intervals_len = 0;491491+ opt_recv->ccid3or_receive_rate = 0;540492 }541541- return 0;493493+494494+ switch (option) {495495+ case TFRC_OPT_LOSS_EVENT_RATE:496496+ if (unlikely(len != 4)) {497497+ DCCP_WARN("%s(%p), invalid len %d "498498+ "for TFRC_OPT_LOSS_EVENT_RATE\n",499499+ dccp_role(sk), sk, len);500500+ rc = -EINVAL;501501+ } else {502502+ opt_val = get_unaligned((__be32 *)value);503503+ opt_recv->ccid3or_loss_event_rate = ntohl(opt_val);504504+ ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",505505+ dccp_role(sk), sk,506506+ opt_recv->ccid3or_loss_event_rate);507507+ }508508+ break;509509+ case TFRC_OPT_LOSS_INTERVALS:510510+ opt_recv->ccid3or_loss_intervals_idx = idx;511511+ opt_recv->ccid3or_loss_intervals_len = len;512512+ ccid3_pr_debug("%s(%p), LOSS_INTERVALS=(%u, %u)\n",513513+ dccp_role(sk), sk,514514+ opt_recv->ccid3or_loss_intervals_idx,515515+ opt_recv->ccid3or_loss_intervals_len);516516+ break;517517+ case TFRC_OPT_RECEIVE_RATE:518518+ if (unlikely(len != 4)) {519519+ DCCP_WARN("%s(%p), invalid len %d "520520+ "for TFRC_OPT_RECEIVE_RATE\n",521521+ dccp_role(sk), sk, len);522522+ rc = -EINVAL;523523+ } else {524524+ opt_val = get_unaligned((__be32 *)value);525525+ opt_recv->ccid3or_receive_rate = ntohl(opt_val);526526+ ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",527527+ dccp_role(sk), sk,528528+ opt_recv->ccid3or_receive_rate);529529+ }530530+ break;531531+ }532532+533533+ return rc;542534}543535544536static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)545537{546538 struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);547539548548- hctx->hist = NULL;549549- setup_timer(&hctx->no_feedback_timer,550550- ccid3_hc_tx_no_feedback_timer, (unsigned long)sk);540540+ hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;541541+ hctx->ccid3hctx_hist = NULL;542542+ setup_timer(&hctx->ccid3hctx_no_feedback_timer,543543+ ccid3_hc_tx_no_feedback_timer, (unsigned long)sk);544544+551545 return 0;552546}553547···584520{585521 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);586522587587- sk_stop_timer(sk, &hctx->no_feedback_timer);588588- tfrc_tx_hist_purge(&hctx->hist);523523+ ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM);524524+ sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);525525+526526+ tfrc_tx_hist_purge(&hctx->ccid3hctx_hist);589527}590528591529static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)592530{593593- info->tcpi_rto = ccid3_hc_tx_sk(sk)->t_rto;594594- info->tcpi_rtt = ccid3_hc_tx_sk(sk)->rtt;531531+ struct ccid3_hc_tx_sock *hctx;532532+533533+ /* Listen socks doesn't have a private CCID block */534534+ if (sk->sk_state == DCCP_LISTEN)535535+ return;536536+537537+ hctx = ccid3_hc_tx_sk(sk);538538+ info->tcpi_rto = hctx->ccid3hctx_t_rto;539539+ info->tcpi_rtt = hctx->ccid3hctx_rtt;595540}596541597542static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,598543 u32 __user *optval, int __user *optlen)599544{600600- const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);601601- struct tfrc_tx_info tfrc;545545+ const struct ccid3_hc_tx_sock *hctx;602546 const void *val;603547548548+ /* Listen socks doesn't have a private CCID block */549549+ if (sk->sk_state == DCCP_LISTEN)550550+ return -EINVAL;551551+552552+ hctx = ccid3_hc_tx_sk(sk);604553 switch (optname) {605554 case DCCP_SOCKOPT_CCID_TX_INFO:606606- if (len < sizeof(tfrc))555555+ if (len < sizeof(hctx->ccid3hctx_tfrc))607556 return -EINVAL;608608- tfrc.tfrctx_x = hctx->x;609609- tfrc.tfrctx_x_recv = hctx->x_recv;610610- tfrc.tfrctx_x_calc = hctx->x_calc;611611- tfrc.tfrctx_rtt = hctx->rtt;612612- tfrc.tfrctx_p = hctx->p;613613- tfrc.tfrctx_rto = hctx->t_rto;614614- tfrc.tfrctx_ipi = hctx->t_ipi;615615- len = sizeof(tfrc);616616- val = &tfrc;557557+ len = sizeof(hctx->ccid3hctx_tfrc);558558+ val = &hctx->ccid3hctx_tfrc;617559 break;618560 default:619561 return -ENOPROTOOPT;···634564/*635565 * Receiver Half-Connection Routines636566 */567567+568568+/* CCID3 feedback types */569569+enum ccid3_fback_type {570570+ CCID3_FBACK_NONE = 0,571571+ CCID3_FBACK_INITIAL,572572+ CCID3_FBACK_PERIODIC,573573+ CCID3_FBACK_PARAM_CHANGE574574+};575575+576576+#ifdef CONFIG_IP_DCCP_CCID3_DEBUG577577+static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state)578578+{579579+ static char *ccid3_rx_state_names[] = {580580+ [TFRC_RSTATE_NO_DATA] = "NO_DATA",581581+ [TFRC_RSTATE_DATA] = "DATA",582582+ [TFRC_RSTATE_TERM] = "TERM",583583+ };584584+585585+ return ccid3_rx_state_names[state];586586+}587587+#endif588588+589589+static void ccid3_hc_rx_set_state(struct sock *sk,590590+ enum ccid3_hc_rx_states state)591591+{592592+ struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);593593+ enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;594594+595595+ ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",596596+ dccp_role(sk), sk, ccid3_rx_state_name(oldstate),597597+ ccid3_rx_state_name(state));598598+ WARN_ON(state == oldstate);599599+ hcrx->ccid3hcrx_state = state;600600+}601601+637602static void ccid3_hc_rx_send_feedback(struct sock *sk,638603 const struct sk_buff *skb,639604 enum ccid3_fback_type fbtype)640605{641606 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);607607+ struct dccp_sock *dp = dccp_sk(sk);608608+ ktime_t now;609609+ s64 delta = 0;610610+611611+ if (unlikely(hcrx->ccid3hcrx_state == TFRC_RSTATE_TERM))612612+ return;613613+614614+ now = ktime_get_real();642615643616 switch (fbtype) {644617 case CCID3_FBACK_INITIAL:645645- hcrx->x_recv = 0;646646- hcrx->p_inverse = ~0U; /* see RFC 4342, 8.5 */618618+ hcrx->ccid3hcrx_x_recv = 0;619619+ hcrx->ccid3hcrx_pinv = ~0U; /* see RFC 4342, 8.5 */647620 break;648621 case CCID3_FBACK_PARAM_CHANGE:649649- if (unlikely(hcrx->feedback == CCID3_FBACK_NONE)) {650650- /*651651- * rfc3448bis-06, 6.3.1: First packet(s) lost or marked652652- * FIXME: in rfc3448bis the receiver returns X_recv=0653653- * here as it normally would in the first feedback packet.654654- * However this is not possible yet, since the code still655655- * uses RFC 3448, i.e.656656- * If (p > 0)657657- * Calculate X_calc using the TCP throughput equation.658658- * X = max(min(X_calc, 2*X_recv), s/t_mbi);659659- * would bring X down to s/t_mbi. That is why we return660660- * X_recv according to rfc3448bis-06 for the moment.661661- */662662- u32 s = tfrc_rx_hist_packet_size(&hcrx->hist),663663- rtt = tfrc_rx_hist_rtt(&hcrx->hist);664664-665665- hcrx->x_recv = scaled_div32(s, 2 * rtt);666666- break;667667- }668622 /*669623 * When parameters change (new loss or p > p_prev), we do not670624 * have a reliable estimate for R_m of [RFC 3448, 6.2] and so671671- * always check whether at least RTT time units were covered.625625+ * need to reuse the previous value of X_recv. However, when626626+ * X_recv was 0 (due to early loss), this would kill X down to627627+ * s/t_mbi (i.e. one packet in 64 seconds).628628+ * To avoid such drastic reduction, we approximate X_recv as629629+ * the number of bytes since last feedback.630630+ * This is a safe fallback, since X is bounded above by X_calc.672631 */673673- hcrx->x_recv = tfrc_rx_hist_x_recv(&hcrx->hist, hcrx->x_recv);674674- break;632632+ if (hcrx->ccid3hcrx_x_recv > 0)633633+ break;634634+ /* fall through */675635 case CCID3_FBACK_PERIODIC:676676- /*677677- * Step (2) of rfc3448bis-06, 6.2:678678- * - if no data packets have been received, just restart timer679679- * - if data packets have been received, re-compute X_recv680680- */681681- if (hcrx->hist.bytes_recvd == 0)682682- goto prepare_for_next_time;683683- hcrx->x_recv = tfrc_rx_hist_x_recv(&hcrx->hist, hcrx->x_recv);636636+ delta = ktime_us_delta(now, hcrx->ccid3hcrx_tstamp_last_feedback);637637+ if (delta <= 0)638638+ DCCP_BUG("delta (%ld) <= 0", (long)delta);639639+ else640640+ hcrx->ccid3hcrx_x_recv =641641+ scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);684642 break;685643 default:686644 return;687645 }688646689689- ccid3_pr_debug("X_recv=%u, 1/p=%u\n", hcrx->x_recv, hcrx->p_inverse);647647+ ccid3_pr_debug("Interval %ldusec, X_recv=%u, 1/p=%u\n", (long)delta,648648+ hcrx->ccid3hcrx_x_recv, hcrx->ccid3hcrx_pinv);690649691691- dccp_sk(sk)->dccps_hc_rx_insert_options = 1;650650+ hcrx->ccid3hcrx_tstamp_last_feedback = now;651651+ hcrx->ccid3hcrx_last_counter = dccp_hdr(skb)->dccph_ccval;652652+ hcrx->ccid3hcrx_bytes_recv = 0;653653+654654+ dp->dccps_hc_rx_insert_options = 1;692655 dccp_send_ack(sk);693693-694694-prepare_for_next_time:695695- tfrc_rx_hist_restart_byte_counter(&hcrx->hist);696696- hcrx->last_counter = dccp_hdr(skb)->dccph_ccval;697697- hcrx->feedback = fbtype;698656}699657700658static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)701659{702702- const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);660660+ const struct ccid3_hc_rx_sock *hcrx;703661 __be32 x_recv, pinv;704662705663 if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))706664 return 0;707665666666+ hcrx = ccid3_hc_rx_sk(sk);667667+708668 if (dccp_packet_without_ack(skb))709669 return 0;710670711711- x_recv = htonl(hcrx->x_recv);712712- pinv = htonl(hcrx->p_inverse);671671+ x_recv = htonl(hcrx->ccid3hcrx_x_recv);672672+ pinv = htonl(hcrx->ccid3hcrx_pinv);713673714674 if (dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE,715675 &pinv, sizeof(pinv)) ||···762662static u32 ccid3_first_li(struct sock *sk)763663{764664 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);765765- u32 s = tfrc_rx_hist_packet_size(&hcrx->hist),766766- rtt = tfrc_rx_hist_rtt(&hcrx->hist), x_recv, p;665665+ u32 x_recv, p, delta;767666 u64 fval;768667769769- /*770770- * rfc3448bis-06, 6.3.1: First data packet(s) are marked or lost. Set p771771- * to give the equivalent of X_target = s/(2*R). Thus fval = 2 and so p772772- * is about 20.64%. This yields an interval length of 4.84 (rounded up).773773- */774774- if (unlikely(hcrx->feedback == CCID3_FBACK_NONE))775775- return 5;668668+ if (hcrx->ccid3hcrx_rtt == 0) {669669+ DCCP_WARN("No RTT estimate available, using fallback RTT\n");670670+ hcrx->ccid3hcrx_rtt = DCCP_FALLBACK_RTT;671671+ }776672777777- x_recv = tfrc_rx_hist_x_recv(&hcrx->hist, hcrx->x_recv);778778- if (x_recv == 0)779779- goto failed;673673+ delta = ktime_to_us(net_timedelta(hcrx->ccid3hcrx_tstamp_last_feedback));674674+ x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);675675+ if (x_recv == 0) { /* would also trigger divide-by-zero */676676+ DCCP_WARN("X_recv==0\n");677677+ if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) {678678+ DCCP_BUG("stored value of X_recv is zero");679679+ return ~0U;680680+ }681681+ }780682781781- fval = scaled_div32(scaled_div(s, rtt), x_recv);683683+ fval = scaled_div(hcrx->ccid3hcrx_s, hcrx->ccid3hcrx_rtt);684684+ fval = scaled_div32(fval, x_recv);782685 p = tfrc_calc_x_reverse_lookup(fval);783686784687 ccid3_pr_debug("%s(%p), receive rate=%u bytes/s, implied "785688 "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);786689787787- if (p > 0)788788- return scaled_div(1, p);789789-failed:790790- return UINT_MAX;690690+ return p == 0 ? ~0U : scaled_div(1, p);791691}792692793693static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)794694{795695 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);696696+ enum ccid3_fback_type do_feedback = CCID3_FBACK_NONE;796697 const u64 ndp = dccp_sk(sk)->dccps_options_received.dccpor_ndp;797698 const bool is_data_packet = dccp_data_packet(skb);699699+700700+ if (unlikely(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)) {701701+ if (is_data_packet) {702702+ const u32 payload = skb->len - dccp_hdr(skb)->dccph_doff * 4;703703+ do_feedback = CCID3_FBACK_INITIAL;704704+ ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);705705+ hcrx->ccid3hcrx_s = payload;706706+ /*707707+ * Not necessary to update ccid3hcrx_bytes_recv here,708708+ * since X_recv = 0 for the first feedback packet (cf.709709+ * RFC 3448, 6.3) -- gerrit710710+ */711711+ }712712+ goto update_records;713713+ }714714+715715+ if (tfrc_rx_hist_duplicate(&hcrx->ccid3hcrx_hist, skb))716716+ return; /* done receiving */717717+718718+ if (is_data_packet) {719719+ const u32 payload = skb->len - dccp_hdr(skb)->dccph_doff * 4;720720+ /*721721+ * Update moving-average of s and the sum of received payload bytes722722+ */723723+ hcrx->ccid3hcrx_s = tfrc_ewma(hcrx->ccid3hcrx_s, payload, 9);724724+ hcrx->ccid3hcrx_bytes_recv += payload;725725+ }798726799727 /*800728 * Perform loss detection and handle pending losses801729 */802802- if (tfrc_rx_congestion_event(&hcrx->hist, &hcrx->li_hist,803803- skb, ndp, ccid3_first_li, sk))804804- ccid3_hc_rx_send_feedback(sk, skb, CCID3_FBACK_PARAM_CHANGE);730730+ if (tfrc_rx_handle_loss(&hcrx->ccid3hcrx_hist, &hcrx->ccid3hcrx_li_hist,731731+ skb, ndp, ccid3_first_li, sk)) {732732+ do_feedback = CCID3_FBACK_PARAM_CHANGE;733733+ goto done_receiving;734734+ }735735+736736+ if (tfrc_rx_hist_loss_pending(&hcrx->ccid3hcrx_hist))737737+ return; /* done receiving */738738+805739 /*806806- * Feedback for first non-empty data packet (RFC 3448, 6.3)740740+ * Handle data packets: RTT sampling and monitoring p807741 */808808- else if (unlikely(hcrx->feedback == CCID3_FBACK_NONE && is_data_packet))809809- ccid3_hc_rx_send_feedback(sk, skb, CCID3_FBACK_INITIAL);742742+ if (unlikely(!is_data_packet))743743+ goto update_records;744744+745745+ if (!tfrc_lh_is_initialised(&hcrx->ccid3hcrx_li_hist)) {746746+ const u32 sample = tfrc_rx_hist_sample_rtt(&hcrx->ccid3hcrx_hist, skb);747747+ /*748748+ * Empty loss history: no loss so far, hence p stays 0.749749+ * Sample RTT values, since an RTT estimate is required for the750750+ * computation of p when the first loss occurs; RFC 3448, 6.3.1.751751+ */752752+ if (sample != 0)753753+ hcrx->ccid3hcrx_rtt = tfrc_ewma(hcrx->ccid3hcrx_rtt, sample, 9);754754+755755+ } else if (tfrc_lh_update_i_mean(&hcrx->ccid3hcrx_li_hist, skb)) {756756+ /*757757+ * Step (3) of [RFC 3448, 6.1]: Recompute I_mean and, if I_mean758758+ * has decreased (resp. p has increased), send feedback now.759759+ */760760+ do_feedback = CCID3_FBACK_PARAM_CHANGE;761761+ }762762+810763 /*811764 * Check if the periodic once-per-RTT feedback is due; RFC 4342, 10.3812765 */813813- else if (!tfrc_rx_hist_loss_pending(&hcrx->hist) && is_data_packet &&814814- SUB16(dccp_hdr(skb)->dccph_ccval, hcrx->last_counter) > 3)815815- ccid3_hc_rx_send_feedback(sk, skb, CCID3_FBACK_PERIODIC);766766+ if (SUB16(dccp_hdr(skb)->dccph_ccval, hcrx->ccid3hcrx_last_counter) > 3)767767+ do_feedback = CCID3_FBACK_PERIODIC;768768+769769+update_records:770770+ tfrc_rx_hist_add_packet(&hcrx->ccid3hcrx_hist, skb, ndp);771771+772772+done_receiving:773773+ if (do_feedback)774774+ ccid3_hc_rx_send_feedback(sk, skb, do_feedback);816775}817776818777static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)819778{820779 struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);821780822822- tfrc_lh_init(&hcrx->li_hist);823823- return tfrc_rx_hist_init(&hcrx->hist, sk);781781+ hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;782782+ tfrc_lh_init(&hcrx->ccid3hcrx_li_hist);783783+ return tfrc_rx_hist_alloc(&hcrx->ccid3hcrx_hist);824784}825785826786static void ccid3_hc_rx_exit(struct sock *sk)827787{828788 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);829789830830- tfrc_rx_hist_purge(&hcrx->hist);831831- tfrc_lh_cleanup(&hcrx->li_hist);790790+ ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);791791+792792+ tfrc_rx_hist_purge(&hcrx->ccid3hcrx_hist);793793+ tfrc_lh_cleanup(&hcrx->ccid3hcrx_li_hist);832794}833795834796static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)835797{798798+ const struct ccid3_hc_rx_sock *hcrx;799799+800800+ /* Listen socks doesn't have a private CCID block */801801+ if (sk->sk_state == DCCP_LISTEN)802802+ return;803803+804804+ hcrx = ccid3_hc_rx_sk(sk);805805+ info->tcpi_ca_state = hcrx->ccid3hcrx_state;836806 info->tcpi_options |= TCPI_OPT_TIMESTAMPS;837837- info->tcpi_rcv_rtt = tfrc_rx_hist_rtt(&ccid3_hc_rx_sk(sk)->hist);807807+ info->tcpi_rcv_rtt = hcrx->ccid3hcrx_rtt;838808}839809840810static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len,841811 u32 __user *optval, int __user *optlen)842812{843843- const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);813813+ const struct ccid3_hc_rx_sock *hcrx;844814 struct tfrc_rx_info rx_info;845815 const void *val;846816817817+ /* Listen socks doesn't have a private CCID block */818818+ if (sk->sk_state == DCCP_LISTEN)819819+ return -EINVAL;820820+821821+ hcrx = ccid3_hc_rx_sk(sk);847822 switch (optname) {848823 case DCCP_SOCKOPT_CCID_RX_INFO:849824 if (len < sizeof(rx_info))850825 return -EINVAL;851851- rx_info.tfrcrx_x_recv = hcrx->x_recv;852852- rx_info.tfrcrx_rtt = tfrc_rx_hist_rtt(&hcrx->hist);853853- rx_info.tfrcrx_p = tfrc_invert_loss_event_rate(hcrx->p_inverse);826826+ rx_info.tfrcrx_x_recv = hcrx->ccid3hcrx_x_recv;827827+ rx_info.tfrcrx_rtt = hcrx->ccid3hcrx_rtt;828828+ rx_info.tfrcrx_p = hcrx->ccid3hcrx_pinv == 0 ? ~0U :829829+ scaled_div(1, hcrx->ccid3hcrx_pinv);854830 len = sizeof(rx_info);855831 val = &rx_info;856832 break;···962786 .ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt,963787};964788965965-module_param(do_osc_prev, bool, 0644);966966-MODULE_PARM_DESC(do_osc_prev, "Use Oscillation Prevention (RFC 3448, 4.5)");967967-968789#ifdef CONFIG_IP_DCCP_CCID3_DEBUG969790module_param(ccid3_debug, bool, 0644);970791MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");···969796970797static __init int ccid3_module_init(void)971798{972972- struct timespec tp;973973-974974- /*975975- * Without a fine-grained clock resolution, RTTs/X_recv are not sampled976976- * correctly and feedback is sent either too early or too late.977977- */978978- hrtimer_get_res(CLOCK_MONOTONIC, &tp);979979- if (tp.tv_sec || tp.tv_nsec > DCCP_TIME_RESOLUTION * NSEC_PER_USEC) {980980- printk(KERN_ERR "%s: Timer too coarse (%ld usec), need %u-usec"981981- " resolution - check your clocksource.\n", __func__,982982- tp.tv_nsec/NSEC_PER_USEC, DCCP_TIME_RESOLUTION);983983- return -ESOCKTNOSUPPORT;984984- }985799 return ccid_register(&ccid3);986800}987801module_init(ccid3_module_init);
+85-68
net/dccp/ccids/ccid3.h
···4747/* Two seconds as per RFC 3448 4.2 */4848#define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC)49495050-/* Maximum backoff interval t_mbi (RFC 3448, 4.3) */5151-#define TFRC_T_MBI (64 * USEC_PER_SEC)5050+/* In usecs - half the scheduling granularity as per RFC3448 4.6 */5151+#define TFRC_OPSYS_HALF_TIME_GRAN (USEC_PER_SEC / (2 * HZ))52525353-/*5454- * The t_delta parameter (RFC 3448, 4.6): delays of less than %USEC_PER_MSEC are5555- * rounded down to 0, since sk_reset_timer() here uses millisecond granularity.5656- * Hence we can use a constant t_delta = %USEC_PER_MSEC when HZ >= 500. A coarse5757- * resolution of HZ < 500 means that the error is below one timer tick (t_gran)5858- * when using the constant t_delta = t_gran / 2 = %USEC_PER_SEC / (2 * HZ).5959- */6060-#if (HZ >= 500)6161-# define TFRC_T_DELTA USEC_PER_MSEC6262-#else6363-# define TFRC_T_DELTA (USEC_PER_SEC / (2 * HZ))6464-#warning Coarse CONFIG_HZ resolution -- higher value recommended for TFRC.6565-#endif5353+/* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */5454+#define TFRC_T_MBI 6466556756enum ccid3_options {6857 TFRC_OPT_LOSS_EVENT_RATE = 192,···5970 TFRC_OPT_RECEIVE_RATE = 194,6071};61727373+struct ccid3_options_received {7474+ u64 ccid3or_seqno:48,7575+ ccid3or_loss_intervals_idx:16;7676+ u16 ccid3or_loss_intervals_len;7777+ u32 ccid3or_loss_event_rate;7878+ u32 ccid3or_receive_rate;7979+};8080+8181+/* TFRC sender states */8282+enum ccid3_hc_tx_states {8383+ TFRC_SSTATE_NO_SENT = 1,8484+ TFRC_SSTATE_NO_FBACK,8585+ TFRC_SSTATE_FBACK,8686+ TFRC_SSTATE_TERM,8787+};8888+6289/** struct ccid3_hc_tx_sock - CCID3 sender half-connection socket6390 *6464- * @x - Current sending rate in 64 * bytes per second6565- * @x_recv - Receive rate in 64 * bytes per second6666- * @x_calc - Calculated rate in bytes per second6767- * @rtt - Estimate of current round trip time in usecs6868- * @r_sqmean - Estimate of long-term RTT (RFC 3448, 4.5)6969- * @p - Current loss event rate (0-1) scaled by 10000007070- * @s - Packet size in bytes7171- * @t_rto - Nofeedback Timer setting in usecs7272- * @t_ipi - Interpacket (send) interval (RFC 3448, 4.6) in usecs7373- * @feedback - Whether feedback has been received or not7474- * @last_win_count - Last window counter sent7575- * @t_last_win_count - Timestamp of earliest packet with7676- * last_win_count value sent7777- * @no_feedback_timer - Handle to no feedback timer7878- * @t_ld - Time last doubled during slow start7979- * @t_nom - Nominal send time of next packet8080- * @hist - Packet history9191+ * @ccid3hctx_x - Current sending rate in 64 * bytes per second9292+ * @ccid3hctx_x_recv - Receive rate in 64 * bytes per second9393+ * @ccid3hctx_x_calc - Calculated rate in bytes per second9494+ * @ccid3hctx_rtt - Estimate of current round trip time in usecs9595+ * @ccid3hctx_p - Current loss event rate (0-1) scaled by 10000009696+ * @ccid3hctx_s - Packet size in bytes9797+ * @ccid3hctx_t_rto - Nofeedback Timer setting in usecs9898+ * @ccid3hctx_t_ipi - Interpacket (send) interval (RFC 3448, 4.6) in usecs9999+ * @ccid3hctx_state - Sender state, one of %ccid3_hc_tx_states100100+ * @ccid3hctx_last_win_count - Last window counter sent101101+ * @ccid3hctx_t_last_win_count - Timestamp of earliest packet102102+ * with last_win_count value sent103103+ * @ccid3hctx_no_feedback_timer - Handle to no feedback timer104104+ * @ccid3hctx_t_ld - Time last doubled during slow start105105+ * @ccid3hctx_t_nom - Nominal send time of next packet106106+ * @ccid3hctx_delta - Send timer delta (RFC 3448, 4.6) in usecs107107+ * @ccid3hctx_hist - Packet history108108+ * @ccid3hctx_options_received - Parsed set of retrieved options81109 */82110struct ccid3_hc_tx_sock {8383- u64 x;8484- u64 x_recv;8585- u32 x_calc;8686- u32 rtt;8787- u16 r_sqmean;8888- u32 p;8989- u32 t_rto;9090- u32 t_ipi;9191- u16 s;9292- bool feedback:1;9393- u8 last_win_count;9494- ktime_t t_last_win_count;9595- struct timer_list no_feedback_timer;9696- ktime_t t_ld;9797- ktime_t t_nom;9898- struct tfrc_tx_hist_entry *hist;111111+ struct tfrc_tx_info ccid3hctx_tfrc;112112+#define ccid3hctx_x ccid3hctx_tfrc.tfrctx_x113113+#define ccid3hctx_x_recv ccid3hctx_tfrc.tfrctx_x_recv114114+#define ccid3hctx_x_calc ccid3hctx_tfrc.tfrctx_x_calc115115+#define ccid3hctx_rtt ccid3hctx_tfrc.tfrctx_rtt116116+#define ccid3hctx_p ccid3hctx_tfrc.tfrctx_p117117+#define ccid3hctx_t_rto ccid3hctx_tfrc.tfrctx_rto118118+#define ccid3hctx_t_ipi ccid3hctx_tfrc.tfrctx_ipi119119+ u16 ccid3hctx_s;120120+ enum ccid3_hc_tx_states ccid3hctx_state:8;121121+ u8 ccid3hctx_last_win_count;122122+ ktime_t ccid3hctx_t_last_win_count;123123+ struct timer_list ccid3hctx_no_feedback_timer;124124+ ktime_t ccid3hctx_t_ld;125125+ ktime_t ccid3hctx_t_nom;126126+ u32 ccid3hctx_delta;127127+ struct tfrc_tx_hist_entry *ccid3hctx_hist;128128+ struct ccid3_options_received ccid3hctx_options_received;99129};100130101131static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)···124116 return hctx;125117}126118127127-128128-enum ccid3_fback_type {129129- CCID3_FBACK_NONE = 0,130130- CCID3_FBACK_INITIAL,131131- CCID3_FBACK_PERIODIC,132132- CCID3_FBACK_PARAM_CHANGE119119+/* TFRC receiver states */120120+enum ccid3_hc_rx_states {121121+ TFRC_RSTATE_NO_DATA = 1,122122+ TFRC_RSTATE_DATA,123123+ TFRC_RSTATE_TERM = 127,133124};134125135126/** struct ccid3_hc_rx_sock - CCID3 receiver half-connection socket136127 *137137- * @last_counter - Tracks window counter (RFC 4342, 8.1)138138- * @feedback - The type of the feedback last sent139139- * @x_recv - Receiver estimate of send rate (RFC 3448, sec. 4.3)140140- * @tstamp_last_feedback - Time at which last feedback was sent141141- * @hist - Packet history (loss detection + RTT sampling)142142- * @li_hist - Loss Interval database143143- * @p_inverse - Inverse of Loss Event Rate (RFC 4342, sec. 8.5)128128+ * @ccid3hcrx_x_recv - Receiver estimate of send rate (RFC 3448 4.3)129129+ * @ccid3hcrx_rtt - Receiver estimate of rtt (non-standard)130130+ * @ccid3hcrx_p - Current loss event rate (RFC 3448 5.4)131131+ * @ccid3hcrx_last_counter - Tracks window counter (RFC 4342, 8.1)132132+ * @ccid3hcrx_state - Receiver state, one of %ccid3_hc_rx_states133133+ * @ccid3hcrx_bytes_recv - Total sum of DCCP payload bytes134134+ * @ccid3hcrx_x_recv - Receiver estimate of send rate (RFC 3448, sec. 4.3)135135+ * @ccid3hcrx_rtt - Receiver estimate of RTT136136+ * @ccid3hcrx_tstamp_last_feedback - Time at which last feedback was sent137137+ * @ccid3hcrx_tstamp_last_ack - Time at which last feedback was sent138138+ * @ccid3hcrx_hist - Packet history (loss detection + RTT sampling)139139+ * @ccid3hcrx_li_hist - Loss Interval database140140+ * @ccid3hcrx_s - Received packet size in bytes141141+ * @ccid3hcrx_pinv - Inverse of Loss Event Rate (RFC 4342, sec. 8.5)144142 */145143struct ccid3_hc_rx_sock {146146- u8 last_counter:4;147147- enum ccid3_fback_type feedback:4;148148- u32 x_recv;149149- ktime_t tstamp_last_feedback;150150- struct tfrc_rx_hist hist;151151- struct tfrc_loss_hist li_hist;152152-#define p_inverse li_hist.i_mean144144+ u8 ccid3hcrx_last_counter:4;145145+ enum ccid3_hc_rx_states ccid3hcrx_state:8;146146+ u32 ccid3hcrx_bytes_recv;147147+ u32 ccid3hcrx_x_recv;148148+ u32 ccid3hcrx_rtt;149149+ ktime_t ccid3hcrx_tstamp_last_feedback;150150+ struct tfrc_rx_hist ccid3hcrx_hist;151151+ struct tfrc_loss_hist ccid3hcrx_li_hist;152152+ u16 ccid3hcrx_s;153153+#define ccid3hcrx_pinv ccid3hcrx_li_hist.i_mean153154};154155155156static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
+14-16
net/dccp/ccids/lib/loss_interval.c
···86868787/**8888 * tfrc_lh_update_i_mean - Update the `open' loss interval I_08989- * This updates I_mean as the sequence numbers increase. As a consequence, the9090- * open loss interval I_0 increases, hence p = W_tot/max(I_tot0, I_tot1)9191- * decreases, and thus there is no need to send renewed feedback.8989+ * For recomputing p: returns `true' if p > p_prev <=> 1/p < 1/p_prev9290 */9393-void tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *skb)9191+u8 tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *skb)9492{9593 struct tfrc_loss_interval *cur = tfrc_lh_peek(lh);9494+ u32 old_i_mean = lh->i_mean;9695 s64 len;97969897 if (cur == NULL) /* not initialised */9999- return;100100-101101- /* FIXME: should probably also count non-data packets (RFC 4342, 6.1) */102102- if (!dccp_data_packet(skb))103103- return;9898+ return 0;10499105100 len = dccp_delta_seqno(cur->li_seqno, DCCP_SKB_CB(skb)->dccpd_seq) + 1;106101107102 if (len - (s64)cur->li_length <= 0) /* duplicate or reordered */108108- return;103103+ return 0;109104110105 if (SUB16(dccp_hdr(skb)->dccph_ccval, cur->li_ccval) > 4)111106 /*···114119 cur->li_is_closed = 1;115120116121 if (tfrc_lh_length(lh) == 1) /* due to RFC 3448, 6.3.1 */117117- return;122122+ return 0;118123119124 cur->li_length = len;120125 tfrc_lh_calc_i_mean(lh);126126+127127+ return (lh->i_mean < old_i_mean);121128}129129+EXPORT_SYMBOL_GPL(tfrc_lh_update_i_mean);122130123131/* Determine if `new_loss' does begin a new loss interval [RFC 4342, 10.2] */124132static inline u8 tfrc_lh_is_new_loss(struct tfrc_loss_interval *cur,···138140 * @sk: Used by @calc_first_li in caller-specific way (subtyping)139141 * Updates I_mean and returns 1 if a new interval has in fact been added to @lh.140142 */141141-bool tfrc_lh_interval_add(struct tfrc_loss_hist *lh, struct tfrc_rx_hist *rh,142142- u32 (*calc_first_li)(struct sock *), struct sock *sk)143143+int tfrc_lh_interval_add(struct tfrc_loss_hist *lh, struct tfrc_rx_hist *rh,144144+ u32 (*calc_first_li)(struct sock *), struct sock *sk)143145{144146 struct tfrc_loss_interval *cur = tfrc_lh_peek(lh), *new;145147146148 if (cur != NULL && !tfrc_lh_is_new_loss(cur, tfrc_rx_hist_loss_prev(rh)))147147- return false;149149+ return 0;148150149151 new = tfrc_lh_demand_next(lh);150152 if (unlikely(new == NULL)) {151153 DCCP_CRIT("Cannot allocate/add loss record.");152152- return false;154154+ return 0;153155 }154156155157 new->li_seqno = tfrc_rx_hist_loss_prev(rh)->tfrchrx_seqno;···167169168170 tfrc_lh_calc_i_mean(lh);169171 }170170- return true;172172+ return 1;171173}172174EXPORT_SYMBOL_GPL(tfrc_lh_interval_add);173175
···4040#include "packet_history.h"4141#include "../../dccp.h"42424343+/**4444+ * tfrc_tx_hist_entry - Simple singly-linked TX history list4545+ * @next: next oldest entry (LIFO order)4646+ * @seqno: sequence number of this entry4747+ * @stamp: send time of packet with sequence number @seqno4848+ */4949+struct tfrc_tx_hist_entry {5050+ struct tfrc_tx_hist_entry *next;5151+ u64 seqno;5252+ ktime_t stamp;5353+};5454+4355/*4456 * Transmitter History Routines4557 */···7159 kmem_cache_destroy(tfrc_tx_hist_slab);7260 tfrc_tx_hist_slab = NULL;7361 }6262+}6363+6464+static struct tfrc_tx_hist_entry *6565+ tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 seqno)6666+{6767+ while (head != NULL && head->seqno != seqno)6868+ head = head->next;6969+7070+ return head;7471}75727673int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno)···11089 *headp = NULL;11190}11291EXPORT_SYMBOL_GPL(tfrc_tx_hist_purge);9292+9393+u32 tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head, const u64 seqno,9494+ const ktime_t now)9595+{9696+ u32 rtt = 0;9797+ struct tfrc_tx_hist_entry *packet = tfrc_tx_hist_find_entry(head, seqno);9898+9999+ if (packet != NULL) {100100+ rtt = ktime_us_delta(now, packet->stamp);101101+ /*102102+ * Garbage-collect older (irrelevant) entries:103103+ */104104+ tfrc_tx_hist_purge(&packet->next);105105+ }106106+107107+ return rtt;108108+}109109+EXPORT_SYMBOL_GPL(tfrc_tx_hist_rtt);110110+113111114112/*115113 * Receiver History Routines···191151}192152EXPORT_SYMBOL_GPL(tfrc_rx_hist_duplicate);193153194194-195195-static void __tfrc_rx_hist_swap(struct tfrc_rx_hist *h, const u8 a, const u8 b)196196-{197197- struct tfrc_rx_hist_entry *tmp = h->ring[a];198198-199199- h->ring[a] = h->ring[b];200200- h->ring[b] = tmp;201201-}202202-203154static void tfrc_rx_hist_swap(struct tfrc_rx_hist *h, const u8 a, const u8 b)204155{205205- __tfrc_rx_hist_swap(h, tfrc_rx_hist_index(h, a),206206- tfrc_rx_hist_index(h, b));207207-}156156+ const u8 idx_a = tfrc_rx_hist_index(h, a),157157+ idx_b = tfrc_rx_hist_index(h, b);158158+ struct tfrc_rx_hist_entry *tmp = h->ring[idx_a];208159209209-/**210210- * tfrc_rx_hist_resume_rtt_sampling - Prepare RX history for RTT sampling211211- * This is called after loss detection has finished, when the history entry212212- * with the index of `loss_count' holds the highest-received sequence number.213213- * RTT sampling requires this information at ring[0] (tfrc_rx_hist_sample_rtt).214214- */215215-static inline void tfrc_rx_hist_resume_rtt_sampling(struct tfrc_rx_hist *h)216216-{217217- __tfrc_rx_hist_swap(h, 0, tfrc_rx_hist_index(h, h->loss_count));218218- h->loss_count = h->loss_start = 0;160160+ h->ring[idx_a] = h->ring[idx_b];161161+ h->ring[idx_b] = tmp;219162}220163221164/*···215192 u64 s0 = tfrc_rx_hist_loss_prev(h)->tfrchrx_seqno,216193 s1 = DCCP_SKB_CB(skb)->dccpd_seq;217194218218- if (!dccp_loss_free(s0, s1, n1)) /* gap between S0 and S1 */195195+ if (!dccp_loss_free(s0, s1, n1)) { /* gap between S0 and S1 */219196 h->loss_count = 1;197197+ tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_entry(h, 1), skb, n1);198198+ }220199}221200222201static void __one_after_loss(struct tfrc_rx_hist *h, struct sk_buff *skb, u32 n2)···240215241216 if (dccp_loss_free(s2, s1, n1)) {242217 /* hole is filled: S0, S2, and S1 are consecutive */243243- tfrc_rx_hist_resume_rtt_sampling(h);218218+ h->loss_count = 0;219219+ h->loss_start = tfrc_rx_hist_index(h, 1);244220 } else245221 /* gap between S2 and S1: just update loss_prev */246222 tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_loss_prev(h), skb, n2);···294268295269 if (dccp_loss_free(s1, s2, n2)) {296270 /* entire hole filled by S0, S3, S1, S2 */297297- tfrc_rx_hist_resume_rtt_sampling(h);271271+ h->loss_start = tfrc_rx_hist_index(h, 2);272272+ h->loss_count = 0;298273 } else {299274 /* gap remains between S1 and S2 */300275 h->loss_start = tfrc_rx_hist_index(h, 1);···339312340313 if (dccp_loss_free(s2, s3, n3)) {341314 /* no gap between S2 and S3: entire hole is filled */342342- tfrc_rx_hist_resume_rtt_sampling(h);315315+ h->loss_start = tfrc_rx_hist_index(h, 3);316316+ h->loss_count = 0;343317 } else {344318 /* gap between S2 and S3 */345319 h->loss_start = tfrc_rx_hist_index(h, 2);···354326}355327356328/**357357- * tfrc_rx_congestion_event - Loss detection and further processing358358- * @h: The non-empty RX history object359359- * @lh: Loss Intervals database to update360360- * @skb: Currently received packet361361- * @ndp: The NDP count belonging to @skb362362- * @first_li: Caller-dependent computation of first loss interval in @lh363363- * @sk: Used by @calc_first_li (see tfrc_lh_interval_add)329329+ * tfrc_rx_handle_loss - Loss detection and further processing330330+ * @h: The non-empty RX history object331331+ * @lh: Loss Intervals database to update332332+ * @skb: Currently received packet333333+ * @ndp: The NDP count belonging to @skb334334+ * @calc_first_li: Caller-dependent computation of first loss interval in @lh335335+ * @sk: Used by @calc_first_li (see tfrc_lh_interval_add)364336 * Chooses action according to pending loss, updates LI database when a new365337 * loss was detected, and does required post-processing. Returns 1 when caller366338 * should send feedback, 0 otherwise.···368340 * records accordingly, the caller should not perform any more RX history369341 * operations when loss_count is greater than 0 after calling this function.370342 */371371-bool tfrc_rx_congestion_event(struct tfrc_rx_hist *h,372372- struct tfrc_loss_hist *lh,373373- struct sk_buff *skb, const u64 ndp,374374- u32 (*first_li)(struct sock *), struct sock *sk)343343+int tfrc_rx_handle_loss(struct tfrc_rx_hist *h,344344+ struct tfrc_loss_hist *lh,345345+ struct sk_buff *skb, const u64 ndp,346346+ u32 (*calc_first_li)(struct sock *), struct sock *sk)375347{376376- bool new_event = false;377377-378378- if (tfrc_rx_hist_duplicate(h, skb))379379- return 0;348348+ int is_new_loss = 0;380349381350 if (h->loss_count == 0) {382351 __do_track_loss(h, skb, ndp);383383- tfrc_rx_hist_sample_rtt(h, skb);384384- tfrc_rx_hist_add_packet(h, skb, ndp);385352 } else if (h->loss_count == 1) {386353 __one_after_loss(h, skb, ndp);387354 } else if (h->loss_count != 2) {···385362 /*386363 * Update Loss Interval database and recycle RX records387364 */388388- new_event = tfrc_lh_interval_add(lh, h, first_li, sk);365365+ is_new_loss = tfrc_lh_interval_add(lh, h, calc_first_li, sk);389366 __three_after_loss(h);390367 }391391-392392- /*393393- * Update moving-average of `s' and the sum of received payload bytes.394394- */395395- if (dccp_data_packet(skb)) {396396- const u32 payload = skb->len - dccp_hdr(skb)->dccph_doff * 4;397397-398398- h->packet_size = tfrc_ewma(h->packet_size, payload, 9);399399- h->bytes_recvd += payload;400400- }401401-402402- /* RFC 3448, 6.1: update I_0, whose growth implies p <= p_prev */403403- if (!new_event)404404- tfrc_lh_update_i_mean(lh, skb);405405-406406- return new_event;368368+ return is_new_loss;407369}408408-EXPORT_SYMBOL_GPL(tfrc_rx_congestion_event);370370+EXPORT_SYMBOL_GPL(tfrc_rx_handle_loss);409371410410-/* Compute the sending rate X_recv measured between feedback intervals */411411-u32 tfrc_rx_hist_x_recv(struct tfrc_rx_hist *h, const u32 last_x_recv)372372+int tfrc_rx_hist_alloc(struct tfrc_rx_hist *h)412373{413413- u64 bytes = h->bytes_recvd, last_rtt = h->rtt_estimate;414414- s64 delta = ktime_to_us(net_timedelta(h->bytes_start));374374+ int i;415375416416- WARN_ON(delta <= 0);417417- /*418418- * Ensure that the sampling interval for X_recv is at least one RTT,419419- * by extending the sampling interval backwards in time, over the last420420- * R_(m-1) seconds, as per rfc3448bis-06, 6.2.421421- * To reduce noise (e.g. when the RTT changes often), this is only422422- * done when delta is smaller than RTT/2.423423- */424424- if (last_x_recv > 0 && delta < last_rtt/2) {425425- tfrc_pr_debug("delta < RTT ==> %ld us < %u us\n",426426- (long)delta, (unsigned)last_rtt);427427-428428- delta = (bytes ? delta : 0) + last_rtt;429429- bytes += div_u64((u64)last_x_recv * last_rtt, USEC_PER_SEC);376376+ for (i = 0; i <= TFRC_NDUPACK; i++) {377377+ h->ring[i] = kmem_cache_alloc(tfrc_rx_hist_slab, GFP_ATOMIC);378378+ if (h->ring[i] == NULL)379379+ goto out_free;430380 }431381432432- if (unlikely(bytes == 0)) {433433- DCCP_WARN("X_recv == 0, using old value of %u\n", last_x_recv);434434- return last_x_recv;382382+ h->loss_count = h->loss_start = 0;383383+ return 0;384384+385385+out_free:386386+ while (i-- != 0) {387387+ kmem_cache_free(tfrc_rx_hist_slab, h->ring[i]);388388+ h->ring[i] = NULL;435389 }436436- return scaled_div32(bytes, delta);390390+ return -ENOBUFS;437391}438438-EXPORT_SYMBOL_GPL(tfrc_rx_hist_x_recv);392392+EXPORT_SYMBOL_GPL(tfrc_rx_hist_alloc);439393440394void tfrc_rx_hist_purge(struct tfrc_rx_hist *h)441395{···426426}427427EXPORT_SYMBOL_GPL(tfrc_rx_hist_purge);428428429429-static int tfrc_rx_hist_alloc(struct tfrc_rx_hist *h)429429+/**430430+ * tfrc_rx_hist_rtt_last_s - reference entry to compute RTT samples against431431+ */432432+static inline struct tfrc_rx_hist_entry *433433+ tfrc_rx_hist_rtt_last_s(const struct tfrc_rx_hist *h)430434{431431- int i;432432-433433- memset(h, 0, sizeof(*h));434434-435435- for (i = 0; i <= TFRC_NDUPACK; i++) {436436- h->ring[i] = kmem_cache_alloc(tfrc_rx_hist_slab, GFP_ATOMIC);437437- if (h->ring[i] == NULL) {438438- tfrc_rx_hist_purge(h);439439- return -ENOBUFS;440440- }441441- }442442- return 0;435435+ return h->ring[0];443436}444437445445-int tfrc_rx_hist_init(struct tfrc_rx_hist *h, struct sock *sk)438438+/**439439+ * tfrc_rx_hist_rtt_prev_s: previously suitable (wrt rtt_last_s) RTT-sampling entry440440+ */441441+static inline struct tfrc_rx_hist_entry *442442+ tfrc_rx_hist_rtt_prev_s(const struct tfrc_rx_hist *h)446443{447447- if (tfrc_rx_hist_alloc(h))448448- return -ENOBUFS;449449- /*450450- * Initialise first entry with GSR to start loss detection as early as451451- * possible. Code using this must not use any other fields. The entry452452- * will be overwritten once the CCID updates its received packets.453453- */454454- tfrc_rx_hist_loss_prev(h)->tfrchrx_seqno = dccp_sk(sk)->dccps_gsr;455455- return 0;444444+ return h->ring[h->rtt_sample_prev];456445}457457-EXPORT_SYMBOL_GPL(tfrc_rx_hist_init);458446459447/**460448 * tfrc_rx_hist_sample_rtt - Sample RTT from timestamp / CCVal461461- * Based on ideas presented in RFC 4342, 8.1. This function expects that no loss462462- * is pending and uses the following history entries (via rtt_sample_prev):463463- * - h->ring[0] contains the most recent history entry prior to @skb;464464- * - h->ring[1] is an unused `dummy' entry when the current difference is 0;449449+ * Based on ideas presented in RFC 4342, 8.1. Returns 0 if it was not able450450+ * to compute a sample with given data - calling function should check this.465451 */466466-void tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h, const struct sk_buff *skb)452452+u32 tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h, const struct sk_buff *skb)467453{468468- struct tfrc_rx_hist_entry *last = h->ring[0];469469- u32 sample, delta_v;454454+ u32 sample = 0,455455+ delta_v = SUB16(dccp_hdr(skb)->dccph_ccval,456456+ tfrc_rx_hist_rtt_last_s(h)->tfrchrx_ccval);470457471471- /*472472- * When not to sample:473473- * - on non-data packets474474- * (RFC 4342, 8.1: CCVal only fully defined for data packets);475475- * - when no data packets have been received yet476476- * (FIXME: using sampled packet size as indicator here);477477- * - as long as there are gaps in the sequence space (pending loss).478478- */479479- if (!dccp_data_packet(skb) || h->packet_size == 0 ||480480- tfrc_rx_hist_loss_pending(h))481481- return;458458+ if (delta_v < 1 || delta_v > 4) { /* unsuitable CCVal delta */459459+ if (h->rtt_sample_prev == 2) { /* previous candidate stored */460460+ sample = SUB16(tfrc_rx_hist_rtt_prev_s(h)->tfrchrx_ccval,461461+ tfrc_rx_hist_rtt_last_s(h)->tfrchrx_ccval);462462+ if (sample)463463+ sample = 4 / sample *464464+ ktime_us_delta(tfrc_rx_hist_rtt_prev_s(h)->tfrchrx_tstamp,465465+ tfrc_rx_hist_rtt_last_s(h)->tfrchrx_tstamp);466466+ else /*467467+ * FIXME: This condition is in principle not468468+ * possible but occurs when CCID is used for469469+ * two-way data traffic. I have tried to trace470470+ * it, but the cause does not seem to be here.471471+ */472472+ DCCP_BUG("please report to dccp@vger.kernel.org"473473+ " => prev = %u, last = %u",474474+ tfrc_rx_hist_rtt_prev_s(h)->tfrchrx_ccval,475475+ tfrc_rx_hist_rtt_last_s(h)->tfrchrx_ccval);476476+ } else if (delta_v < 1) {477477+ h->rtt_sample_prev = 1;478478+ goto keep_ref_for_next_time;479479+ }482480483483- h->rtt_sample_prev = 0; /* reset previous candidate */484484-485485- delta_v = SUB16(dccp_hdr(skb)->dccph_ccval, last->tfrchrx_ccval);486486- if (delta_v == 0) { /* less than RTT/4 difference */487487- h->rtt_sample_prev = 1;488488- return;481481+ } else if (delta_v == 4) /* optimal match */482482+ sample = ktime_to_us(net_timedelta(tfrc_rx_hist_rtt_last_s(h)->tfrchrx_tstamp));483483+ else { /* suboptimal match */484484+ h->rtt_sample_prev = 2;485485+ goto keep_ref_for_next_time;489486 }490490- sample = dccp_sane_rtt(ktime_to_us(net_timedelta(last->tfrchrx_tstamp)));491487492492- if (delta_v <= 4) /* between RTT/4 and RTT */493493- sample *= 4 / delta_v;494494- else if (!(sample < h->rtt_estimate && sample > h->rtt_estimate/2))495495- /*496496- * Optimisation: CCVal difference is greater than 1 RTT, yet the497497- * sample is less than the local RTT estimate; which means that498498- * the RTT estimate is too high.499499- * To avoid noise, it is not done if the sample is below RTT/2.500500- */501501- return;488488+ if (unlikely(sample > DCCP_SANE_RTT_MAX)) {489489+ DCCP_WARN("RTT sample %u too large, using max\n", sample);490490+ sample = DCCP_SANE_RTT_MAX;491491+ }502492503503- /* Use a lower weight than usual to increase responsiveness */504504- h->rtt_estimate = tfrc_ewma(h->rtt_estimate, sample, 5);493493+ h->rtt_sample_prev = 0; /* use current entry as next reference */494494+keep_ref_for_next_time:495495+496496+ return sample;505497}506498EXPORT_SYMBOL_GPL(tfrc_rx_hist_sample_rtt);
+11-67
net/dccp/ccids/lib/packet_history.h
···4040#include <linux/slab.h>4141#include "tfrc.h"42424343-/**4444- * tfrc_tx_hist_entry - Simple singly-linked TX history list4545- * @next: next oldest entry (LIFO order)4646- * @seqno: sequence number of this entry4747- * @stamp: send time of packet with sequence number @seqno4848- */4949-struct tfrc_tx_hist_entry {5050- struct tfrc_tx_hist_entry *next;5151- u64 seqno;5252- ktime_t stamp;5353-};5454-5555-static inline struct tfrc_tx_hist_entry *5656- tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 seqno)5757-{5858- while (head != NULL && head->seqno != seqno)5959- head = head->next;6060- return head;6161-}4343+struct tfrc_tx_hist_entry;62446345extern int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno);6446extern void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp);4747+extern u32 tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head,4848+ const u64 seqno, const ktime_t now);65496650/* Subtraction a-b modulo-16, respects circular wrap-around */6751#define SUB16(a, b) (((a) + 16 - (b)) & 0xF)···7591 * @loss_count: Number of entries in circular history7692 * @loss_start: Movable index (for loss detection)7793 * @rtt_sample_prev: Used during RTT sampling, points to candidate entry7878- * @rtt_estimate: Receiver RTT estimate7979- * @packet_size: Packet size in bytes (as per RFC 3448, 3.1)8080- * @bytes_recvd: Number of bytes received since @bytes_start8181- * @bytes_start: Start time for counting @bytes_recvd8294 */8395struct tfrc_rx_hist {8496 struct tfrc_rx_hist_entry *ring[TFRC_NDUPACK + 1];8597 u8 loss_count:2,8698 loss_start:2;8787- /* Receiver RTT sampling */8899#define rtt_sample_prev loss_start8989- u32 rtt_estimate;9090- /* Receiver sampling of application payload lengths */9191- u32 packet_size,9292- bytes_recvd;9393- ktime_t bytes_start;94100};9510196102/**···124150 return h->loss_count > 0;125151}126152127127-/*128128- * Accessor functions to retrieve parameters sampled by the RX history129129- */130130-static inline u32 tfrc_rx_hist_packet_size(const struct tfrc_rx_hist *h)131131-{132132- if (h->packet_size == 0) {133133- DCCP_WARN("No sample for s, using fallback\n");134134- return TCP_MIN_RCVMSS;135135- }136136- return h->packet_size;137137-138138-}139139-static inline u32 tfrc_rx_hist_rtt(const struct tfrc_rx_hist *h)140140-{141141- if (h->rtt_estimate == 0) {142142- DCCP_WARN("No RTT estimate available, using fallback RTT\n");143143- return DCCP_FALLBACK_RTT;144144- }145145- return h->rtt_estimate;146146-}147147-148148-static inline void tfrc_rx_hist_restart_byte_counter(struct tfrc_rx_hist *h)149149-{150150- h->bytes_recvd = 0;151151- h->bytes_start = ktime_get_real();152152-}153153-154154-extern u32 tfrc_rx_hist_x_recv(struct tfrc_rx_hist *h, const u32 last_x_recv);155155-156156-157153extern void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h,158154 const struct sk_buff *skb, const u64 ndp);159155160156extern int tfrc_rx_hist_duplicate(struct tfrc_rx_hist *h, struct sk_buff *skb);161157162158struct tfrc_loss_hist;163163-extern bool tfrc_rx_congestion_event(struct tfrc_rx_hist *h,164164- struct tfrc_loss_hist *lh,165165- struct sk_buff *skb, const u64 ndp,166166- u32 (*first_li)(struct sock *sk),167167- struct sock *sk);168168-extern void tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h,169169- const struct sk_buff *skb);170170-extern int tfrc_rx_hist_init(struct tfrc_rx_hist *h, struct sock *sk);159159+extern int tfrc_rx_handle_loss(struct tfrc_rx_hist *h,160160+ struct tfrc_loss_hist *lh,161161+ struct sk_buff *skb, const u64 ndp,162162+ u32 (*first_li)(struct sock *sk),163163+ struct sock *sk);164164+extern u32 tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h,165165+ const struct sk_buff *skb);166166+extern int tfrc_rx_hist_alloc(struct tfrc_rx_hist *h);171167extern void tfrc_rx_hist_purge(struct tfrc_rx_hist *h);172168173169#endif /* _DCCP_PKT_HIST_ */
-16
net/dccp/ccids/lib/tfrc.h
···4848}49495050/**5151- * tfrc_scaled_sqrt - Compute scaled integer sqrt(x) for 0 < x < 2^22-15252- * Uses scaling to improve accuracy of the integer approximation of sqrt(). The5353- * scaling factor of 2^10 limits the maximum @sample to 4e6; this is okay for5454- * clamped RTT samples (dccp_sample_rtt).5555- * Should best be used for expressions of type sqrt(x)/sqrt(y), since then the5656- * scaling factor is neutralised. For this purpose, it avoids returning zero.5757- */5858-static inline u16 tfrc_scaled_sqrt(const u32 sample)5959-{6060- const unsigned long non_zero_sample = sample ? : 1;6161-6262- return int_sqrt(non_zero_sample << 10);6363-}6464-6565-/**6651 * tfrc_ewma - Exponentially weighted moving average6752 * @weight: Weight to be used as damping factor, in units of 1/106853 */···58735974extern u32 tfrc_calc_x(u16 s, u32 R, u32 p);6075extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue);6161-extern u32 tfrc_invert_loss_event_rate(u32 loss_event_rate);62766377extern int tfrc_tx_packet_history_init(void);6478extern void tfrc_tx_packet_history_exit(void);
+4-25
net/dccp/ccids/lib/tfrc_equation.c
···632632633633 if (p <= TFRC_CALC_X_SPLIT) { /* 0.0000 < p <= 0.05 */634634 if (p < TFRC_SMALLEST_P) { /* 0.0000 < p < 0.0001 */635635- /*636636- * In the congestion-avoidance phase p decays towards 0637637- * when there are no further losses, so this case is638638- * natural. Truncating to p_min = 0.01% means that the639639- * maximum achievable throughput is limited to about640640- * X_calc_max = 122.4 * s/RTT (see RFC 3448, 3.1); e.g.641641- * with s=1500 bytes, RTT=0.01 s: X_calc_max = 147 Mbps.642642- */643643- tfrc_pr_debug("Value of p (%d) below resolution. "644644- "Substituting %d\n", p, TFRC_SMALLEST_P);635635+ DCCP_WARN("Value of p (%d) below resolution. "636636+ "Substituting %d\n", p, TFRC_SMALLEST_P);645637 index = 0;646638 } else /* 0.0001 <= p <= 0.05 */647639 index = p/TFRC_SMALLEST_P - 1;···658666 result = scaled_div(s, R);659667 return scaled_div32(result, f);660668}669669+661670EXPORT_SYMBOL_GPL(tfrc_calc_x);662671663672/**···693700 index = tfrc_binsearch(fvalue, 0);694701 return (index + 1) * 1000000 / TFRC_CALC_X_ARRSIZE;695702}696696-EXPORT_SYMBOL_GPL(tfrc_calc_x_reverse_lookup);697703698698-/**699699- * tfrc_invert_loss_event_rate - Compute p so that 10^6 corresponds to 100%700700- * When @loss_event_rate is large, there is a chance that p is truncated to 0.701701- * To avoid re-entering slow-start in that case, we set p = TFRC_SMALLEST_P > 0.702702- */703703-u32 tfrc_invert_loss_event_rate(u32 loss_event_rate)704704-{705705- if (loss_event_rate == UINT_MAX) /* see RFC 4342, 8.5 */706706- return 0;707707- if (unlikely(loss_event_rate == 0)) /* map 1/0 into 100% */708708- return 1000000;709709- return max_t(u32, scaled_div(1, loss_event_rate), TFRC_SMALLEST_P);710710-}711711-EXPORT_SYMBOL_GPL(tfrc_invert_loss_event_rate);704704+EXPORT_SYMBOL_GPL(tfrc_calc_x_reverse_lookup);
+27-77
net/dccp/dccp.h
···4242extern int dccp_debug;4343#define dccp_pr_debug(format, a...) DCCP_PR_DEBUG(dccp_debug, format, ##a)4444#define dccp_pr_debug_cat(format, a...) DCCP_PRINTK(dccp_debug, format, ##a)4545-#define dccp_debug(fmt, a...) dccp_pr_debug_cat(KERN_DEBUG fmt, ##a)4645#else4746#define dccp_pr_debug(format, a...)4847#define dccp_pr_debug_cat(format, a...)4949-#define dccp_debug(format, a...)5048#endif51495250extern struct inet_hashinfo dccp_hashinfo;···6163 * - DCCP-Reset with ACK Subheader and 4 bytes of Reset Code fields6264 * Hence a safe upper bound for the maximum option length is 1020-28 = 9926365 */6464-#define MAX_DCCP_SPECIFIC_HEADER (255 * sizeof(uint32_t))6666+#define MAX_DCCP_SPECIFIC_HEADER (255 * sizeof(int))6567#define DCCP_MAX_PACKET_HDR 286668#define DCCP_MAX_OPT_LEN (MAX_DCCP_SPECIFIC_HEADER - DCCP_MAX_PACKET_HDR)6769#define MAX_DCCP_HEADER (MAX_DCCP_SPECIFIC_HEADER + MAX_HEADER)6868-6969-/* Upper bound for initial feature-negotiation overhead (padded to 32 bits) */7070-#define DCCP_FEATNEG_OVERHEAD (32 * sizeof(uint32_t))71707271#define DCCP_TIMEWAIT_LEN (60 * HZ) /* how long to wait to destroy TIME-WAIT7372 * state, about 60 seconds */···8186 */8287#define DCCP_RTO_MAX ((unsigned)(64 * HZ))83888484-/* DCCP base time resolution - 10 microseconds (RFC 4340, 13.1 ... 13.3) */8585-#define DCCP_TIME_RESOLUTION 108686-8789/*8890 * RTT sampling: sanity bounds and fallback RTT value from RFC 4340, section 3.48991 */9090-#define DCCP_SANE_RTT_MIN (10 * DCCP_TIME_RESOLUTION)9292+#define DCCP_SANE_RTT_MIN 1009193#define DCCP_FALLBACK_RTT (USEC_PER_SEC / 5)9294#define DCCP_SANE_RTT_MAX (3 * USEC_PER_SEC)9395···95103extern int sysctl_dccp_request_retries;96104extern int sysctl_dccp_retries1;97105extern int sysctl_dccp_retries2;106106+extern int sysctl_dccp_feat_sequence_window;107107+extern int sysctl_dccp_feat_rx_ccid;108108+extern int sysctl_dccp_feat_tx_ccid;109109+extern int sysctl_dccp_feat_ack_ratio;110110+extern int sysctl_dccp_feat_send_ack_vector;111111+extern int sysctl_dccp_feat_send_ndp_count;98112extern int sysctl_dccp_tx_qlen;99113extern int sysctl_dccp_sync_ratelimit;100114···235237extern void dccp_send_sync(struct sock *sk, const u64 seq,236238 const enum dccp_pkt_type pkt_type);237239238238-/*239239- * TX Packet Dequeueing Interface240240- */241241-extern void dccp_qpolicy_push(struct sock *sk, struct sk_buff *skb);242242-extern bool dccp_qpolicy_full(struct sock *sk);243243-extern void dccp_qpolicy_drop(struct sock *sk, struct sk_buff *skb);244244-extern struct sk_buff *dccp_qpolicy_top(struct sock *sk);245245-extern struct sk_buff *dccp_qpolicy_pop(struct sock *sk);246246-extern bool dccp_qpolicy_param_ok(struct sock *sk, __be32 param);247247-248248-/*249249- * TX Packet Output and TX Timers250250- */251251-extern void dccp_write_xmit(struct sock *sk);240240+extern void dccp_write_xmit(struct sock *sk, int block);252241extern void dccp_write_space(struct sock *sk);253253-extern void dccp_flush_write_queue(struct sock *sk, long *time_budget);254242255243extern void dccp_init_xmit_timers(struct sock *sk);256244static inline void dccp_clear_xmit_timers(struct sock *sk)···252268extern void dccp_set_state(struct sock *sk, const int state);253269extern void dccp_done(struct sock *sk);254270255255-extern int dccp_reqsk_init(struct request_sock *rq, struct dccp_sock const *dp,256256- struct sk_buff const *skb);271271+extern void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb);257272258273extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb);259274···317334extern int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code);318335extern void dccp_send_close(struct sock *sk, const int active);319336extern int dccp_invalid_packet(struct sk_buff *skb);320320-321321-static inline u32 dccp_sane_rtt(long usec_sample)322322-{323323- if (unlikely(usec_sample <= 0 || usec_sample > DCCP_SANE_RTT_MAX))324324- DCCP_WARN("RTT sample %ld out of bounds!\n", usec_sample);325325- return clamp_val(usec_sample, DCCP_SANE_RTT_MIN, DCCP_SANE_RTT_MAX);326326-}327327-extern u32 dccp_sample_rtt(struct sock *sk, long delta);337337+extern u32 dccp_sample_rtt(struct sock *sk, long delta);328338329339static inline int dccp_bad_service_code(const struct sock *sk,330340 const __be32 service)···411435static inline void dccp_update_gsr(struct sock *sk, u64 seq)412436{413437 struct dccp_sock *dp = dccp_sk(sk);438438+ const struct dccp_minisock *dmsk = dccp_msk(sk);414439415440 dp->dccps_gsr = seq;416416- /* Sequence validity window depends on remote Sequence Window (7.5.1) */417417- dp->dccps_swl = SUB48(ADD48(dp->dccps_gsr, 1), dp->dccps_r_seq_win / 4);418418- /*419419- * Adjust SWL so that it is not below ISR. In contrast to RFC 4340,420420- * 7.5.1 we perform this check beyond the initial handshake: W/W' are421421- * always > 32, so for the first W/W' packets in the lifetime of a422422- * connection we always have to adjust SWL.423423- * A second reason why we are doing this is that the window depends on424424- * the feature-remote value of Sequence Window: nothing stops the peer425425- * from updating this value while we are busy adjusting SWL for the426426- * first W packets (we would have to count from scratch again then).427427- * Therefore it is safer to always make sure that the Sequence Window428428- * is not artificially extended by a peer who grows SWL downwards by429429- * continually updating the feature-remote Sequence-Window.430430- * If sequence numbers wrap it is bad luck. But that will take a while431431- * (48 bit), and this measure prevents Sequence-number attacks.432432- */433433- if (before48(dp->dccps_swl, dp->dccps_isr))434434- dp->dccps_swl = dp->dccps_isr;435435- dp->dccps_swh = ADD48(dp->dccps_gsr, (3 * dp->dccps_r_seq_win) / 4);441441+ dccp_set_seqno(&dp->dccps_swl,442442+ dp->dccps_gsr + 1 - (dmsk->dccpms_sequence_window / 4));443443+ dccp_set_seqno(&dp->dccps_swh,444444+ dp->dccps_gsr + (3 * dmsk->dccpms_sequence_window) / 4);436445}437446438447static inline void dccp_update_gss(struct sock *sk, u64 seq)439448{440449 struct dccp_sock *dp = dccp_sk(sk);441450442442- dp->dccps_gss = seq;443443- /* Ack validity window depends on local Sequence Window value (7.5.1) */444444- dp->dccps_awl = SUB48(ADD48(dp->dccps_gss, 1), dp->dccps_l_seq_win);445445- /* Adjust AWL so that it is not below ISS - see comment above for SWL */446446- if (before48(dp->dccps_awl, dp->dccps_iss))447447- dp->dccps_awl = dp->dccps_iss;448448- dp->dccps_awh = dp->dccps_gss;449449-}450450-451451-static inline int dccp_ackvec_pending(const struct sock *sk)452452-{453453- return dccp_sk(sk)->dccps_hc_rx_ackvec != NULL &&454454- !dccp_ackvec_is_empty(dccp_sk(sk)->dccps_hc_rx_ackvec);451451+ dp->dccps_awh = dp->dccps_gss = seq;452452+ dccp_set_seqno(&dp->dccps_awl,453453+ (dp->dccps_gss -454454+ dccp_msk(sk)->dccpms_sequence_window + 1));455455}456456457457static inline int dccp_ack_pending(const struct sock *sk)458458{459459- return dccp_ackvec_pending(sk) || inet_csk_ack_scheduled(sk);459459+ const struct dccp_sock *dp = dccp_sk(sk);460460+ return dp->dccps_timestamp_echo != 0 ||461461+#ifdef CONFIG_IP_DCCP_ACKVEC462462+ (dccp_msk(sk)->dccpms_send_ack_vector &&463463+ dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) ||464464+#endif465465+ inet_csk_ack_scheduled(sk);460466}461461-462462-extern int dccp_feat_signal_nn_change(struct sock *sk, u8 feat, u64 nn_val);463463-extern int dccp_feat_finalise_settings(struct dccp_sock *dp);464464-extern int dccp_feat_server_ccid_dependencies(struct dccp_request_sock *dreq);465465-extern int dccp_feat_insert_opts(struct dccp_sock*, struct dccp_request_sock*,466466- struct sk_buff *skb);467467-extern int dccp_feat_activate_values(struct sock *sk, struct list_head *fn);468468-extern void dccp_feat_list_purge(struct list_head *fn_list);469467470468extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb);471469extern int dccp_insert_options_rsk(struct dccp_request_sock*, struct sk_buff*);
+1-1
net/dccp/diag.c
···2929 info->tcpi_backoff = icsk->icsk_backoff;3030 info->tcpi_pmtu = icsk->icsk_pmtu_cookie;31313232- if (dp->dccps_hc_rx_ackvec != NULL)3232+ if (dccp_msk(sk)->dccpms_send_ack_vector)3333 info->tcpi_options |= TCPI_OPT_SACK;34343535 ccid_hc_rx_get_info(dp->dccps_hc_rx_ccid, sk, info);
+555-1438
net/dccp/feat.c
···11/*22 * net/dccp/feat.c33 *44- * Feature negotiation for the DCCP protocol (RFC 4340, section 6)55- *66- * Copyright (c) 2008 The University of Aberdeen, Scotland, UK77- * Copyright (c) 2008 Gerrit Renker <gerrit@erg.abdn.ac.uk>88- * Rewrote from scratch, some bits from earlier code by99- * Copyright (c) 2005 Andrea Bittau <a.bittau@cs.ucl.ac.uk>1010- *44+ * An implementation of the DCCP protocol55+ * Andrea Bittau <a.bittau@cs.ucl.ac.uk>116 *127 * ASSUMPTIONS138 * -----------1414- * o Feature negotiation is coordinated with connection setup (as in TCP), wild1515- * changes of parameters of an established connection are not supported.1616- * o Changing NN values (Ack Ratio only) is supported in state OPEN/PARTOPEN.179 * o All currently known SP features have 1-byte quantities. If in the future1810 * extensions of RFCs 4340..42 define features with item lengths larger than1911 * one byte, a feature-specific extension of the code will be required.···1523 * as published by the Free Software Foundation; either version1624 * 2 of the License, or (at your option) any later version.1725 */2626+1827#include <linux/module.h>2828+1929#include "ccid.h"2030#include "feat.h"21312222-/* feature-specific sysctls - initialised to the defaults from RFC 4340, 6.4 */2323-unsigned long sysctl_dccp_sequence_window __read_mostly = 100;2424-int sysctl_dccp_rx_ccid __read_mostly = 2,2525- sysctl_dccp_tx_ccid __read_mostly = 2;3232+#define DCCP_FEAT_SP_NOAGREE (-123)26332727-/*2828- * Feature activation handlers.2929- *3030- * These all use an u64 argument, to provide enough room for NN/SP features. At3131- * this stage the negotiated values have been checked to be within their range.3232- */3333-static int dccp_hdlr_ccid(struct sock *sk, u64 ccid, bool rx)3434+int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,3535+ u8 *val, u8 len, gfp_t gfp)3636+{3737+ struct dccp_opt_pend *opt;3838+3939+ dccp_feat_debug(type, feature, *val);4040+4141+ if (len > 3) {4242+ DCCP_WARN("invalid length %d\n", len);4343+ return -EINVAL;4444+ }4545+ /* XXX add further sanity checks */4646+4747+ /* check if that feature is already being negotiated */4848+ list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {4949+ /* ok we found a negotiation for this option already */5050+ if (opt->dccpop_feat == feature && opt->dccpop_type == type) {5151+ dccp_pr_debug("Replacing old\n");5252+ /* replace */5353+ BUG_ON(opt->dccpop_val == NULL);5454+ kfree(opt->dccpop_val);5555+ opt->dccpop_val = val;5656+ opt->dccpop_len = len;5757+ opt->dccpop_conf = 0;5858+ return 0;5959+ }6060+ }6161+6262+ /* negotiation for a new feature */6363+ opt = kmalloc(sizeof(*opt), gfp);6464+ if (opt == NULL)6565+ return -ENOMEM;6666+6767+ opt->dccpop_type = type;6868+ opt->dccpop_feat = feature;6969+ opt->dccpop_len = len;7070+ opt->dccpop_val = val;7171+ opt->dccpop_conf = 0;7272+ opt->dccpop_sc = NULL;7373+7474+ BUG_ON(opt->dccpop_val == NULL);7575+7676+ list_add_tail(&opt->dccpop_node, &dmsk->dccpms_pending);7777+ return 0;7878+}7979+8080+EXPORT_SYMBOL_GPL(dccp_feat_change);8181+8282+static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr)3483{3584 struct dccp_sock *dp = dccp_sk(sk);3636- struct ccid *new_ccid = ccid_new(ccid, sk, rx, gfp_any());8585+ struct dccp_minisock *dmsk = dccp_msk(sk);8686+ /* figure out if we are changing our CCID or the peer's */8787+ const int rx = type == DCCPO_CHANGE_R;8888+ const u8 ccid_nr = rx ? dmsk->dccpms_rx_ccid : dmsk->dccpms_tx_ccid;8989+ struct ccid *new_ccid;37909191+ /* Check if nothing is being changed. */9292+ if (ccid_nr == new_ccid_nr)9393+ return 0;9494+9595+ new_ccid = ccid_new(new_ccid_nr, sk, rx, GFP_ATOMIC);3896 if (new_ccid == NULL)3997 return -ENOMEM;40984199 if (rx) {42100 ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);43101 dp->dccps_hc_rx_ccid = new_ccid;102102+ dmsk->dccpms_rx_ccid = new_ccid_nr;44103 } else {45104 ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);46105 dp->dccps_hc_tx_ccid = new_ccid;106106+ dmsk->dccpms_tx_ccid = new_ccid_nr;107107+ }108108+109109+ return 0;110110+}111111+112112+static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val)113113+{114114+ dccp_feat_debug(type, feat, val);115115+116116+ switch (feat) {117117+ case DCCPF_CCID:118118+ return dccp_feat_update_ccid(sk, type, val);119119+ default:120120+ dccp_pr_debug("UNIMPLEMENTED: %s(%d, ...)\n",121121+ dccp_feat_typename(type), feat);122122+ break;47123 }48124 return 0;49125}501265151-static int dccp_hdlr_seq_win(struct sock *sk, u64 seq_win, bool rx)127127+static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt,128128+ u8 *rpref, u8 rlen)52129{53130 struct dccp_sock *dp = dccp_sk(sk);131131+ u8 *spref, slen, *res = NULL;132132+ int i, j, rc, agree = 1;541335555- if (rx) {5656- dp->dccps_r_seq_win = seq_win;5757- /* propagate changes to update SWL/SWH */5858- dccp_update_gsr(sk, dp->dccps_gsr);134134+ BUG_ON(rpref == NULL);135135+136136+ /* check if we are the black sheep */137137+ if (dp->dccps_role == DCCP_ROLE_CLIENT) {138138+ spref = rpref;139139+ slen = rlen;140140+ rpref = opt->dccpop_val;141141+ rlen = opt->dccpop_len;59142 } else {6060- dp->dccps_l_seq_win = seq_win;6161- /* propagate changes to update AWL */6262- dccp_update_gss(sk, dp->dccps_gss);143143+ spref = opt->dccpop_val;144144+ slen = opt->dccpop_len;63145 }6464- return 0;6565-}6666-6767-static int dccp_hdlr_ack_ratio(struct sock *sk, u64 ratio, bool rx)6868-{6969-#ifndef __CCID2_COPES_GRACEFULLY_WITH_DYNAMIC_ACK_RATIO_UPDATES__70146 /*7171- * FIXME: This is required until several problems in the CCID-2 code are7272- * resolved. The CCID-2 code currently does not cope well; using dynamic7373- * Ack Ratios greater than 1 caused instabilities. These were manifest7474- * in hangups and long RTO timeouts (1...3 seconds). Until this has been7575- * stabilised, it is safer not to activate dynamic Ack Ratio changes.147147+ * Now we have server preference list in spref and client preference in148148+ * rpref76149 */7777- dccp_pr_debug("Not changing %s Ack Ratio from 1 to %u\n",7878- rx ? "RX" : "TX", (u16)ratio);7979- ratio = 1;8080-#endif8181- if (rx)8282- dccp_sk(sk)->dccps_r_ack_ratio = ratio;150150+ BUG_ON(spref == NULL);151151+ BUG_ON(rpref == NULL);152152+153153+ /* FIXME sanity check vals */154154+155155+ /* Are values in any order? XXX Lame "algorithm" here */156156+ for (i = 0; i < slen; i++) {157157+ for (j = 0; j < rlen; j++) {158158+ if (spref[i] == rpref[j]) {159159+ res = &spref[i];160160+ break;161161+ }162162+ }163163+ if (res)164164+ break;165165+ }166166+167167+ /* we didn't agree on anything */168168+ if (res == NULL) {169169+ /* confirm previous value */170170+ switch (opt->dccpop_feat) {171171+ case DCCPF_CCID:172172+ /* XXX did i get this right? =P */173173+ if (opt->dccpop_type == DCCPO_CHANGE_L)174174+ res = &dccp_msk(sk)->dccpms_tx_ccid;175175+ else176176+ res = &dccp_msk(sk)->dccpms_rx_ccid;177177+ break;178178+179179+ default:180180+ DCCP_BUG("Fell through, feat=%d", opt->dccpop_feat);181181+ /* XXX implement res */182182+ return -EFAULT;183183+ }184184+185185+ dccp_pr_debug("Don't agree... reconfirming %d\n", *res);186186+ agree = 0; /* this is used for mandatory options... */187187+ }188188+189189+ /* need to put result and our preference list */190190+ rlen = 1 + opt->dccpop_len;191191+ rpref = kmalloc(rlen, GFP_ATOMIC);192192+ if (rpref == NULL)193193+ return -ENOMEM;194194+195195+ *rpref = *res;196196+ memcpy(&rpref[1], opt->dccpop_val, opt->dccpop_len);197197+198198+ /* put it in the "confirm queue" */199199+ if (opt->dccpop_sc == NULL) {200200+ opt->dccpop_sc = kmalloc(sizeof(*opt->dccpop_sc), GFP_ATOMIC);201201+ if (opt->dccpop_sc == NULL) {202202+ kfree(rpref);203203+ return -ENOMEM;204204+ }205205+ } else {206206+ /* recycle the confirm slot */207207+ BUG_ON(opt->dccpop_sc->dccpoc_val == NULL);208208+ kfree(opt->dccpop_sc->dccpoc_val);209209+ dccp_pr_debug("recycling confirm slot\n");210210+ }211211+ memset(opt->dccpop_sc, 0, sizeof(*opt->dccpop_sc));212212+213213+ opt->dccpop_sc->dccpoc_val = rpref;214214+ opt->dccpop_sc->dccpoc_len = rlen;215215+216216+ /* update the option on our side [we are about to send the confirm] */217217+ rc = dccp_feat_update(sk, opt->dccpop_type, opt->dccpop_feat, *res);218218+ if (rc) {219219+ kfree(opt->dccpop_sc->dccpoc_val);220220+ kfree(opt->dccpop_sc);221221+ opt->dccpop_sc = NULL;222222+ return rc;223223+ }224224+225225+ dccp_pr_debug("Will confirm %d\n", *rpref);226226+227227+ /* say we want to change to X but we just got a confirm X, suppress our228228+ * change229229+ */230230+ if (!opt->dccpop_conf) {231231+ if (*opt->dccpop_val == *res)232232+ opt->dccpop_conf = 1;233233+ dccp_pr_debug("won't ask for change of same feature\n");234234+ }235235+236236+ return agree ? 0 : DCCP_FEAT_SP_NOAGREE; /* used for mandatory opts */237237+}238238+239239+static int dccp_feat_sp(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)240240+{241241+ struct dccp_minisock *dmsk = dccp_msk(sk);242242+ struct dccp_opt_pend *opt;243243+ int rc = 1;244244+ u8 t;245245+246246+ /*247247+ * We received a CHANGE. We gotta match it against our own preference248248+ * list. If we got a CHANGE_R it means it's a change for us, so we need249249+ * to compare our CHANGE_L list.250250+ */251251+ if (type == DCCPO_CHANGE_L)252252+ t = DCCPO_CHANGE_R;83253 else8484- dccp_sk(sk)->dccps_l_ack_ratio = ratio;254254+ t = DCCPO_CHANGE_L;255255+256256+ /* find our preference list for this feature */257257+ list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {258258+ if (opt->dccpop_type != t || opt->dccpop_feat != feature)259259+ continue;260260+261261+ /* find the winner from the two preference lists */262262+ rc = dccp_feat_reconcile(sk, opt, val, len);263263+ break;264264+ }265265+266266+ /* We didn't deal with the change. This can happen if we have no267267+ * preference list for the feature. In fact, it just shouldn't268268+ * happen---if we understand a feature, we should have a preference list269269+ * with at least the default value.270270+ */271271+ BUG_ON(rc == 1);272272+273273+ return rc;274274+}275275+276276+static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)277277+{278278+ struct dccp_opt_pend *opt;279279+ struct dccp_minisock *dmsk = dccp_msk(sk);280280+ u8 *copy;281281+ int rc;282282+283283+ /* NN features must be Change L (sec. 6.3.2) */284284+ if (type != DCCPO_CHANGE_L) {285285+ dccp_pr_debug("received %s for NN feature %d\n",286286+ dccp_feat_typename(type), feature);287287+ return -EFAULT;288288+ }289289+290290+ /* XXX sanity check opt val */291291+292292+ /* copy option so we can confirm it */293293+ opt = kzalloc(sizeof(*opt), GFP_ATOMIC);294294+ if (opt == NULL)295295+ return -ENOMEM;296296+297297+ copy = kmemdup(val, len, GFP_ATOMIC);298298+ if (copy == NULL) {299299+ kfree(opt);300300+ return -ENOMEM;301301+ }302302+303303+ opt->dccpop_type = DCCPO_CONFIRM_R; /* NN can only confirm R */304304+ opt->dccpop_feat = feature;305305+ opt->dccpop_val = copy;306306+ opt->dccpop_len = len;307307+308308+ /* change feature */309309+ rc = dccp_feat_update(sk, type, feature, *val);310310+ if (rc) {311311+ kfree(opt->dccpop_val);312312+ kfree(opt);313313+ return rc;314314+ }315315+316316+ dccp_feat_debug(type, feature, *copy);317317+318318+ list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf);319319+85320 return 0;86321}873228888-static int dccp_hdlr_ackvec(struct sock *sk, u64 enable, bool rx)323323+static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk,324324+ u8 type, u8 feature)89325{9090- struct dccp_sock *dp = dccp_sk(sk);326326+ /* XXX check if other confirms for that are queued and recycle slot */327327+ struct dccp_opt_pend *opt = kzalloc(sizeof(*opt), GFP_ATOMIC);913289292- if (rx) {9393- if (enable && dp->dccps_hc_rx_ackvec == NULL) {9494- dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(gfp_any());9595- if (dp->dccps_hc_rx_ackvec == NULL)9696- return -ENOMEM;9797- } else if (!enable) {9898- dccp_ackvec_free(dp->dccps_hc_rx_ackvec);9999- dp->dccps_hc_rx_ackvec = NULL;329329+ if (opt == NULL) {330330+ /* XXX what do we do? Ignoring should be fine. It's a change331331+ * after all =P332332+ */333333+ return;334334+ }335335+336336+ switch (type) {337337+ case DCCPO_CHANGE_L:338338+ opt->dccpop_type = DCCPO_CONFIRM_R;339339+ break;340340+ case DCCPO_CHANGE_R:341341+ opt->dccpop_type = DCCPO_CONFIRM_L;342342+ break;343343+ default:344344+ DCCP_WARN("invalid type %d\n", type);345345+ kfree(opt);346346+ return;347347+ }348348+ opt->dccpop_feat = feature;349349+ opt->dccpop_val = NULL;350350+ opt->dccpop_len = 0;351351+352352+ /* change feature */353353+ dccp_pr_debug("Empty %s(%d)\n", dccp_feat_typename(type), feature);354354+355355+ list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf);356356+}357357+358358+static void dccp_feat_flush_confirm(struct sock *sk)359359+{360360+ struct dccp_minisock *dmsk = dccp_msk(sk);361361+ /* Check if there is anything to confirm in the first place */362362+ int yes = !list_empty(&dmsk->dccpms_conf);363363+364364+ if (!yes) {365365+ struct dccp_opt_pend *opt;366366+367367+ list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {368368+ if (opt->dccpop_conf) {369369+ yes = 1;370370+ break;371371+ }100372 }101373 }102102- return 0;374374+375375+ if (!yes)376376+ return;377377+378378+ /* OK there is something to confirm... */379379+ /* XXX check if packet is in flight? Send delayed ack?? */380380+ if (sk->sk_state == DCCP_OPEN)381381+ dccp_send_ack(sk);103382}104383105105-static int dccp_hdlr_ndp(struct sock *sk, u64 enable, bool rx)384384+int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)106385{107107- if (!rx)108108- dccp_sk(sk)->dccps_send_ndp_count = (enable > 0);109109- return 0;110110-}386386+ int rc;111387112112-/*113113- * Minimum Checksum Coverage is located at the RX side (9.2.1). This means that114114- * `rx' holds when the sending peer informs about his partial coverage via a115115- * ChangeR() option. In the other case, we are the sender and the receiver116116- * announces its coverage via ChangeL() options. The policy here is to honour117117- * such communication by enabling the corresponding partial coverage - but only118118- * if it has not been set manually before; the warning here means that all119119- * packets will be dropped.120120- */121121-static int dccp_hdlr_min_cscov(struct sock *sk, u64 cscov, bool rx)122122-{123123- struct dccp_sock *dp = dccp_sk(sk);388388+ dccp_feat_debug(type, feature, *val);124389125125- if (rx)126126- dp->dccps_pcrlen = cscov;127127- else {128128- if (dp->dccps_pcslen == 0)129129- dp->dccps_pcslen = cscov;130130- else if (cscov > dp->dccps_pcslen)131131- DCCP_WARN("CsCov %u too small, peer requires >= %u\n",132132- dp->dccps_pcslen, (u8)cscov);390390+ /* figure out if it's SP or NN feature */391391+ switch (feature) {392392+ /* deal with SP features */393393+ case DCCPF_CCID:394394+ rc = dccp_feat_sp(sk, type, feature, val, len);395395+ break;396396+397397+ /* deal with NN features */398398+ case DCCPF_ACK_RATIO:399399+ rc = dccp_feat_nn(sk, type, feature, val, len);400400+ break;401401+402402+ /* XXX implement other features */403403+ default:404404+ dccp_pr_debug("UNIMPLEMENTED: not handling %s(%d, ...)\n",405405+ dccp_feat_typename(type), feature);406406+ rc = -EFAULT;407407+ break;133408 }134134- return 0;409409+410410+ /* check if there were problems changing features */411411+ if (rc) {412412+ /* If we don't agree on SP, we sent a confirm for old value.413413+ * However we propagate rc to caller in case option was414414+ * mandatory415415+ */416416+ if (rc != DCCP_FEAT_SP_NOAGREE)417417+ dccp_feat_empty_confirm(dccp_msk(sk), type, feature);418418+ }419419+420420+ /* generate the confirm [if required] */421421+ dccp_feat_flush_confirm(sk);422422+423423+ return rc;135424}136425137137-static const struct {138138- u8 feat_num; /* DCCPF_xxx */139139- enum dccp_feat_type rxtx; /* RX or TX */140140- enum dccp_feat_type reconciliation; /* SP or NN */141141- u8 default_value; /* as in 6.4 */142142- int (*activation_hdlr)(struct sock *sk, u64 val, bool rx);143143-/*144144- * Lookup table for location and type of features (from RFC 4340/4342)145145- * +--------------------------+----+-----+----+----+---------+-----------+146146- * | Feature | Location | Reconc. | Initial | Section |147147- * | | RX | TX | SP | NN | Value | Reference |148148- * +--------------------------+----+-----+----+----+---------+-----------+149149- * | DCCPF_CCID | | X | X | | 2 | 10 |150150- * | DCCPF_SHORT_SEQNOS | | X | X | | 0 | 7.6.1 |151151- * | DCCPF_SEQUENCE_WINDOW | | X | | X | 100 | 7.5.2 |152152- * | DCCPF_ECN_INCAPABLE | X | | X | | 0 | 12.1 |153153- * | DCCPF_ACK_RATIO | | X | | X | 2 | 11.3 |154154- * | DCCPF_SEND_ACK_VECTOR | X | | X | | 0 | 11.5 |155155- * | DCCPF_SEND_NDP_COUNT | | X | X | | 0 | 7.7.2 |156156- * | DCCPF_MIN_CSUM_COVER | X | | X | | 0 | 9.2.1 |157157- * | DCCPF_DATA_CHECKSUM | X | | X | | 0 | 9.3.1 |158158- * | DCCPF_SEND_LEV_RATE | X | | X | | 0 | 4342/8.4 |159159- * +--------------------------+----+-----+----+----+---------+-----------+160160- */161161-} dccp_feat_table[] = {162162- { DCCPF_CCID, FEAT_AT_TX, FEAT_SP, 2, dccp_hdlr_ccid },163163- { DCCPF_SHORT_SEQNOS, FEAT_AT_TX, FEAT_SP, 0, NULL },164164- { DCCPF_SEQUENCE_WINDOW, FEAT_AT_TX, FEAT_NN, 100, dccp_hdlr_seq_win },165165- { DCCPF_ECN_INCAPABLE, FEAT_AT_RX, FEAT_SP, 0, NULL },166166- { DCCPF_ACK_RATIO, FEAT_AT_TX, FEAT_NN, 2, dccp_hdlr_ack_ratio},167167- { DCCPF_SEND_ACK_VECTOR, FEAT_AT_RX, FEAT_SP, 0, dccp_hdlr_ackvec },168168- { DCCPF_SEND_NDP_COUNT, FEAT_AT_TX, FEAT_SP, 0, dccp_hdlr_ndp },169169- { DCCPF_MIN_CSUM_COVER, FEAT_AT_RX, FEAT_SP, 0, dccp_hdlr_min_cscov},170170- { DCCPF_DATA_CHECKSUM, FEAT_AT_RX, FEAT_SP, 0, NULL },171171- { DCCPF_SEND_LEV_RATE, FEAT_AT_RX, FEAT_SP, 0, NULL },172172-};173173-#define DCCP_FEAT_SUPPORTED_MAX ARRAY_SIZE(dccp_feat_table)426426+EXPORT_SYMBOL_GPL(dccp_feat_change_recv);174427175175-/**176176- * dccp_feat_index - Hash function to map feature number into array position177177- * Returns consecutive array index or -1 if the feature is not understood.178178- */179179-static int dccp_feat_index(u8 feat_num)428428+int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature,429429+ u8 *val, u8 len)180430{181181- /* The first 9 entries are occupied by the types from RFC 4340, 6.4 */182182- if (feat_num > DCCPF_RESERVED && feat_num <= DCCPF_DATA_CHECKSUM)183183- return feat_num - 1;431431+ u8 t;432432+ struct dccp_opt_pend *opt;433433+ struct dccp_minisock *dmsk = dccp_msk(sk);434434+ int found = 0;435435+ int all_confirmed = 1;184436185185- /*186186- * Other features: add cases for new feature types here after adding187187- * them to the above table.437437+ dccp_feat_debug(type, feature, *val);438438+439439+ /* locate our change request */440440+ switch (type) {441441+ case DCCPO_CONFIRM_L: t = DCCPO_CHANGE_R; break;442442+ case DCCPO_CONFIRM_R: t = DCCPO_CHANGE_L; break;443443+ default: DCCP_WARN("invalid type %d\n", type);444444+ return 1;445445+446446+ }447447+ /* XXX sanity check feature value */448448+449449+ list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {450450+ if (!opt->dccpop_conf && opt->dccpop_type == t &&451451+ opt->dccpop_feat == feature) {452452+ found = 1;453453+ dccp_pr_debug("feature %d found\n", opt->dccpop_feat);454454+455455+ /* XXX do sanity check */456456+457457+ opt->dccpop_conf = 1;458458+459459+ /* We got a confirmation---change the option */460460+ dccp_feat_update(sk, opt->dccpop_type,461461+ opt->dccpop_feat, *val);462462+463463+ /* XXX check the return value of dccp_feat_update */464464+ break;465465+ }466466+467467+ if (!opt->dccpop_conf)468468+ all_confirmed = 0;469469+ }470470+471471+ /* fix re-transmit timer */472472+ /* XXX gotta make sure that no option negotiation occurs during473473+ * connection shutdown. Consider that the CLOSEREQ is sent and timer is474474+ * on. if all options are confirmed it might kill timer which should475475+ * remain alive until close is received.188476 */189189- switch (feat_num) {190190- case DCCPF_SEND_LEV_RATE:191191- return DCCP_FEAT_SUPPORTED_MAX - 1;477477+ if (all_confirmed) {478478+ dccp_pr_debug("clear feat negotiation timer %p\n", sk);479479+ inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);192480 }193193- return -1;481481+482482+ if (!found)483483+ dccp_pr_debug("%s(%d, ...) never requested\n",484484+ dccp_feat_typename(type), feature);485485+ return 0;194486}195487196196-static u8 dccp_feat_type(u8 feat_num)488488+EXPORT_SYMBOL_GPL(dccp_feat_confirm_recv);489489+490490+void dccp_feat_clean(struct dccp_minisock *dmsk)197491{198198- int idx = dccp_feat_index(feat_num);492492+ struct dccp_opt_pend *opt, *next;199493200200- if (idx < 0)201201- return FEAT_UNKNOWN;202202- return dccp_feat_table[idx].reconciliation;494494+ list_for_each_entry_safe(opt, next, &dmsk->dccpms_pending,495495+ dccpop_node) {496496+ BUG_ON(opt->dccpop_val == NULL);497497+ kfree(opt->dccpop_val);498498+499499+ if (opt->dccpop_sc != NULL) {500500+ BUG_ON(opt->dccpop_sc->dccpoc_val == NULL);501501+ kfree(opt->dccpop_sc->dccpoc_val);502502+ kfree(opt->dccpop_sc);503503+ }504504+505505+ kfree(opt);506506+ }507507+ INIT_LIST_HEAD(&dmsk->dccpms_pending);508508+509509+ list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) {510510+ BUG_ON(opt == NULL);511511+ if (opt->dccpop_val != NULL)512512+ kfree(opt->dccpop_val);513513+ kfree(opt);514514+ }515515+ INIT_LIST_HEAD(&dmsk->dccpms_conf);203516}204517205205-static int dccp_feat_default_value(u8 feat_num)206206-{207207- int idx = dccp_feat_index(feat_num);518518+EXPORT_SYMBOL_GPL(dccp_feat_clean);208519209209- return idx < 0 ? : dccp_feat_table[idx].default_value;210210-}211211-212212-/*213213- * Debugging and verbose-printing section520520+/* this is to be called only when a listening sock creates its child. It is521521+ * assumed by the function---the confirm is not duplicated, but rather it is522522+ * "passed on".214523 */215215-static const char *dccp_feat_fname(const u8 feat)524524+int dccp_feat_clone(struct sock *oldsk, struct sock *newsk)525525+{526526+ struct dccp_minisock *olddmsk = dccp_msk(oldsk);527527+ struct dccp_minisock *newdmsk = dccp_msk(newsk);528528+ struct dccp_opt_pend *opt;529529+ int rc = 0;530530+531531+ INIT_LIST_HEAD(&newdmsk->dccpms_pending);532532+ INIT_LIST_HEAD(&newdmsk->dccpms_conf);533533+534534+ list_for_each_entry(opt, &olddmsk->dccpms_pending, dccpop_node) {535535+ struct dccp_opt_pend *newopt;536536+ /* copy the value of the option */537537+ u8 *val = kmemdup(opt->dccpop_val, opt->dccpop_len, GFP_ATOMIC);538538+539539+ if (val == NULL)540540+ goto out_clean;541541+542542+ newopt = kmemdup(opt, sizeof(*newopt), GFP_ATOMIC);543543+ if (newopt == NULL) {544544+ kfree(val);545545+ goto out_clean;546546+ }547547+548548+ /* insert the option */549549+ newopt->dccpop_val = val;550550+ list_add_tail(&newopt->dccpop_node, &newdmsk->dccpms_pending);551551+552552+ /* XXX what happens with backlogs and multiple connections at553553+ * once...554554+ */555555+ /* the master socket no longer needs to worry about confirms */556556+ opt->dccpop_sc = NULL; /* it's not a memleak---new socket has it */557557+558558+ /* reset state for a new socket */559559+ opt->dccpop_conf = 0;560560+ }561561+562562+ /* XXX not doing anything about the conf queue */563563+564564+out:565565+ return rc;566566+567567+out_clean:568568+ dccp_feat_clean(newdmsk);569569+ rc = -ENOMEM;570570+ goto out;571571+}572572+573573+EXPORT_SYMBOL_GPL(dccp_feat_clone);574574+575575+static int __dccp_feat_init(struct dccp_minisock *dmsk, u8 type, u8 feat,576576+ u8 *val, u8 len)577577+{578578+ int rc = -ENOMEM;579579+ u8 *copy = kmemdup(val, len, GFP_KERNEL);580580+581581+ if (copy != NULL) {582582+ rc = dccp_feat_change(dmsk, type, feat, copy, len, GFP_KERNEL);583583+ if (rc)584584+ kfree(copy);585585+ }586586+ return rc;587587+}588588+589589+int dccp_feat_init(struct dccp_minisock *dmsk)590590+{591591+ int rc;592592+593593+ INIT_LIST_HEAD(&dmsk->dccpms_pending);594594+ INIT_LIST_HEAD(&dmsk->dccpms_conf);595595+596596+ /* CCID L */597597+ rc = __dccp_feat_init(dmsk, DCCPO_CHANGE_L, DCCPF_CCID,598598+ &dmsk->dccpms_tx_ccid, 1);599599+ if (rc)600600+ goto out;601601+602602+ /* CCID R */603603+ rc = __dccp_feat_init(dmsk, DCCPO_CHANGE_R, DCCPF_CCID,604604+ &dmsk->dccpms_rx_ccid, 1);605605+ if (rc)606606+ goto out;607607+608608+ /* Ack ratio */609609+ rc = __dccp_feat_init(dmsk, DCCPO_CHANGE_L, DCCPF_ACK_RATIO,610610+ &dmsk->dccpms_ack_ratio, 1);611611+out:612612+ return rc;613613+}614614+615615+EXPORT_SYMBOL_GPL(dccp_feat_init);616616+617617+#ifdef CONFIG_IP_DCCP_DEBUG618618+const char *dccp_feat_typename(const u8 type)619619+{620620+ switch(type) {621621+ case DCCPO_CHANGE_L: return("ChangeL");622622+ case DCCPO_CONFIRM_L: return("ConfirmL");623623+ case DCCPO_CHANGE_R: return("ChangeR");624624+ case DCCPO_CONFIRM_R: return("ConfirmR");625625+ /* the following case must not appear in feature negotation */626626+ default: dccp_pr_debug("unknown type %d [BUG!]\n", type);627627+ }628628+ return NULL;629629+}630630+631631+EXPORT_SYMBOL_GPL(dccp_feat_typename);632632+633633+const char *dccp_feat_name(const u8 feat)216634{217635 static const char *feature_names[] = {218636 [DCCPF_RESERVED] = "Reserved",···639237 if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC)640238 return feature_names[DCCPF_RESERVED];641239642642- if (feat == DCCPF_SEND_LEV_RATE)643643- return "Send Loss Event Rate";644240 if (feat >= DCCPF_MIN_CCID_SPECIFIC)645241 return "CCID-specific";646242647243 return feature_names[feat];648244}649245650650-static const char *dccp_feat_sname[] = { "DEFAULT", "INITIALISING", "CHANGING",651651- "UNSTABLE", "STABLE" };652652-653653-#ifdef CONFIG_IP_DCCP_DEBUG654654-static const char *dccp_feat_oname(const u8 opt)655655-{656656- switch (opt) {657657- case DCCPO_CHANGE_L: return "Change_L";658658- case DCCPO_CONFIRM_L: return "Confirm_L";659659- case DCCPO_CHANGE_R: return "Change_R";660660- case DCCPO_CONFIRM_R: return "Confirm_R";661661- }662662- return NULL;663663-}664664-665665-static void dccp_feat_printval(u8 feat_num, dccp_feat_val const *val)666666-{667667- u8 i, type = dccp_feat_type(feat_num);668668-669669- if (val == NULL || (type == FEAT_SP && val->sp.vec == NULL))670670- dccp_pr_debug_cat("(NULL)");671671- else if (type == FEAT_SP)672672- for (i = 0; i < val->sp.len; i++)673673- dccp_pr_debug_cat("%s%u", i ? " " : "", val->sp.vec[i]);674674- else if (type == FEAT_NN)675675- dccp_pr_debug_cat("%llu", (unsigned long long)val->nn);676676- else677677- dccp_pr_debug_cat("unknown type %u", type);678678-}679679-680680-static void dccp_feat_printvals(u8 feat_num, u8 *list, u8 len)681681-{682682- u8 type = dccp_feat_type(feat_num);683683- dccp_feat_val fval = { .sp.vec = list, .sp.len = len };684684-685685- if (type == FEAT_NN)686686- fval.nn = dccp_decode_value_var(list, len);687687- dccp_feat_printval(feat_num, &fval);688688-}689689-690690-static void dccp_feat_print_entry(struct dccp_feat_entry const *entry)691691-{692692- dccp_debug(" * %s %s = ", entry->is_local ? "local" : "remote",693693- dccp_feat_fname(entry->feat_num));694694- dccp_feat_printval(entry->feat_num, &entry->val);695695- dccp_pr_debug_cat(", state=%s %s\n", dccp_feat_sname[entry->state],696696- entry->needs_confirm ? "(Confirm pending)" : "");697697-}698698-699699-#define dccp_feat_print_opt(opt, feat, val, len, mandatory) do { \700700- dccp_pr_debug("%s(%s, ", dccp_feat_oname(opt), dccp_feat_fname(feat));\701701- dccp_feat_printvals(feat, val, len); \702702- dccp_pr_debug_cat(") %s\n", mandatory ? "!" : ""); } while (0)703703-704704-#define dccp_feat_print_fnlist(fn_list) { \705705- const struct dccp_feat_entry *___entry; \706706- \707707- dccp_pr_debug("List Dump:\n"); \708708- list_for_each_entry(___entry, fn_list, node) \709709- dccp_feat_print_entry(___entry); \710710-}711711-#else /* ! CONFIG_IP_DCCP_DEBUG */712712-#define dccp_feat_print_opt(opt, feat, val, len, mandatory)713713-#define dccp_feat_print_fnlist(fn_list)714714-#endif715715-716716-static int __dccp_feat_activate(struct sock *sk, const int idx,717717- const bool is_local, dccp_feat_val const *fval)718718-{719719- bool rx;720720- u64 val;721721-722722- if (idx < 0 || idx >= DCCP_FEAT_SUPPORTED_MAX)723723- return -1;724724- if (dccp_feat_table[idx].activation_hdlr == NULL)725725- return 0;726726-727727- if (fval == NULL) {728728- val = dccp_feat_table[idx].default_value;729729- } else if (dccp_feat_table[idx].reconciliation == FEAT_SP) {730730- if (fval->sp.vec == NULL) {731731- /*732732- * This can happen when an empty Confirm is sent733733- * for an SP (i.e. known) feature. In this case734734- * we would be using the default anyway.735735- */736736- DCCP_CRIT("Feature #%d undefined: using default", idx);737737- val = dccp_feat_table[idx].default_value;738738- } else {739739- val = fval->sp.vec[0];740740- }741741- } else {742742- val = fval->nn;743743- }744744-745745- /* Location is RX if this is a local-RX or remote-TX feature */746746- rx = (is_local == (dccp_feat_table[idx].rxtx == FEAT_AT_RX));747747-748748- dccp_debug(" -> activating %s %s, %sval=%llu\n", rx ? "RX" : "TX",749749- dccp_feat_fname(dccp_feat_table[idx].feat_num),750750- fval ? "" : "default ", (unsigned long long)val);751751-752752- return dccp_feat_table[idx].activation_hdlr(sk, val, rx);753753-}754754-755755-/**756756- * dccp_feat_activate - Activate feature value on socket757757- * @sk: fully connected DCCP socket (after handshake is complete)758758- * @feat_num: feature to activate, one of %dccp_feature_numbers759759- * @local: whether local (1) or remote (0) @feat_num is meant760760- * @fval: the value (SP or NN) to activate, or NULL to use the default value761761- * For general use this function is preferable over __dccp_feat_activate().762762- */763763-static int dccp_feat_activate(struct sock *sk, u8 feat_num, bool local,764764- dccp_feat_val const *fval)765765-{766766- return __dccp_feat_activate(sk, dccp_feat_index(feat_num), local, fval);767767-}768768-769769-/* Test for "Req'd" feature (RFC 4340, 6.4) */770770-static inline int dccp_feat_must_be_understood(u8 feat_num)771771-{772772- return feat_num == DCCPF_CCID || feat_num == DCCPF_SHORT_SEQNOS ||773773- feat_num == DCCPF_SEQUENCE_WINDOW;774774-}775775-776776-/* copy constructor, fval must not already contain allocated memory */777777-static int dccp_feat_clone_sp_val(dccp_feat_val *fval, u8 const *val, u8 len)778778-{779779- fval->sp.len = len;780780- if (fval->sp.len > 0) {781781- fval->sp.vec = kmemdup(val, len, gfp_any());782782- if (fval->sp.vec == NULL) {783783- fval->sp.len = 0;784784- return -ENOBUFS;785785- }786786- }787787- return 0;788788-}789789-790790-static void dccp_feat_val_destructor(u8 feat_num, dccp_feat_val *val)791791-{792792- if (unlikely(val == NULL))793793- return;794794- if (dccp_feat_type(feat_num) == FEAT_SP)795795- kfree(val->sp.vec);796796- memset(val, 0, sizeof(*val));797797-}798798-799799-static struct dccp_feat_entry *800800- dccp_feat_clone_entry(struct dccp_feat_entry const *original)801801-{802802- struct dccp_feat_entry *new;803803- u8 type = dccp_feat_type(original->feat_num);804804-805805- if (type == FEAT_UNKNOWN)806806- return NULL;807807-808808- new = kmemdup(original, sizeof(struct dccp_feat_entry), gfp_any());809809- if (new == NULL)810810- return NULL;811811-812812- if (type == FEAT_SP && dccp_feat_clone_sp_val(&new->val,813813- original->val.sp.vec,814814- original->val.sp.len)) {815815- kfree(new);816816- return NULL;817817- }818818- return new;819819-}820820-821821-static void dccp_feat_entry_destructor(struct dccp_feat_entry *entry)822822-{823823- if (entry != NULL) {824824- dccp_feat_val_destructor(entry->feat_num, &entry->val);825825- kfree(entry);826826- }827827-}828828-829829-/*830830- * List management functions831831- *832832- * Feature negotiation lists rely on and maintain the following invariants:833833- * - each feat_num in the list is known, i.e. we know its type and default value834834- * - each feat_num/is_local combination is unique (old entries are overwritten)835835- * - SP values are always freshly allocated836836- * - list is sorted in increasing order of feature number (faster lookup)837837- */838838-static struct dccp_feat_entry *dccp_feat_list_lookup(struct list_head *fn_list,839839- u8 feat_num, bool is_local)840840-{841841- struct dccp_feat_entry *entry;842842-843843- list_for_each_entry(entry, fn_list, node)844844- if (entry->feat_num == feat_num && entry->is_local == is_local)845845- return entry;846846- else if (entry->feat_num > feat_num)847847- break;848848- return NULL;849849-}850850-851851-/**852852- * dccp_feat_entry_new - Central list update routine (called by all others)853853- * @head: list to add to854854- * @feat: feature number855855- * @local: whether the local (1) or remote feature with number @feat is meant856856- * This is the only constructor and serves to ensure the above invariants.857857- */858858-static struct dccp_feat_entry *859859- dccp_feat_entry_new(struct list_head *head, u8 feat, bool local)860860-{861861- struct dccp_feat_entry *entry;862862-863863- list_for_each_entry(entry, head, node)864864- if (entry->feat_num == feat && entry->is_local == local) {865865- dccp_feat_val_destructor(entry->feat_num, &entry->val);866866- return entry;867867- } else if (entry->feat_num > feat) {868868- head = &entry->node;869869- break;870870- }871871-872872- entry = kmalloc(sizeof(*entry), gfp_any());873873- if (entry != NULL) {874874- entry->feat_num = feat;875875- entry->is_local = local;876876- list_add_tail(&entry->node, head);877877- }878878- return entry;879879-}880880-881881-/**882882- * dccp_feat_push_change - Add/overwrite a Change option in the list883883- * @fn_list: feature-negotiation list to update884884- * @feat: one of %dccp_feature_numbers885885- * @local: whether local (1) or remote (0) @feat_num is meant886886- * @needs_mandatory: whether to use Mandatory feature negotiation options887887- * @fval: pointer to NN/SP value to be inserted (will be copied)888888- */889889-static int dccp_feat_push_change(struct list_head *fn_list, u8 feat, u8 local,890890- u8 mandatory, dccp_feat_val *fval)891891-{892892- struct dccp_feat_entry *new = dccp_feat_entry_new(fn_list, feat, local);893893-894894- if (new == NULL)895895- return -ENOMEM;896896-897897- new->feat_num = feat;898898- new->is_local = local;899899- new->state = FEAT_INITIALISING;900900- new->needs_confirm = 0;901901- new->empty_confirm = 0;902902- new->val = *fval;903903- new->needs_mandatory = mandatory;904904-905905- return 0;906906-}907907-908908-/**909909- * dccp_feat_push_confirm - Add a Confirm entry to the FN list910910- * @fn_list: feature-negotiation list to add to911911- * @feat: one of %dccp_feature_numbers912912- * @local: whether local (1) or remote (0) @feat_num is being confirmed913913- * @fval: pointer to NN/SP value to be inserted or NULL914914- * Returns 0 on success, a Reset code for further processing otherwise.915915- */916916-static int dccp_feat_push_confirm(struct list_head *fn_list, u8 feat, u8 local,917917- dccp_feat_val *fval)918918-{919919- struct dccp_feat_entry *new = dccp_feat_entry_new(fn_list, feat, local);920920-921921- if (new == NULL)922922- return DCCP_RESET_CODE_TOO_BUSY;923923-924924- new->feat_num = feat;925925- new->is_local = local;926926- new->state = FEAT_STABLE; /* transition in 6.6.2 */927927- new->needs_confirm = 1;928928- new->empty_confirm = (fval == NULL);929929- new->val.nn = 0; /* zeroes the whole structure */930930- if (!new->empty_confirm)931931- new->val = *fval;932932- new->needs_mandatory = 0;933933-934934- return 0;935935-}936936-937937-static int dccp_push_empty_confirm(struct list_head *fn_list, u8 feat, u8 local)938938-{939939- return dccp_feat_push_confirm(fn_list, feat, local, NULL);940940-}941941-942942-static inline void dccp_feat_list_pop(struct dccp_feat_entry *entry)943943-{944944- list_del(&entry->node);945945- dccp_feat_entry_destructor(entry);946946-}947947-948948-void dccp_feat_list_purge(struct list_head *fn_list)949949-{950950- struct dccp_feat_entry *entry, *next;951951-952952- list_for_each_entry_safe(entry, next, fn_list, node)953953- dccp_feat_entry_destructor(entry);954954- INIT_LIST_HEAD(fn_list);955955-}956956-EXPORT_SYMBOL_GPL(dccp_feat_list_purge);957957-958958-/* generate @to as full clone of @from - @to must not contain any nodes */959959-int dccp_feat_clone_list(struct list_head const *from, struct list_head *to)960960-{961961- struct dccp_feat_entry *entry, *new;962962-963963- INIT_LIST_HEAD(to);964964- list_for_each_entry(entry, from, node) {965965- new = dccp_feat_clone_entry(entry);966966- if (new == NULL)967967- goto cloning_failed;968968- list_add_tail(&new->node, to);969969- }970970- return 0;971971-972972-cloning_failed:973973- dccp_feat_list_purge(to);974974- return -ENOMEM;975975-}976976-977977-/**978978- * dccp_feat_valid_nn_length - Enforce length constraints on NN options979979- * Length is between 0 and %DCCP_OPTVAL_MAXLEN. Used for outgoing packets only,980980- * incoming options are accepted as long as their values are valid.981981- */982982-static u8 dccp_feat_valid_nn_length(u8 feat_num)983983-{984984- if (feat_num == DCCPF_ACK_RATIO) /* RFC 4340, 11.3 and 6.6.8 */985985- return 2;986986- if (feat_num == DCCPF_SEQUENCE_WINDOW) /* RFC 4340, 7.5.2 and 6.5 */987987- return 6;988988- return 0;989989-}990990-991991-static u8 dccp_feat_is_valid_nn_val(u8 feat_num, u64 val)992992-{993993- switch (feat_num) {994994- case DCCPF_ACK_RATIO:995995- return val <= DCCPF_ACK_RATIO_MAX;996996- case DCCPF_SEQUENCE_WINDOW:997997- return val >= DCCPF_SEQ_WMIN && val <= DCCPF_SEQ_WMAX;998998- }999999- return 0; /* feature unknown - so we can't tell */10001000-}10011001-10021002-/* check that SP values are within the ranges defined in RFC 4340 */10031003-static u8 dccp_feat_is_valid_sp_val(u8 feat_num, u8 val)10041004-{10051005- switch (feat_num) {10061006- case DCCPF_CCID:10071007- return val == DCCPC_CCID2 || val == DCCPC_CCID3;10081008- /* Type-check Boolean feature values: */10091009- case DCCPF_SHORT_SEQNOS:10101010- case DCCPF_ECN_INCAPABLE:10111011- case DCCPF_SEND_ACK_VECTOR:10121012- case DCCPF_SEND_NDP_COUNT:10131013- case DCCPF_DATA_CHECKSUM:10141014- case DCCPF_SEND_LEV_RATE:10151015- return val < 2;10161016- case DCCPF_MIN_CSUM_COVER:10171017- return val < 16;10181018- }10191019- return 0; /* feature unknown */10201020-}10211021-10221022-static u8 dccp_feat_sp_list_ok(u8 feat_num, u8 const *sp_list, u8 sp_len)10231023-{10241024- if (sp_list == NULL || sp_len < 1)10251025- return 0;10261026- while (sp_len--)10271027- if (!dccp_feat_is_valid_sp_val(feat_num, *sp_list++))10281028- return 0;10291029- return 1;10301030-}10311031-10321032-/**10331033- * dccp_feat_insert_opts - Generate FN options from current list state10341034- * @skb: next sk_buff to be sent to the peer10351035- * @dp: for client during handshake and general negotiation10361036- * @dreq: used by the server only (all Changes/Confirms in LISTEN/RESPOND)10371037- */10381038-int dccp_feat_insert_opts(struct dccp_sock *dp, struct dccp_request_sock *dreq,10391039- struct sk_buff *skb)10401040-{10411041- struct list_head *fn = dreq ? &dreq->dreq_featneg : &dp->dccps_featneg;10421042- struct dccp_feat_entry *pos, *next;10431043- u8 opt, type, len, *ptr, nn_in_nbo[DCCP_OPTVAL_MAXLEN];10441044- bool rpt;10451045-10461046- /* put entries into @skb in the order they appear in the list */10471047- list_for_each_entry_safe_reverse(pos, next, fn, node) {10481048- opt = dccp_feat_genopt(pos);10491049- type = dccp_feat_type(pos->feat_num);10501050- rpt = false;10511051-10521052- if (pos->empty_confirm) {10531053- len = 0;10541054- ptr = NULL;10551055- } else {10561056- if (type == FEAT_SP) {10571057- len = pos->val.sp.len;10581058- ptr = pos->val.sp.vec;10591059- rpt = pos->needs_confirm;10601060- } else if (type == FEAT_NN) {10611061- len = dccp_feat_valid_nn_length(pos->feat_num);10621062- ptr = nn_in_nbo;10631063- dccp_encode_value_var(pos->val.nn, ptr, len);10641064- } else {10651065- DCCP_BUG("unknown feature %u", pos->feat_num);10661066- return -1;10671067- }10681068- }10691069- dccp_feat_print_opt(opt, pos->feat_num, ptr, len, 0);10701070-10711071- if (dccp_insert_fn_opt(skb, opt, pos->feat_num, ptr, len, rpt))10721072- return -1;10731073- if (pos->needs_mandatory && dccp_insert_option_mandatory(skb))10741074- return -1;10751075- /*10761076- * Enter CHANGING after transmitting the Change option (6.6.2).10771077- */10781078- if (pos->state == FEAT_INITIALISING)10791079- pos->state = FEAT_CHANGING;10801080- }10811081- return 0;10821082-}10831083-10841084-/**10851085- * __feat_register_nn - Register new NN value on socket10861086- * @fn: feature-negotiation list to register with10871087- * @feat: an NN feature from %dccp_feature_numbers10881088- * @mandatory: use Mandatory option if 110891089- * @nn_val: value to register (restricted to 4 bytes)10901090- * Note that NN features are local by definition (RFC 4340, 6.3.2).10911091- */10921092-static int __feat_register_nn(struct list_head *fn, u8 feat,10931093- u8 mandatory, u64 nn_val)10941094-{10951095- dccp_feat_val fval = { .nn = nn_val };10961096-10971097- if (dccp_feat_type(feat) != FEAT_NN ||10981098- !dccp_feat_is_valid_nn_val(feat, nn_val))10991099- return -EINVAL;11001100-11011101- /* Don't bother with default values, they will be activated anyway. */11021102- if (nn_val - (u64)dccp_feat_default_value(feat) == 0)11031103- return 0;11041104-11051105- return dccp_feat_push_change(fn, feat, 1, mandatory, &fval);11061106-}11071107-11081108-/**11091109- * __feat_register_sp - Register new SP value/list on socket11101110- * @fn: feature-negotiation list to register with11111111- * @feat: an SP feature from %dccp_feature_numbers11121112- * @is_local: whether the local (1) or the remote (0) @feat is meant11131113- * @mandatory: use Mandatory option if 111141114- * @sp_val: SP value followed by optional preference list11151115- * @sp_len: length of @sp_val in bytes11161116- */11171117-static int __feat_register_sp(struct list_head *fn, u8 feat, u8 is_local,11181118- u8 mandatory, u8 const *sp_val, u8 sp_len)11191119-{11201120- dccp_feat_val fval;11211121-11221122- if (dccp_feat_type(feat) != FEAT_SP ||11231123- !dccp_feat_sp_list_ok(feat, sp_val, sp_len))11241124- return -EINVAL;11251125-11261126- /* Avoid negotiating alien CCIDs by only advertising supported ones */11271127- if (feat == DCCPF_CCID && !ccid_support_check(sp_val, sp_len))11281128- return -EOPNOTSUPP;11291129-11301130- if (dccp_feat_clone_sp_val(&fval, sp_val, sp_len))11311131- return -ENOMEM;11321132-11331133- return dccp_feat_push_change(fn, feat, is_local, mandatory, &fval);11341134-}11351135-11361136-/**11371137- * dccp_feat_register_sp - Register requests to change SP feature values11381138- * @sk: client or listening socket11391139- * @feat: one of %dccp_feature_numbers11401140- * @is_local: whether the local (1) or remote (0) @feat is meant11411141- * @list: array of preferred values, in descending order of preference11421142- * @len: length of @list in bytes11431143- */11441144-int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local,11451145- u8 const *list, u8 len)11461146-{ /* any changes must be registered before establishing the connection */11471147- if (sk->sk_state != DCCP_CLOSED)11481148- return -EISCONN;11491149- if (dccp_feat_type(feat) != FEAT_SP)11501150- return -EINVAL;11511151- return __feat_register_sp(&dccp_sk(sk)->dccps_featneg, feat, is_local,11521152- 0, list, len);11531153-}11541154-11551155-/* Analogous to dccp_feat_register_sp(), but for non-negotiable values */11561156-int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val)11571157-{11581158- /* any changes must be registered before establishing the connection */11591159- if (sk->sk_state != DCCP_CLOSED)11601160- return -EISCONN;11611161- if (dccp_feat_type(feat) != FEAT_NN)11621162- return -EINVAL;11631163- return __feat_register_nn(&dccp_sk(sk)->dccps_featneg, feat, 0, val);11641164-}11651165-11661166-/**11671167- * dccp_feat_signal_nn_change - Update NN values for an established connection11681168- * @sk: DCCP socket of an established connection11691169- * @feat: NN feature number from %dccp_feature_numbers11701170- * @nn_val: the new value to use11711171- * This function is used to communicate NN updates out-of-band. The difference11721172- * to feature negotiation during connection setup is that values are activated11731173- * immediately after validation, i.e. we don't wait for the Confirm: either the11741174- * value is accepted by the peer (and then the waiting is futile), or it is not11751175- * (Reset or empty Confirm). We don't accept empty Confirms - transmitted values11761176- * are validated, and the peer "MUST accept any valid value" (RFC 4340, 6.3.2).11771177- */11781178-int dccp_feat_signal_nn_change(struct sock *sk, u8 feat, u64 nn_val)11791179-{11801180- struct list_head *fn = &dccp_sk(sk)->dccps_featneg;11811181- dccp_feat_val fval = { .nn = nn_val };11821182- struct dccp_feat_entry *entry;11831183-11841184- if (sk->sk_state != DCCP_OPEN && sk->sk_state != DCCP_PARTOPEN)11851185- return 0;11861186-11871187- if (dccp_feat_type(feat) != FEAT_NN ||11881188- !dccp_feat_is_valid_nn_val(feat, nn_val))11891189- return -EINVAL;11901190-11911191- entry = dccp_feat_list_lookup(fn, feat, 1);11921192- if (entry != NULL) {11931193- dccp_pr_debug("Ignoring %llu, entry %llu exists in state %s\n",11941194- (unsigned long long)nn_val,11951195- (unsigned long long)entry->val.nn,11961196- dccp_feat_sname[entry->state]);11971197- return 0;11981198- }11991199-12001200- if (dccp_feat_activate(sk, feat, 1, &fval))12011201- return -EADV;12021202-12031203- inet_csk_schedule_ack(sk);12041204- return dccp_feat_push_change(fn, feat, 1, 0, &fval);12051205-}12061206-EXPORT_SYMBOL_GPL(dccp_feat_signal_nn_change);12071207-12081208-/*12091209- * Tracking features whose value depend on the choice of CCID12101210- *12111211- * This is designed with an extension in mind so that a list walk could be done12121212- * before activating any features. However, the existing framework was found to12131213- * work satisfactorily up until now, the automatic verification is left open.12141214- * When adding new CCIDs, add a corresponding dependency table here.12151215- */12161216-static const struct ccid_dependency *dccp_feat_ccid_deps(u8 ccid, bool is_local)12171217-{12181218- static const struct ccid_dependency ccid2_dependencies[2][2] = {12191219- /*12201220- * CCID2 mandates Ack Vectors (RFC 4341, 4.): as CCID is a TX12211221- * feature and Send Ack Vector is an RX feature, `is_local'12221222- * needs to be reversed.12231223- */12241224- { /* Dependencies of the receiver-side (remote) CCID2 */12251225- {12261226- .dependent_feat = DCCPF_SEND_ACK_VECTOR,12271227- .is_local = true,12281228- .is_mandatory = true,12291229- .val = 112301230- },12311231- { 0, 0, 0, 0 }12321232- },12331233- { /* Dependencies of the sender-side (local) CCID2 */12341234- {12351235- .dependent_feat = DCCPF_SEND_ACK_VECTOR,12361236- .is_local = false,12371237- .is_mandatory = true,12381238- .val = 112391239- },12401240- { 0, 0, 0, 0 }12411241- }12421242- };12431243- static const struct ccid_dependency ccid3_dependencies[2][5] = {12441244- { /*12451245- * Dependencies of the receiver-side CCID312461246- */12471247- { /* locally disable Ack Vectors */12481248- .dependent_feat = DCCPF_SEND_ACK_VECTOR,12491249- .is_local = true,12501250- .is_mandatory = false,12511251- .val = 012521252- },12531253- { /* see below why Send Loss Event Rate is on */12541254- .dependent_feat = DCCPF_SEND_LEV_RATE,12551255- .is_local = true,12561256- .is_mandatory = true,12571257- .val = 112581258- },12591259- { /* NDP Count is needed as per RFC 4342, 6.1.1 */12601260- .dependent_feat = DCCPF_SEND_NDP_COUNT,12611261- .is_local = false,12621262- .is_mandatory = true,12631263- .val = 112641264- },12651265- { 0, 0, 0, 0 },12661266- },12671267- { /*12681268- * CCID3 at the TX side: we request that the HC-receiver12691269- * will not send Ack Vectors (they will be ignored, so12701270- * Mandatory is not set); we enable Send Loss Event Rate12711271- * (Mandatory since the implementation does not support12721272- * the Loss Intervals option of RFC 4342, 8.6).12731273- * The last two options are for peer's information only.12741274- */12751275- {12761276- .dependent_feat = DCCPF_SEND_ACK_VECTOR,12771277- .is_local = false,12781278- .is_mandatory = false,12791279- .val = 012801280- },12811281- {12821282- .dependent_feat = DCCPF_SEND_LEV_RATE,12831283- .is_local = false,12841284- .is_mandatory = true,12851285- .val = 112861286- },12871287- { /* this CCID does not support Ack Ratio */12881288- .dependent_feat = DCCPF_ACK_RATIO,12891289- .is_local = true,12901290- .is_mandatory = false,12911291- .val = 012921292- },12931293- { /* tell receiver we are sending NDP counts */12941294- .dependent_feat = DCCPF_SEND_NDP_COUNT,12951295- .is_local = true,12961296- .is_mandatory = false,12971297- .val = 112981298- },12991299- { 0, 0, 0, 0 }13001300- }13011301- };13021302- switch (ccid) {13031303- case DCCPC_CCID2:13041304- return ccid2_dependencies[is_local];13051305- case DCCPC_CCID3:13061306- return ccid3_dependencies[is_local];13071307- default:13081308- return NULL;13091309- }13101310-}13111311-13121312-/**13131313- * dccp_feat_propagate_ccid - Resolve dependencies of features on choice of CCID13141314- * @fn: feature-negotiation list to update13151315- * @id: CCID number to track13161316- * @is_local: whether TX CCID (1) or RX CCID (0) is meant13171317- * This function needs to be called after registering all other features.13181318- */13191319-static int dccp_feat_propagate_ccid(struct list_head *fn, u8 id, bool is_local)13201320-{13211321- const struct ccid_dependency *table = dccp_feat_ccid_deps(id, is_local);13221322- int i, rc = (table == NULL);13231323-13241324- for (i = 0; rc == 0 && table[i].dependent_feat != DCCPF_RESERVED; i++)13251325- if (dccp_feat_type(table[i].dependent_feat) == FEAT_SP)13261326- rc = __feat_register_sp(fn, table[i].dependent_feat,13271327- table[i].is_local,13281328- table[i].is_mandatory,13291329- &table[i].val, 1);13301330- else13311331- rc = __feat_register_nn(fn, table[i].dependent_feat,13321332- table[i].is_mandatory,13331333- table[i].val);13341334- return rc;13351335-}13361336-13371337-/**13381338- * dccp_feat_finalise_settings - Finalise settings before starting negotiation13391339- * @dp: client or listening socket (settings will be inherited)13401340- * This is called after all registrations (socket initialisation, sysctls, and13411341- * sockopt calls), and before sending the first packet containing Change options13421342- * (ie. client-Request or server-Response), to ensure internal consistency.13431343- */13441344-int dccp_feat_finalise_settings(struct dccp_sock *dp)13451345-{13461346- struct list_head *fn = &dp->dccps_featneg;13471347- struct dccp_feat_entry *entry;13481348- int i = 2, ccids[2] = { -1, -1 };13491349-13501350- /*13511351- * Propagating CCIDs:13521352- * 1) not useful to propagate CCID settings if this host advertises more13531353- * than one CCID: the choice of CCID may still change - if this is13541354- * the client, or if this is the server and the client sends13551355- * singleton CCID values.13561356- * 2) since is that propagate_ccid changes the list, we defer changing13571357- * the sorted list until after the traversal.13581358- */13591359- list_for_each_entry(entry, fn, node)13601360- if (entry->feat_num == DCCPF_CCID && entry->val.sp.len == 1)13611361- ccids[entry->is_local] = entry->val.sp.vec[0];13621362- while (i--)13631363- if (ccids[i] > 0 && dccp_feat_propagate_ccid(fn, ccids[i], i))13641364- return -1;13651365- dccp_feat_print_fnlist(fn);13661366- return 0;13671367-}13681368-13691369-/**13701370- * dccp_feat_server_ccid_dependencies - Resolve CCID-dependent features13711371- * It is the server which resolves the dependencies once the CCID has been13721372- * fully negotiated. If no CCID has been negotiated, it uses the default CCID.13731373- */13741374-int dccp_feat_server_ccid_dependencies(struct dccp_request_sock *dreq)13751375-{13761376- struct list_head *fn = &dreq->dreq_featneg;13771377- struct dccp_feat_entry *entry;13781378- u8 is_local, ccid;13791379-13801380- for (is_local = 0; is_local <= 1; is_local++) {13811381- entry = dccp_feat_list_lookup(fn, DCCPF_CCID, is_local);13821382-13831383- if (entry != NULL && !entry->empty_confirm)13841384- ccid = entry->val.sp.vec[0];13851385- else13861386- ccid = dccp_feat_default_value(DCCPF_CCID);13871387-13881388- if (dccp_feat_propagate_ccid(fn, ccid, is_local))13891389- return -1;13901390- }13911391- return 0;13921392-}13931393-13941394-/* Select the first entry in @servlist that also occurs in @clilist (6.3.1) */13951395-static int dccp_feat_preflist_match(u8 *servlist, u8 slen, u8 *clilist, u8 clen)13961396-{13971397- u8 c, s;13981398-13991399- for (s = 0; s < slen; s++)14001400- for (c = 0; c < clen; c++)14011401- if (servlist[s] == clilist[c])14021402- return servlist[s];14031403- return -1;14041404-}14051405-14061406-/**14071407- * dccp_feat_prefer - Move preferred entry to the start of array14081408- * Reorder the @array_len elements in @array so that @preferred_value comes14091409- * first. Returns >0 to indicate that @preferred_value does occur in @array.14101410- */14111411-static u8 dccp_feat_prefer(u8 preferred_value, u8 *array, u8 array_len)14121412-{14131413- u8 i, does_occur = 0;14141414-14151415- if (array != NULL) {14161416- for (i = 0; i < array_len; i++)14171417- if (array[i] == preferred_value) {14181418- array[i] = array[0];14191419- does_occur++;14201420- }14211421- if (does_occur)14221422- array[0] = preferred_value;14231423- }14241424- return does_occur;14251425-}14261426-14271427-/**14281428- * dccp_feat_reconcile - Reconcile SP preference lists14291429- * @fval: SP list to reconcile into14301430- * @arr: received SP preference list14311431- * @len: length of @arr in bytes14321432- * @is_server: whether this side is the server (and @fv is the server's list)14331433- * @reorder: whether to reorder the list in @fv after reconciling with @arr14341434- * When successful, > 0 is returned and the reconciled list is in @fval.14351435- * A value of 0 means that negotiation failed (no shared entry).14361436- */14371437-static int dccp_feat_reconcile(dccp_feat_val *fv, u8 *arr, u8 len,14381438- bool is_server, bool reorder)14391439-{14401440- int rc;14411441-14421442- if (!fv->sp.vec || !arr) {14431443- DCCP_CRIT("NULL feature value or array");14441444- return 0;14451445- }14461446-14471447- if (is_server)14481448- rc = dccp_feat_preflist_match(fv->sp.vec, fv->sp.len, arr, len);14491449- else14501450- rc = dccp_feat_preflist_match(arr, len, fv->sp.vec, fv->sp.len);14511451-14521452- if (!reorder)14531453- return rc;14541454- if (rc < 0)14551455- return 0;14561456-14571457- /*14581458- * Reorder list: used for activating features and in dccp_insert_fn_opt.14591459- */14601460- return dccp_feat_prefer(rc, fv->sp.vec, fv->sp.len);14611461-}14621462-14631463-/**14641464- * dccp_feat_change_recv - Process incoming ChangeL/R options14651465- * @fn: feature-negotiation list to update14661466- * @is_mandatory: whether the Change was preceded by a Mandatory option14671467- * @opt: %DCCPO_CHANGE_L or %DCCPO_CHANGE_R14681468- * @feat: one of %dccp_feature_numbers14691469- * @val: NN value or SP value/preference list14701470- * @len: length of @val in bytes14711471- * @server: whether this node is the server (1) or the client (0)14721472- */14731473-static u8 dccp_feat_change_recv(struct list_head *fn, u8 is_mandatory, u8 opt,14741474- u8 feat, u8 *val, u8 len, const bool server)14751475-{14761476- u8 defval, type = dccp_feat_type(feat);14771477- const bool local = (opt == DCCPO_CHANGE_R);14781478- struct dccp_feat_entry *entry;14791479- dccp_feat_val fval;14801480-14811481- if (len == 0 || type == FEAT_UNKNOWN) /* 6.1 and 6.6.8 */14821482- goto unknown_feature_or_value;14831483-14841484- dccp_feat_print_opt(opt, feat, val, len, is_mandatory);14851485-14861486- /*14871487- * Negotiation of NN features: Change R is invalid, so there is no14881488- * simultaneous negotiation; hence we do not look up in the list.14891489- */14901490- if (type == FEAT_NN) {14911491- if (local || len > sizeof(fval.nn))14921492- goto unknown_feature_or_value;14931493-14941494- /* 6.3.2: "The feature remote MUST accept any valid value..." */14951495- fval.nn = dccp_decode_value_var(val, len);14961496- if (!dccp_feat_is_valid_nn_val(feat, fval.nn))14971497- goto unknown_feature_or_value;14981498-14991499- return dccp_feat_push_confirm(fn, feat, local, &fval);15001500- }15011501-15021502- /*15031503- * Unidirectional/simultaneous negotiation of SP features (6.3.1)15041504- */15051505- entry = dccp_feat_list_lookup(fn, feat, local);15061506- if (entry == NULL) {15071507- /*15081508- * No particular preferences have been registered. We deal with15091509- * this situation by assuming that all valid values are equally15101510- * acceptable, and apply the following checks:15111511- * - if the peer's list is a singleton, we accept a valid value;15121512- * - if we are the server, we first try to see if the peer (the15131513- * client) advertises the default value. If yes, we use it,15141514- * otherwise we accept the preferred value;15151515- * - else if we are the client, we use the first list element.15161516- */15171517- if (dccp_feat_clone_sp_val(&fval, val, 1))15181518- return DCCP_RESET_CODE_TOO_BUSY;15191519-15201520- if (len > 1 && server) {15211521- defval = dccp_feat_default_value(feat);15221522- if (dccp_feat_preflist_match(&defval, 1, val, len) > -1)15231523- fval.sp.vec[0] = defval;15241524- } else if (!dccp_feat_is_valid_sp_val(feat, fval.sp.vec[0])) {15251525- kfree(fval.sp.vec);15261526- goto unknown_feature_or_value;15271527- }15281528-15291529- /* Treat unsupported CCIDs like invalid values */15301530- if (feat == DCCPF_CCID && !ccid_support_check(fval.sp.vec, 1)) {15311531- kfree(fval.sp.vec);15321532- goto not_valid_or_not_known;15331533- }15341534-15351535- return dccp_feat_push_confirm(fn, feat, local, &fval);15361536-15371537- } else if (entry->state == FEAT_UNSTABLE) { /* 6.6.2 */15381538- return 0;15391539- }15401540-15411541- if (dccp_feat_reconcile(&entry->val, val, len, server, true)) {15421542- entry->empty_confirm = 0;15431543- } else if (is_mandatory) {15441544- return DCCP_RESET_CODE_MANDATORY_ERROR;15451545- } else if (entry->state == FEAT_INITIALISING) {15461546- /*15471547- * Failed simultaneous negotiation (server only): try to `save'15481548- * the connection by checking whether entry contains the default15491549- * value for @feat. If yes, send an empty Confirm to signal that15501550- * the received Change was not understood - which implies using15511551- * the default value.15521552- * If this also fails, we use Reset as the last resort.15531553- */15541554- WARN_ON(!server);15551555- defval = dccp_feat_default_value(feat);15561556- if (!dccp_feat_reconcile(&entry->val, &defval, 1, server, true))15571557- return DCCP_RESET_CODE_OPTION_ERROR;15581558- entry->empty_confirm = 1;15591559- }15601560- entry->needs_confirm = 1;15611561- entry->needs_mandatory = 0;15621562- entry->state = FEAT_STABLE;15631563- return 0;15641564-15651565-unknown_feature_or_value:15661566- if (!is_mandatory)15671567- return dccp_push_empty_confirm(fn, feat, local);15681568-15691569-not_valid_or_not_known:15701570- return is_mandatory ? DCCP_RESET_CODE_MANDATORY_ERROR15711571- : DCCP_RESET_CODE_OPTION_ERROR;15721572-}15731573-15741574-/**15751575- * dccp_feat_confirm_recv - Process received Confirm options15761576- * @fn: feature-negotiation list to update15771577- * @is_mandatory: whether @opt was preceded by a Mandatory option15781578- * @opt: %DCCPO_CONFIRM_L or %DCCPO_CONFIRM_R15791579- * @feat: one of %dccp_feature_numbers15801580- * @val: NN value or SP value/preference list15811581- * @len: length of @val in bytes15821582- * @server: whether this node is server (1) or client (0)15831583- */15841584-static u8 dccp_feat_confirm_recv(struct list_head *fn, u8 is_mandatory, u8 opt,15851585- u8 feat, u8 *val, u8 len, const bool server)15861586-{15871587- u8 *plist, plen, type = dccp_feat_type(feat);15881588- const bool local = (opt == DCCPO_CONFIRM_R);15891589- struct dccp_feat_entry *entry = dccp_feat_list_lookup(fn, feat, local);15901590-15911591- dccp_feat_print_opt(opt, feat, val, len, is_mandatory);15921592-15931593- if (entry == NULL) { /* nothing queued: ignore or handle error */15941594- if (is_mandatory && type == FEAT_UNKNOWN)15951595- return DCCP_RESET_CODE_MANDATORY_ERROR;15961596-15971597- if (!local && type == FEAT_NN) /* 6.3.2 */15981598- goto confirmation_failed;15991599- return 0;16001600- }16011601-16021602- if (entry->state != FEAT_CHANGING) /* 6.6.2 */16031603- return 0;16041604-16051605- if (len == 0) {16061606- if (dccp_feat_must_be_understood(feat)) /* 6.6.7 */16071607- goto confirmation_failed;16081608- /*16091609- * Empty Confirm during connection setup: this means reverting16101610- * to the `old' value, which in this case is the default. Since16111611- * we handle default values automatically when no other values16121612- * have been set, we revert to the old value by removing this16131613- * entry from the list.16141614- */16151615- dccp_feat_list_pop(entry);16161616- return 0;16171617- }16181618-16191619- if (type == FEAT_NN) {16201620- if (len > sizeof(entry->val.nn))16211621- goto confirmation_failed;16221622-16231623- if (entry->val.nn == dccp_decode_value_var(val, len))16241624- goto confirmation_succeeded;16251625-16261626- DCCP_WARN("Bogus Confirm for non-existing value\n");16271627- goto confirmation_failed;16281628- }16291629-16301630- /*16311631- * Parsing SP Confirms: the first element of @val is the preferred16321632- * SP value which the peer confirms, the remainder depends on @len.16331633- * Note that only the confirmed value need to be a valid SP value.16341634- */16351635- if (!dccp_feat_is_valid_sp_val(feat, *val))16361636- goto confirmation_failed;16371637-16381638- if (len == 1) { /* peer didn't supply a preference list */16391639- plist = val;16401640- plen = len;16411641- } else { /* preferred value + preference list */16421642- plist = val + 1;16431643- plen = len - 1;16441644- }16451645-16461646- /* Check whether the peer got the reconciliation right (6.6.8) */16471647- if (dccp_feat_reconcile(&entry->val, plist, plen, server, 0) != *val) {16481648- DCCP_WARN("Confirm selected the wrong value %u\n", *val);16491649- return DCCP_RESET_CODE_OPTION_ERROR;16501650- }16511651- entry->val.sp.vec[0] = *val;16521652-16531653-confirmation_succeeded:16541654- entry->state = FEAT_STABLE;16551655- return 0;16561656-16571657-confirmation_failed:16581658- DCCP_WARN("Confirmation failed\n");16591659- return is_mandatory ? DCCP_RESET_CODE_MANDATORY_ERROR16601660- : DCCP_RESET_CODE_OPTION_ERROR;16611661-}16621662-16631663-/**16641664- * dccp_feat_handle_nn_established - Fast-path reception of NN options16651665- * @sk: socket of an established DCCP connection16661666- * @mandatory: whether @opt was preceded by a Mandatory option16671667- * @opt: %DCCPO_CHANGE_L | %DCCPO_CONFIRM_R (NN only)16681668- * @feat: NN number, one of %dccp_feature_numbers16691669- * @val: NN value16701670- * @len: length of @val in bytes16711671- * This function combines the functionality of change_recv/confirm_recv, with16721672- * the following differences (reset codes are the same):16731673- * - cleanup after receiving the Confirm;16741674- * - values are directly activated after successful parsing;16751675- * - deliberately restricted to NN features.16761676- * The restriction to NN features is essential since SP features can have non-16771677- * predictable outcomes (depending on the remote configuration), and are inter-16781678- * dependent (CCIDs for instance cause further dependencies).16791679- */16801680-static u8 dccp_feat_handle_nn_established(struct sock *sk, u8 mandatory, u8 opt,16811681- u8 feat, u8 *val, u8 len)16821682-{16831683- struct list_head *fn = &dccp_sk(sk)->dccps_featneg;16841684- const bool local = (opt == DCCPO_CONFIRM_R);16851685- struct dccp_feat_entry *entry;16861686- u8 type = dccp_feat_type(feat);16871687- dccp_feat_val fval;16881688-16891689- dccp_feat_print_opt(opt, feat, val, len, mandatory);16901690-16911691- /* Ignore non-mandatory unknown and non-NN features */16921692- if (type == FEAT_UNKNOWN) {16931693- if (local && !mandatory)16941694- return 0;16951695- goto fast_path_unknown;16961696- } else if (type != FEAT_NN) {16971697- return 0;16981698- }16991699-17001700- /*17011701- * We don't accept empty Confirms, since in fast-path feature17021702- * negotiation the values are enabled immediately after sending17031703- * the Change option.17041704- * Empty Changes on the other hand are invalid (RFC 4340, 6.1).17051705- */17061706- if (len == 0 || len > sizeof(fval.nn))17071707- goto fast_path_unknown;17081708-17091709- if (opt == DCCPO_CHANGE_L) {17101710- fval.nn = dccp_decode_value_var(val, len);17111711- if (!dccp_feat_is_valid_nn_val(feat, fval.nn))17121712- goto fast_path_unknown;17131713-17141714- if (dccp_feat_push_confirm(fn, feat, local, &fval) ||17151715- dccp_feat_activate(sk, feat, local, &fval))17161716- return DCCP_RESET_CODE_TOO_BUSY;17171717-17181718- /* set the `Ack Pending' flag to piggyback a Confirm */17191719- inet_csk_schedule_ack(sk);17201720-17211721- } else if (opt == DCCPO_CONFIRM_R) {17221722- entry = dccp_feat_list_lookup(fn, feat, local);17231723- if (entry == NULL || entry->state != FEAT_CHANGING)17241724- return 0;17251725-17261726- fval.nn = dccp_decode_value_var(val, len);17271727- if (fval.nn != entry->val.nn) {17281728- DCCP_WARN("Bogus Confirm for non-existing value\n");17291729- goto fast_path_failed;17301730- }17311731-17321732- /* It has been confirmed - so remove the entry */17331733- dccp_feat_list_pop(entry);17341734-17351735- } else {17361736- DCCP_WARN("Received illegal option %u\n", opt);17371737- goto fast_path_failed;17381738- }17391739- return 0;17401740-17411741-fast_path_unknown:17421742- if (!mandatory)17431743- return dccp_push_empty_confirm(fn, feat, local);17441744-17451745-fast_path_failed:17461746- return mandatory ? DCCP_RESET_CODE_MANDATORY_ERROR17471747- : DCCP_RESET_CODE_OPTION_ERROR;17481748-}17491749-17501750-/**17511751- * dccp_feat_parse_options - Process Feature-Negotiation Options17521752- * @sk: for general use and used by the client during connection setup17531753- * @dreq: used by the server during connection setup17541754- * @mandatory: whether @opt was preceded by a Mandatory option17551755- * @opt: %DCCPO_CHANGE_L | %DCCPO_CHANGE_R | %DCCPO_CONFIRM_L | %DCCPO_CONFIRM_R17561756- * @feat: one of %dccp_feature_numbers17571757- * @val: value contents of @opt17581758- * @len: length of @val in bytes17591759- * Returns 0 on success, a Reset code for ending the connection otherwise.17601760- */17611761-int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq,17621762- u8 mandatory, u8 opt, u8 feat, u8 *val, u8 len)17631763-{17641764- struct dccp_sock *dp = dccp_sk(sk);17651765- struct list_head *fn = dreq ? &dreq->dreq_featneg : &dp->dccps_featneg;17661766- bool server = false;17671767-17681768- switch (sk->sk_state) {17691769- /*17701770- * Negotiation during connection setup17711771- */17721772- case DCCP_LISTEN:17731773- server = true; /* fall through */17741774- case DCCP_REQUESTING:17751775- switch (opt) {17761776- case DCCPO_CHANGE_L:17771777- case DCCPO_CHANGE_R:17781778- return dccp_feat_change_recv(fn, mandatory, opt, feat,17791779- val, len, server);17801780- case DCCPO_CONFIRM_R:17811781- case DCCPO_CONFIRM_L:17821782- return dccp_feat_confirm_recv(fn, mandatory, opt, feat,17831783- val, len, server);17841784- }17851785- break;17861786- /*17871787- * Support for exchanging NN options on an established connection17881788- * This is currently restricted to Ack Ratio (RFC 4341, 6.1.2)17891789- */17901790- case DCCP_OPEN:17911791- case DCCP_PARTOPEN:17921792- return dccp_feat_handle_nn_established(sk, mandatory, opt, feat,17931793- val, len);17941794- }17951795- return 0; /* ignore FN options in all other states */17961796-}17971797-17981798-/**17991799- * dccp_feat_init - Seed feature negotiation with host-specific defaults18001800- * This initialises global defaults, depending on the value of the sysctls.18011801- * These can later be overridden by registering changes via setsockopt calls.18021802- * The last link in the chain is finalise_settings, to make sure that between18031803- * here and the start of actual feature negotiation no inconsistencies enter.18041804- *18051805- * All features not appearing below use either defaults or are otherwise18061806- * later adjusted through dccp_feat_finalise_settings().18071807- */18081808-int dccp_feat_init(struct sock *sk)18091809-{18101810- struct list_head *fn = &dccp_sk(sk)->dccps_featneg;18111811- u8 on = 1, off = 0;18121812- int rc;18131813- struct {18141814- u8 *val;18151815- u8 len;18161816- } tx, rx;18171817-18181818- /* Non-negotiable (NN) features */18191819- rc = __feat_register_nn(fn, DCCPF_SEQUENCE_WINDOW, 0,18201820- sysctl_dccp_sequence_window);18211821- if (rc)18221822- return rc;18231823-18241824- /* Server-priority (SP) features */18251825-18261826- /* Advertise that short seqnos are not supported (7.6.1) */18271827- rc = __feat_register_sp(fn, DCCPF_SHORT_SEQNOS, true, true, &off, 1);18281828- if (rc)18291829- return rc;18301830-18311831- /* RFC 4340 12.1: "If a DCCP is not ECN capable, ..." */18321832- rc = __feat_register_sp(fn, DCCPF_ECN_INCAPABLE, true, true, &on, 1);18331833- if (rc)18341834- return rc;18351835-18361836- /*18371837- * We advertise the available list of CCIDs and reorder according to18381838- * preferences, to avoid failure resulting from negotiating different18391839- * singleton values (which always leads to failure).18401840- * These settings can still (later) be overridden via sockopts.18411841- */18421842- if (ccid_get_builtin_ccids(&tx.val, &tx.len) ||18431843- ccid_get_builtin_ccids(&rx.val, &rx.len))18441844- return -ENOBUFS;18451845-18461846- /* Pre-load all CCID modules that are going to be advertised */18471847- rc = -EUNATCH;18481848- if (ccid_request_modules(tx.val, tx.len))18491849- goto free_ccid_lists;18501850-18511851- if (!dccp_feat_prefer(sysctl_dccp_tx_ccid, tx.val, tx.len) ||18521852- !dccp_feat_prefer(sysctl_dccp_rx_ccid, rx.val, rx.len))18531853- goto free_ccid_lists;18541854-18551855- rc = __feat_register_sp(fn, DCCPF_CCID, true, false, tx.val, tx.len);18561856- if (rc)18571857- goto free_ccid_lists;18581858-18591859- rc = __feat_register_sp(fn, DCCPF_CCID, false, false, rx.val, rx.len);18601860-18611861-free_ccid_lists:18621862- kfree(tx.val);18631863- kfree(rx.val);18641864- return rc;18651865-}18661866-18671867-int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list)18681868-{18691869- struct dccp_sock *dp = dccp_sk(sk);18701870- struct dccp_feat_entry *cur, *next;18711871- int idx;18721872- dccp_feat_val *fvals[DCCP_FEAT_SUPPORTED_MAX][2] = {18731873- [0 ... DCCP_FEAT_SUPPORTED_MAX-1] = { NULL, NULL }18741874- };18751875-18761876- list_for_each_entry(cur, fn_list, node) {18771877- /*18781878- * An empty Confirm means that either an unknown feature type18791879- * or an invalid value was present. In the first case there is18801880- * nothing to activate, in the other the default value is used.18811881- */18821882- if (cur->empty_confirm)18831883- continue;18841884-18851885- idx = dccp_feat_index(cur->feat_num);18861886- if (idx < 0) {18871887- DCCP_BUG("Unknown feature %u", cur->feat_num);18881888- goto activation_failed;18891889- }18901890- if (cur->state != FEAT_STABLE) {18911891- DCCP_CRIT("Negotiation of %s %s failed in state %s",18921892- cur->is_local ? "local" : "remote",18931893- dccp_feat_fname(cur->feat_num),18941894- dccp_feat_sname[cur->state]);18951895- goto activation_failed;18961896- }18971897- fvals[idx][cur->is_local] = &cur->val;18981898- }18991899-19001900- /*19011901- * Activate in decreasing order of index, so that the CCIDs are always19021902- * activated as the last feature. This avoids the case where a CCID19031903- * relies on the initialisation of one or more features that it depends19041904- * on (e.g. Send NDP Count, Send Ack Vector, and Ack Ratio features).19051905- */19061906- for (idx = DCCP_FEAT_SUPPORTED_MAX; --idx >= 0;)19071907- if (__dccp_feat_activate(sk, idx, 0, fvals[idx][0]) ||19081908- __dccp_feat_activate(sk, idx, 1, fvals[idx][1])) {19091909- DCCP_CRIT("Could not activate %d", idx);19101910- goto activation_failed;19111911- }19121912-19131913- /* Clean up Change options which have been confirmed already */19141914- list_for_each_entry_safe(cur, next, fn_list, node)19151915- if (!cur->needs_confirm)19161916- dccp_feat_list_pop(cur);19171917-19181918- dccp_pr_debug("Activation OK\n");19191919- return 0;19201920-19211921-activation_failed:19221922- /*19231923- * We clean up everything that may have been allocated, since19241924- * it is difficult to track at which stage negotiation failed.19251925- * This is ok, since all allocation functions below are robust19261926- * against NULL arguments.19271927- */19281928- ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);19291929- ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);19301930- dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;19311931- dccp_ackvec_free(dp->dccps_hc_rx_ackvec);19321932- dp->dccps_hc_rx_ackvec = NULL;19331933- return -1;19341934-}246246+EXPORT_SYMBOL_GPL(dccp_feat_name);247247+#endif /* CONFIG_IP_DCCP_DEBUG */
+23-119
net/dccp/feat.h
···33/*44 * net/dccp/feat.h55 *66- * Feature negotiation for the DCCP protocol (RFC 4340, section 6)77- * Copyright (c) 2008 Gerrit Renker <gerrit@erg.abdn.ac.uk>66+ * An implementation of the DCCP protocol87 * Copyright (c) 2005 Andrea Bittau <a.bittau@cs.ucl.ac.uk>98 *1010- * This program is free software; you can redistribute it and/or modify it1111- * under the terms of the GNU General Public License version 2 as1212- * published by the Free Software Foundation.99+ * This program is free software; you can redistribute it and/or modify it1010+ * under the terms of the GNU General Public License version 2 as1111+ * published by the Free Software Foundation.1312 */1313+1414#include <linux/types.h>1515#include "dccp.h"16161717-/*1818- * Known limit values1919- */2020-/* Ack Ratio takes 2-byte integer values (11.3) */2121-#define DCCPF_ACK_RATIO_MAX 0xFFFF2222-/* Wmin=32 and Wmax=2^46-1 from 7.5.2 */2323-#define DCCPF_SEQ_WMIN 322424-#define DCCPF_SEQ_WMAX 0x3FFFFFFFFFFFull2525-/* Maximum number of SP values that fit in a single (Confirm) option */2626-#define DCCP_FEAT_MAX_SP_VALS (DCCP_SINGLE_OPT_MAXLEN - 2)1717+#ifdef CONFIG_IP_DCCP_DEBUG1818+extern const char *dccp_feat_typename(const u8 type);1919+extern const char *dccp_feat_name(const u8 feat);27202828-enum dccp_feat_type {2929- FEAT_AT_RX = 1, /* located at RX side of half-connection */3030- FEAT_AT_TX = 2, /* located at TX side of half-connection */3131- FEAT_SP = 4, /* server-priority reconciliation (6.3.1) */3232- FEAT_NN = 8, /* non-negotiable reconciliation (6.3.2) */3333- FEAT_UNKNOWN = 0xFF /* not understood or invalid feature */3434-};3535-3636-enum dccp_feat_state {3737- FEAT_DEFAULT = 0, /* using default values from 6.4 */3838- FEAT_INITIALISING, /* feature is being initialised */3939- FEAT_CHANGING, /* Change sent but not confirmed yet */4040- FEAT_UNSTABLE, /* local modification in state CHANGING */4141- FEAT_STABLE /* both ends (think they) agree */4242-};4343-4444-/**4545- * dccp_feat_val - Container for SP or NN feature values4646- * @nn: single NN value4747- * @sp.vec: single SP value plus optional preference list4848- * @sp.len: length of @sp.vec in bytes4949- */5050-typedef union {5151- u64 nn;5252- struct {5353- u8 *vec;5454- u8 len;5555- } sp;5656-} dccp_feat_val;5757-5858-/**5959- * struct feat_entry - Data structure to perform feature negotiation6060- * @feat_num: one of %dccp_feature_numbers6161- * @val: feature's current value (SP features may have preference list)6262- * @state: feature's current state6363- * @needs_mandatory: whether Mandatory options should be sent6464- * @needs_confirm: whether to send a Confirm instead of a Change6565- * @empty_confirm: whether to send an empty Confirm (depends on @needs_confirm)6666- * @is_local: feature location (1) or feature-remote (0)6767- * @node: list pointers, entries arranged in FIFO order6868- */6969-struct dccp_feat_entry {7070- u8 feat_num;7171- dccp_feat_val val;7272- enum dccp_feat_state state:8;7373- bool needs_mandatory:1,7474- needs_confirm:1,7575- empty_confirm:1,7676- is_local:1;7777-7878- struct list_head node;7979-};8080-8181-static inline u8 dccp_feat_genopt(struct dccp_feat_entry *entry)2121+static inline void dccp_feat_debug(const u8 type, const u8 feat, const u8 val)8222{8383- if (entry->needs_confirm)8484- return entry->is_local ? DCCPO_CONFIRM_L : DCCPO_CONFIRM_R;8585- return entry->is_local ? DCCPO_CHANGE_L : DCCPO_CHANGE_R;2323+ dccp_pr_debug("%s(%s (%d), %d)\n", dccp_feat_typename(type),2424+ dccp_feat_name(feat), feat, val);8625}2626+#else2727+#define dccp_feat_debug(type, feat, val)2828+#endif /* CONFIG_IP_DCCP_DEBUG */87298888-/**8989- * struct ccid_dependency - Track changes resulting from choosing a CCID9090- * @dependent_feat: one of %dccp_feature_numbers9191- * @is_local: local (1) or remote (0) @dependent_feat9292- * @is_mandatory: whether presence of @dependent_feat is mission-critical or not9393- * @val: corresponding default value for @dependent_feat (u8 is sufficient here)9494- */9595-struct ccid_dependency {9696- u8 dependent_feat;9797- bool is_local:1,9898- is_mandatory:1;9999- u8 val;100100-};3030+extern int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,3131+ u8 *val, u8 len, gfp_t gfp);3232+extern int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature,3333+ u8 *val, u8 len);3434+extern int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature,3535+ u8 *val, u8 len);3636+extern void dccp_feat_clean(struct dccp_minisock *dmsk);3737+extern int dccp_feat_clone(struct sock *oldsk, struct sock *newsk);3838+extern int dccp_feat_init(struct dccp_minisock *dmsk);10139102102-/*103103- * Sysctls to seed defaults for feature negotiation104104- */105105-extern unsigned long sysctl_dccp_sequence_window;106106-extern int sysctl_dccp_rx_ccid;107107-extern int sysctl_dccp_tx_ccid;108108-109109-extern int dccp_feat_init(struct sock *sk);110110-extern void dccp_feat_initialise_sysctls(void);111111-extern int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local,112112- u8 const *list, u8 len);113113-extern int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val);114114-extern int dccp_feat_parse_options(struct sock *, struct dccp_request_sock *,115115- u8 mand, u8 opt, u8 feat, u8 *val, u8 len);116116-extern int dccp_feat_clone_list(struct list_head const *, struct list_head *);117117-118118-/*119119- * Encoding variable-length options and their maximum length.120120- *121121- * This affects NN options (SP options are all u8) and other variable-length122122- * options (see table 3 in RFC 4340). The limit is currently given the Sequence123123- * Window NN value (sec. 7.5.2) and the NDP count (sec. 7.7) option, all other124124- * options consume less than 6 bytes (timestamps are 4 bytes).125125- * When updating this constant (e.g. due to new internet drafts / RFCs), make126126- * sure that you also update all code which refers to it.127127- */128128-#define DCCP_OPTVAL_MAXLEN 6129129-130130-extern void dccp_encode_value_var(const u64 value, u8 *to, const u8 len);131131-extern u64 dccp_decode_value_var(const u8 *bf, const u8 len);132132-133133-extern int dccp_insert_option_mandatory(struct sk_buff *skb);134134-extern int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat,135135- u8 *val, u8 len, bool repeat_first);13640#endif /* _DCCP_FEAT_H */
+91-73
net/dccp/input.c
···159159 dccp_time_wait(sk, DCCP_TIME_WAIT, 0);160160}161161162162-static void dccp_handle_ackvec_processing(struct sock *sk, struct sk_buff *skb)162162+static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb)163163{164164- struct dccp_ackvec *av = dccp_sk(sk)->dccps_hc_rx_ackvec;164164+ struct dccp_sock *dp = dccp_sk(sk);165165166166- if (av == NULL)167167- return;168168- if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)169169- dccp_ackvec_clear_state(av, DCCP_SKB_CB(skb)->dccpd_ack_seq);170170- dccp_ackvec_input(av, skb);166166+ if (dccp_msk(sk)->dccpms_send_ack_vector)167167+ dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk,168168+ DCCP_SKB_CB(skb)->dccpd_ack_seq);171169}172170173171static void dccp_deliver_input_to_ccids(struct sock *sk, struct sk_buff *skb)···364366int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,365367 const struct dccp_hdr *dh, const unsigned len)366368{369369+ struct dccp_sock *dp = dccp_sk(sk);370370+367371 if (dccp_check_seqno(sk, skb))368372 goto discard;369373370374 if (dccp_parse_options(sk, NULL, skb))371375 return 1;372376373373- dccp_handle_ackvec_processing(sk, skb);377377+ if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)378378+ dccp_event_ack_recv(sk, skb);379379+380380+ if (dccp_msk(sk)->dccpms_send_ack_vector &&381381+ dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,382382+ DCCP_SKB_CB(skb)->dccpd_seq,383383+ DCCP_ACKVEC_STATE_RECEIVED))384384+ goto discard;374385 dccp_deliver_input_to_ccids(sk, skb);375386376387 return __dccp_rcv_established(sk, skb, dh, len);···421414 goto out_invalid_packet;422415 }423416424424- /*425425- * If option processing (Step 8) failed, return 1 here so that426426- * dccp_v4_do_rcv() sends a Reset. The Reset code depends on427427- * the option type and is set in dccp_parse_options().428428- */429417 if (dccp_parse_options(sk, NULL, skb))430430- return 1;418418+ goto out_invalid_packet;431419432420 /* Obtain usec RTT sample from SYN exchange (used by CCID 3) */433421 if (likely(dp->dccps_options_received.dccpor_timestamp_echo))434422 dp->dccps_syn_rtt = dccp_sample_rtt(sk, 10 * (tstamp -435423 dp->dccps_options_received.dccpor_timestamp_echo));424424+425425+ if (dccp_msk(sk)->dccpms_send_ack_vector &&426426+ dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,427427+ DCCP_SKB_CB(skb)->dccpd_seq,428428+ DCCP_ACKVEC_STATE_RECEIVED))429429+ goto out_invalid_packet; /* FIXME: change error code */436430437431 /* Stop the REQUEST timer */438432 inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);···441433 kfree_skb(sk->sk_send_head);442434 sk->sk_send_head = NULL;443435436436+ dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq;437437+ dccp_update_gsr(sk, dp->dccps_isr);444438 /*445445- * Set ISR, GSR from packet. ISS was set in dccp_v{4,6}_connect446446- * and GSS in dccp_transmit_skb(). Setting AWL/AWH and SWL/SWH447447- * is done as part of activating the feature values below, since448448- * these settings depend on the local/remote Sequence Window449449- * features, which were undefined or not confirmed until now.439439+ * SWL and AWL are initially adjusted so that they are not less than440440+ * the initial Sequence Numbers received and sent, respectively:441441+ * SWL := max(GSR + 1 - floor(W/4), ISR),442442+ * AWL := max(GSS - W' + 1, ISS).443443+ * These adjustments MUST be applied only at the beginning of the444444+ * connection.445445+ *446446+ * AWL was adjusted in dccp_v4_connect -acme450447 */451451- dp->dccps_gsr = dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq;448448+ dccp_set_seqno(&dp->dccps_swl,449449+ max48(dp->dccps_swl, dp->dccps_isr));452450453451 dccp_sync_mss(sk, icsk->icsk_pmtu_cookie);454452···474460 * three-way handshake * /475461 */476462 dccp_set_state(sk, DCCP_PARTOPEN);477477-478478- /*479479- * If feature negotiation was successful, activate features now;480480- * an activation failure means that this host could not activate481481- * one ore more features (e.g. insufficient memory), which would482482- * leave at least one feature in an undefined state.483483- */484484- if (dccp_feat_activate_values(sk, &dp->dccps_featneg))485485- goto unable_to_proceed;486463487464 /* Make sure socket is routed, for correct metrics. */488465 icsk->icsk_af_ops->rebuild_header(sk);···508503out_invalid_packet:509504 /* dccp_v4_do_rcv will send a reset */510505 DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;511511- return 1;512512-513513-unable_to_proceed:514514- DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_ABORTED;515515- /*516516- * We mark this socket as no longer usable, so that the loop in517517- * dccp_sendmsg() terminates and the application gets notified.518518- */519519- dccp_set_state(sk, DCCP_CLOSED);520520- sk->sk_err = ECOMM;521506 return 1;522507}523508···590595 if (inet_csk(sk)->icsk_af_ops->conn_request(sk,591596 skb) < 0)592597 return 1;598598+599599+ /* FIXME: do congestion control initialization */593600 goto discard;594601 }595602 if (dh->dccph_type == DCCP_PKT_RESET)···600603 /* Caller (dccp_v4_do_rcv) will send Reset */601604 dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;602605 return 1;603603- } else if (sk->sk_state == DCCP_CLOSED) {604604- dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;605605- return 1;606606 }607607608608- /* Step 6: Check sequence numbers (omitted in LISTEN/REQUEST state) */609609- if (sk->sk_state != DCCP_REQUESTING && dccp_check_seqno(sk, skb))610610- goto discard;608608+ if (sk->sk_state != DCCP_REQUESTING) {609609+ if (dccp_check_seqno(sk, skb))610610+ goto discard;611611612612- /*613613- * Step 7: Check for unexpected packet types614614- * If (S.is_server and P.type == Response)615615- * or (S.is_client and P.type == Request)616616- * or (S.state == RESPOND and P.type == Data),617617- * Send Sync packet acknowledging P.seqno618618- * Drop packet and return619619- */620620- if ((dp->dccps_role != DCCP_ROLE_CLIENT &&621621- dh->dccph_type == DCCP_PKT_RESPONSE) ||622622- (dp->dccps_role == DCCP_ROLE_CLIENT &&623623- dh->dccph_type == DCCP_PKT_REQUEST) ||624624- (sk->sk_state == DCCP_RESPOND && dh->dccph_type == DCCP_PKT_DATA)) {625625- dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);626626- goto discard;612612+ /*613613+ * Step 8: Process options and mark acknowledgeable614614+ */615615+ if (dccp_parse_options(sk, NULL, skb))616616+ return 1;617617+618618+ if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)619619+ dccp_event_ack_recv(sk, skb);620620+621621+ if (dccp_msk(sk)->dccpms_send_ack_vector &&622622+ dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,623623+ DCCP_SKB_CB(skb)->dccpd_seq,624624+ DCCP_ACKVEC_STATE_RECEIVED))625625+ goto discard;626626+627627+ dccp_deliver_input_to_ccids(sk, skb);627628 }628628-629629- /* Step 8: Process options */630630- if (dccp_parse_options(sk, NULL, skb))631631- return 1;632629633630 /*634631 * Step 9: Process Reset···631640 * S.state := TIMEWAIT632641 * Set TIMEWAIT timer633642 * Drop packet and return634634- */643643+ */635644 if (dh->dccph_type == DCCP_PKT_RESET) {636645 dccp_rcv_reset(sk, skb);637646 return 0;638638- } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) { /* Step 13 */647647+ /*648648+ * Step 7: Check for unexpected packet types649649+ * If (S.is_server and P.type == Response)650650+ * or (S.is_client and P.type == Request)651651+ * or (S.state == RESPOND and P.type == Data),652652+ * Send Sync packet acknowledging P.seqno653653+ * Drop packet and return654654+ */655655+ } else if ((dp->dccps_role != DCCP_ROLE_CLIENT &&656656+ dh->dccph_type == DCCP_PKT_RESPONSE) ||657657+ (dp->dccps_role == DCCP_ROLE_CLIENT &&658658+ dh->dccph_type == DCCP_PKT_REQUEST) ||659659+ (sk->sk_state == DCCP_RESPOND &&660660+ dh->dccph_type == DCCP_PKT_DATA)) {661661+ dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);662662+ goto discard;663663+ } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) {639664 if (dccp_rcv_closereq(sk, skb))640665 return 0;641666 goto discard;642642- } else if (dh->dccph_type == DCCP_PKT_CLOSE) { /* Step 14 */667667+ } else if (dh->dccph_type == DCCP_PKT_CLOSE) {643668 if (dccp_rcv_close(sk, skb))644669 return 0;645670 goto discard;646671 }647672648673 switch (sk->sk_state) {674674+ case DCCP_CLOSED:675675+ dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;676676+ return 1;677677+649678 case DCCP_REQUESTING:679679+ /* FIXME: do congestion control initialization */680680+650681 queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len);651682 if (queued >= 0)652683 return queued;···676663 __kfree_skb(skb);677664 return 0;678665679679- case DCCP_PARTOPEN:680680- /* Step 8: if using Ack Vectors, mark packet acknowledgeable */681681- dccp_handle_ackvec_processing(sk, skb);682682- dccp_deliver_input_to_ccids(sk, skb);683683- /* fall through */684666 case DCCP_RESPOND:667667+ case DCCP_PARTOPEN:685668 queued = dccp_rcv_respond_partopen_state_process(sk, skb,686669 dh, len);687670 break;···716707 /* dccpor_elapsed_time is either zeroed out or set and > 0 */717708 delta -= dccp_sk(sk)->dccps_options_received.dccpor_elapsed_time * 10;718709719719- return dccp_sane_rtt(delta);710710+ if (unlikely(delta <= 0)) {711711+ DCCP_WARN("unusable RTT sample %ld, using min\n", delta);712712+ return DCCP_SANE_RTT_MIN;713713+ }714714+ if (unlikely(delta > DCCP_SANE_RTT_MAX)) {715715+ DCCP_WARN("RTT sample %ld too large, using max\n", delta);716716+ return DCCP_SANE_RTT_MAX;717717+ }718718+719719+ return delta;720720}721721722722EXPORT_SYMBOL_GPL(dccp_sample_rtt);
+1-3
net/dccp/ipv4.c
···545545546546static void dccp_v4_reqsk_destructor(struct request_sock *req)547547{548548- dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);549548 kfree(inet_rsk(req)->opt);550549}551550···595596 if (req == NULL)596597 goto drop;597598598598- if (dccp_reqsk_init(req, dccp_sk(sk), skb))599599- goto drop_and_free;599599+ dccp_reqsk_init(req, skb);600600601601 dreq = dccp_rsk(req);602602 if (dccp_parse_options(sk, dreq, skb))
+1-3
net/dccp/ipv6.c
···302302303303static void dccp_v6_reqsk_destructor(struct request_sock *req)304304{305305- dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);306305 if (inet6_rsk(req)->pktopts != NULL)307306 kfree_skb(inet6_rsk(req)->pktopts);308307}···424425 if (req == NULL)425426 goto drop;426427427427- if (dccp_reqsk_init(req, dccp_sk(sk), skb))428428- goto drop_and_free;428428+ dccp_reqsk_init(req, skb);429429430430 dreq = dccp_rsk(req);431431 if (dccp_parse_options(sk, dreq, skb))
+66-25
net/dccp/minisocks.c
···42424343EXPORT_SYMBOL_GPL(dccp_death_row);44444545+void dccp_minisock_init(struct dccp_minisock *dmsk)4646+{4747+ dmsk->dccpms_sequence_window = sysctl_dccp_feat_sequence_window;4848+ dmsk->dccpms_rx_ccid = sysctl_dccp_feat_rx_ccid;4949+ dmsk->dccpms_tx_ccid = sysctl_dccp_feat_tx_ccid;5050+ dmsk->dccpms_ack_ratio = sysctl_dccp_feat_ack_ratio;5151+ dmsk->dccpms_send_ack_vector = sysctl_dccp_feat_send_ack_vector;5252+ dmsk->dccpms_send_ndp_count = sysctl_dccp_feat_send_ndp_count;5353+}5454+4555void dccp_time_wait(struct sock *sk, int state, int timeo)4656{4757 struct inet_timewait_sock *tw = NULL;···112102 struct sock *newsk = inet_csk_clone(sk, req, GFP_ATOMIC);113103114104 if (newsk != NULL) {115115- struct dccp_request_sock *dreq = dccp_rsk(req);105105+ const struct dccp_request_sock *dreq = dccp_rsk(req);116106 struct inet_connection_sock *newicsk = inet_csk(newsk);117107 struct dccp_sock *newdp = dccp_sk(newsk);108108+ struct dccp_minisock *newdmsk = dccp_msk(newsk);118109119110 newdp->dccps_role = DCCP_ROLE_SERVER;120111 newdp->dccps_hc_rx_ackvec = NULL;···125114 newdp->dccps_timestamp_time = dreq->dreq_timestamp_time;126115 newicsk->icsk_rto = DCCP_TIMEOUT_INIT;127116128128- INIT_LIST_HEAD(&newdp->dccps_featneg);129129- /*130130- * Step 3: Process LISTEN state131131- *132132- * Choose S.ISS (initial seqno) or set from Init Cookies133133- * Initialize S.GAR := S.ISS134134- * Set S.ISR, S.GSR from packet (or Init Cookies)135135- *136136- * Setting AWL/AWH and SWL/SWH happens as part of the feature137137- * activation below, as these windows all depend on the local138138- * and remote Sequence Window feature values (7.5.2).139139- */140140- newdp->dccps_gss = newdp->dccps_iss = dreq->dreq_iss;141141- newdp->dccps_gar = newdp->dccps_iss;142142- newdp->dccps_gsr = newdp->dccps_isr = dreq->dreq_isr;117117+ if (dccp_feat_clone(sk, newsk))118118+ goto out_free;143119144144- /*145145- * Activate features: initialise CCIDs, sequence windows etc.146146- */147147- if (dccp_feat_activate_values(newsk, &dreq->dreq_featneg)) {120120+ if (newdmsk->dccpms_send_ack_vector) {121121+ newdp->dccps_hc_rx_ackvec =122122+ dccp_ackvec_alloc(GFP_ATOMIC);123123+ if (unlikely(newdp->dccps_hc_rx_ackvec == NULL))124124+ goto out_free;125125+ }126126+127127+ newdp->dccps_hc_rx_ccid =128128+ ccid_hc_rx_new(newdmsk->dccpms_rx_ccid,129129+ newsk, GFP_ATOMIC);130130+ newdp->dccps_hc_tx_ccid =131131+ ccid_hc_tx_new(newdmsk->dccpms_tx_ccid,132132+ newsk, GFP_ATOMIC);133133+ if (unlikely(newdp->dccps_hc_rx_ccid == NULL ||134134+ newdp->dccps_hc_tx_ccid == NULL)) {135135+ dccp_ackvec_free(newdp->dccps_hc_rx_ackvec);136136+ ccid_hc_rx_delete(newdp->dccps_hc_rx_ccid, newsk);137137+ ccid_hc_tx_delete(newdp->dccps_hc_tx_ccid, newsk);138138+out_free:148139 /* It is still raw copy of parent, so invalidate149140 * destructor and make plain sk_free() */150141 newsk->sk_destruct = NULL;151142 sk_free(newsk);152143 return NULL;153144 }145145+146146+ /*147147+ * Step 3: Process LISTEN state148148+ *149149+ * Choose S.ISS (initial seqno) or set from Init Cookies150150+ * Initialize S.GAR := S.ISS151151+ * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies152152+ */153153+154154+ /* See dccp_v4_conn_request */155155+ newdmsk->dccpms_sequence_window = req->rcv_wnd;156156+157157+ newdp->dccps_gar = newdp->dccps_iss = dreq->dreq_iss;158158+ dccp_update_gss(newsk, dreq->dreq_iss);159159+160160+ newdp->dccps_isr = dreq->dreq_isr;161161+ dccp_update_gsr(newsk, dreq->dreq_isr);162162+163163+ /*164164+ * SWL and AWL are initially adjusted so that they are not less than165165+ * the initial Sequence Numbers received and sent, respectively:166166+ * SWL := max(GSR + 1 - floor(W/4), ISR),167167+ * AWL := max(GSS - W' + 1, ISS).168168+ * These adjustments MUST be applied only at the beginning of the169169+ * connection.170170+ */171171+ dccp_set_seqno(&newdp->dccps_swl,172172+ max48(newdp->dccps_swl, newdp->dccps_isr));173173+ dccp_set_seqno(&newdp->dccps_awl,174174+ max48(newdp->dccps_awl, newdp->dccps_iss));175175+154176 dccp_init_xmit_timers(newsk);155177156178 DCCP_INC_STATS_BH(DCCP_MIB_PASSIVEOPENS);···304260305261EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack);306262307307-int dccp_reqsk_init(struct request_sock *req,308308- struct dccp_sock const *dp, struct sk_buff const *skb)263263+void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb)309264{310265 struct dccp_request_sock *dreq = dccp_rsk(req);311266312267 inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport;313268 inet_rsk(req)->acked = 0;269269+ req->rcv_wnd = sysctl_dccp_feat_sequence_window;314270 dreq->dreq_timestamp_echo = 0;315315-316316- /* inherit feature negotiation options from listening socket */317317- return dccp_feat_clone_list(&dp->dccps_featneg, &dreq->dreq_featneg);318271}319272320273EXPORT_SYMBOL_GPL(dccp_reqsk_init);
+171-186
net/dccp/options.c
···2323#include "dccp.h"2424#include "feat.h"25252626-u64 dccp_decode_value_var(const u8 *bf, const u8 len)2727-{2828- u64 value = 0;2626+int sysctl_dccp_feat_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW;2727+int sysctl_dccp_feat_rx_ccid = DCCPF_INITIAL_CCID;2828+int sysctl_dccp_feat_tx_ccid = DCCPF_INITIAL_CCID;2929+int sysctl_dccp_feat_ack_ratio = DCCPF_INITIAL_ACK_RATIO;3030+int sysctl_dccp_feat_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR;3131+int sysctl_dccp_feat_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT;29323030- if (len >= DCCP_OPTVAL_MAXLEN)3131- value += ((u64)*bf++) << 40;3232- if (len > 4)3333- value += ((u64)*bf++) << 32;3333+static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len)3434+{3535+ u32 value = 0;3636+3437 if (len > 3)3535- value += ((u64)*bf++) << 24;3838+ value += *bf++ << 24;3639 if (len > 2)3737- value += ((u64)*bf++) << 16;4040+ value += *bf++ << 16;3841 if (len > 1)3939- value += ((u64)*bf++) << 8;4242+ value += *bf++ << 8;4043 if (len > 0)4144 value += *bf;4245···5754 struct dccp_sock *dp = dccp_sk(sk);5855 const struct dccp_hdr *dh = dccp_hdr(skb);5956 const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type;5757+ u64 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;6058 unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);6159 unsigned char *opt_ptr = options;6260 const unsigned char *opt_end = (unsigned char *)dh +···9995 }1009610197 /*9898+ * CCID-Specific Options (from RFC 4340, sec. 10.3):9999+ *100100+ * Option numbers 128 through 191 are for options sent from the101101+ * HC-Sender to the HC-Receiver; option numbers 192 through 255102102+ * are for options sent from the HC-Receiver to the HC-Sender.103103+ *102104 * CCID-specific options are ignored during connection setup, as103105 * negotiation may still be in progress (see RFC 4340, 10.3).104106 * The same applies to Ack Vectors, as these depend on the CCID.107107+ *105108 */106106- if (dreq != NULL && (opt >= DCCPO_MIN_RX_CCID_SPECIFIC ||109109+ if (dreq != NULL && (opt >= 128 ||107110 opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1))108111 goto ignore_option;109112···131120 dccp_pr_debug("%s opt: NDP count=%llu\n", dccp_role(sk),132121 (unsigned long long)opt_recv->dccpor_ndp);133122 break;134134- case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R:135135- if (pkt_type == DCCP_PKT_DATA) /* RFC 4340, 6 */123123+ case DCCPO_CHANGE_L:124124+ /* fall through */125125+ case DCCPO_CHANGE_R:126126+ if (pkt_type == DCCP_PKT_DATA)136127 break;137137- rc = dccp_feat_parse_options(sk, dreq, mandatory, opt,138138- *value, value + 1, len - 1);139139- if (rc)140140- goto out_featneg_failed;128128+ if (len < 2)129129+ goto out_invalid_option;130130+ rc = dccp_feat_change_recv(sk, opt, *value, value + 1,131131+ len - 1);132132+ /*133133+ * When there is a change error, change_recv is134134+ * responsible for dealing with it. i.e. reply with an135135+ * empty confirm.136136+ * If the change was mandatory, then we need to die.137137+ */138138+ if (rc && mandatory)139139+ goto out_invalid_option;140140+ break;141141+ case DCCPO_CONFIRM_L:142142+ /* fall through */143143+ case DCCPO_CONFIRM_R:144144+ if (pkt_type == DCCP_PKT_DATA)145145+ break;146146+ if (len < 2) /* FIXME this disallows empty confirm */147147+ goto out_invalid_option;148148+ if (dccp_feat_confirm_recv(sk, opt, *value,149149+ value + 1, len - 1))150150+ goto out_invalid_option;151151+ break;152152+ case DCCPO_ACK_VECTOR_0:153153+ case DCCPO_ACK_VECTOR_1:154154+ if (dccp_packet_without_ack(skb)) /* RFC 4340, 11.4 */155155+ break;156156+157157+ if (dccp_msk(sk)->dccpms_send_ack_vector &&158158+ dccp_ackvec_parse(sk, skb, &ackno, opt, value, len))159159+ goto out_invalid_option;141160 break;142161 case DCCPO_TIMESTAMP:143162 if (len != 4)···195154 dccp_role(sk), ntohl(opt_val),196155 (unsigned long long)197156 DCCP_SKB_CB(skb)->dccpd_ack_seq);198198- /* schedule an Ack in case this sender is quiescent */199199- inet_csk_schedule_ack(sk);200157 break;201158 case DCCPO_TIMESTAMP_ECHO:202159 if (len != 4 && len != 6 && len != 8)···251212 dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n",252213 dccp_role(sk), elapsed_time);253214 break;254254- case DCCPO_MIN_RX_CCID_SPECIFIC ... DCCPO_MAX_RX_CCID_SPECIFIC:215215+ case 128 ... 191: {216216+ const u16 idx = value - options;217217+255218 if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk,256256- pkt_type, opt, value, len))219219+ opt, len, idx,220220+ value) != 0)257221 goto out_invalid_option;222222+ }258223 break;259259- case DCCPO_ACK_VECTOR_0:260260- case DCCPO_ACK_VECTOR_1:261261- if (dccp_packet_without_ack(skb)) /* RFC 4340, 11.4 */262262- break;263263- /*264264- * Ack vectors are processed by the TX CCID if it is265265- * interested. The RX CCID need not parse Ack Vectors,266266- * since it is only interested in clearing old state.267267- * Fall through.268268- */269269- case DCCPO_MIN_TX_CCID_SPECIFIC ... DCCPO_MAX_TX_CCID_SPECIFIC:224224+ case 192 ... 255: {225225+ const u16 idx = value - options;226226+270227 if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk,271271- pkt_type, opt, value, len))228228+ opt, len, idx,229229+ value) != 0)272230 goto out_invalid_option;231231+ }273232 break;274233 default:275234 DCCP_CRIT("DCCP(%p): option %d(len=%d) not "···289252290253out_invalid_option:291254 DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT);292292- rc = DCCP_RESET_CODE_OPTION_ERROR;293293-out_featneg_failed:294294- DCCP_WARN("DCCP(%p): Option %d (len=%d) error=%u\n", sk, opt, len, rc);295295- DCCP_SKB_CB(skb)->dccpd_reset_code = rc;255255+ DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_OPTION_ERROR;256256+ DCCP_WARN("DCCP(%p): invalid option %d, len=%d", sk, opt, len);296257 DCCP_SKB_CB(skb)->dccpd_reset_data[0] = opt;297258 DCCP_SKB_CB(skb)->dccpd_reset_data[1] = len > 0 ? value[0] : 0;298259 DCCP_SKB_CB(skb)->dccpd_reset_data[2] = len > 1 ? value[1] : 0;···299264300265EXPORT_SYMBOL_GPL(dccp_parse_options);301266302302-void dccp_encode_value_var(const u64 value, u8 *to, const u8 len)267267+static void dccp_encode_value_var(const u32 value, unsigned char *to,268268+ const unsigned int len)303269{304304- if (len >= DCCP_OPTVAL_MAXLEN)305305- *to++ = (value & 0xFF0000000000ull) >> 40;306306- if (len > 4)307307- *to++ = (value & 0xFF00000000ull) >> 32;308270 if (len > 3)309271 *to++ = (value & 0xFF000000) >> 24;310272 if (len > 2)···461429 return 0;462430}463431464464-static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)432432+static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,433433+ u8 *val, u8 len)465434{466466- struct dccp_sock *dp = dccp_sk(sk);467467- struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;468468- struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);469469- const u16 buflen = dccp_ackvec_buflen(av);470470- /* Figure out how many options do we need to represent the ackvec */471471- const u8 nr_opts = DIV_ROUND_UP(buflen, DCCP_SINGLE_OPT_MAXLEN);472472- u16 len = buflen + 2 * nr_opts;473473- u8 i, nonce = 0;474474- const unsigned char *tail, *from;475475- unsigned char *to;435435+ u8 *to;476436477477- if (dcb->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {478478- DCCP_WARN("Lacking space for %u bytes on %s packet\n", len,479479- dccp_packet_name(dcb->dccpd_type));480480- return -1;481481- }482482- /*483483- * Since Ack Vectors are variable-length, we can not always predict484484- * their size. To catch exception cases where the space is running out485485- * on the skb, a separate Sync is scheduled to carry the Ack Vector.486486- */487487- if (len > DCCPAV_MIN_OPTLEN &&488488- len + dcb->dccpd_opt_len + skb->len > dp->dccps_mss_cache) {489489- DCCP_WARN("No space left for Ack Vector (%u) on skb (%u+%u), "490490- "MPS=%u ==> reduce payload size?\n", len, skb->len,491491- dcb->dccpd_opt_len, dp->dccps_mss_cache);492492- dp->dccps_sync_scheduled = 1;493493- return 0;494494- }495495- dcb->dccpd_opt_len += len;496496-497497- to = skb_push(skb, len);498498- len = buflen;499499- from = av->av_buf + av->av_buf_head;500500- tail = av->av_buf + DCCPAV_MAX_ACKVEC_LEN;501501-502502- for (i = 0; i < nr_opts; ++i) {503503- int copylen = len;504504-505505- if (len > DCCP_SINGLE_OPT_MAXLEN)506506- copylen = DCCP_SINGLE_OPT_MAXLEN;507507-508508- /*509509- * RFC 4340, 12.2: Encode the Nonce Echo for this Ack Vector via510510- * its type; ack_nonce is the sum of all individual buf_nonce's.511511- */512512- nonce ^= av->av_buf_nonce[i];513513-514514- *to++ = DCCPO_ACK_VECTOR_0 + av->av_buf_nonce[i];515515- *to++ = copylen + 2;516516-517517- /* Check if buf_head wraps */518518- if (from + copylen > tail) {519519- const u16 tailsize = tail - from;520520-521521- memcpy(to, from, tailsize);522522- to += tailsize;523523- len -= tailsize;524524- copylen -= tailsize;525525- from = av->av_buf;526526- }527527-528528- memcpy(to, from, copylen);529529- from += copylen;530530- to += copylen;531531- len -= copylen;532532- }533533- /*534534- * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340.535535- */536536- if (dccp_ackvec_update_records(av, dcb->dccpd_seq, nonce))537537- return -ENOBUFS;538538- return 0;539539-}540540-541541-/**542542- * dccp_insert_option_mandatory - Mandatory option (5.8.2)543543- * Note that since we are using skb_push, this function needs to be called544544- * _after_ inserting the option it is supposed to influence (stack order).545545- */546546-int dccp_insert_option_mandatory(struct sk_buff *skb)547547-{548548- if (DCCP_SKB_CB(skb)->dccpd_opt_len >= DCCP_MAX_OPT_LEN)549549- return -1;550550-551551- DCCP_SKB_CB(skb)->dccpd_opt_len++;552552- *skb_push(skb, 1) = DCCPO_MANDATORY;553553- return 0;554554-}555555-556556-/**557557- * dccp_insert_fn_opt - Insert single Feature-Negotiation option into @skb558558- * @type: %DCCPO_CHANGE_L, %DCCPO_CHANGE_R, %DCCPO_CONFIRM_L, %DCCPO_CONFIRM_R559559- * @feat: one out of %dccp_feature_numbers560560- * @val: NN value or SP array (preferred element first) to copy561561- * @len: true length of @val in bytes (excluding first element repetition)562562- * @repeat_first: whether to copy the first element of @val twice563563- * The last argument is used to construct Confirm options, where the preferred564564- * value and the preference list appear separately (RFC 4340, 6.3.1). Preference565565- * lists are kept such that the preferred entry is always first, so we only need566566- * to copy twice, and avoid the overhead of cloning into a bigger array.567567- */568568-int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat,569569- u8 *val, u8 len, bool repeat_first)570570-{571571- u8 tot_len, *to;572572-573573- /* take the `Feature' field and possible repetition into account */574574- if (len > (DCCP_SINGLE_OPT_MAXLEN - 2)) {575575- DCCP_WARN("length %u for feature %u too large\n", len, feat);576576- return -1;577577- }578578-579579- if (unlikely(val == NULL || len == 0))580580- len = repeat_first = 0;581581- tot_len = 3 + repeat_first + len;582582-583583- if (DCCP_SKB_CB(skb)->dccpd_opt_len + tot_len > DCCP_MAX_OPT_LEN) {437437+ if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 3 > DCCP_MAX_OPT_LEN) {584438 DCCP_WARN("packet too small for feature %d option!\n", feat);585439 return -1;586440 }587587- DCCP_SKB_CB(skb)->dccpd_opt_len += tot_len;588441589589- to = skb_push(skb, tot_len);442442+ DCCP_SKB_CB(skb)->dccpd_opt_len += len + 3;443443+444444+ to = skb_push(skb, len + 3);590445 *to++ = type;591591- *to++ = tot_len;446446+ *to++ = len + 3;592447 *to++ = feat;593448594594- if (repeat_first)595595- *to++ = *val;596449 if (len)597450 memcpy(to, val, len);451451+452452+ dccp_pr_debug("%s(%s (%d), ...), length %d\n",453453+ dccp_feat_typename(type),454454+ dccp_feat_name(feat), feat, len);455455+ return 0;456456+}457457+458458+static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb)459459+{460460+ struct dccp_sock *dp = dccp_sk(sk);461461+ struct dccp_minisock *dmsk = dccp_msk(sk);462462+ struct dccp_opt_pend *opt, *next;463463+ int change = 0;464464+465465+ /* confirm any options [NN opts] */466466+ list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) {467467+ dccp_insert_feat_opt(skb, opt->dccpop_type,468468+ opt->dccpop_feat, opt->dccpop_val,469469+ opt->dccpop_len);470470+ /* fear empty confirms */471471+ if (opt->dccpop_val)472472+ kfree(opt->dccpop_val);473473+ kfree(opt);474474+ }475475+ INIT_LIST_HEAD(&dmsk->dccpms_conf);476476+477477+ /* see which features we need to send */478478+ list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {479479+ /* see if we need to send any confirm */480480+ if (opt->dccpop_sc) {481481+ dccp_insert_feat_opt(skb, opt->dccpop_type + 1,482482+ opt->dccpop_feat,483483+ opt->dccpop_sc->dccpoc_val,484484+ opt->dccpop_sc->dccpoc_len);485485+486486+ BUG_ON(!opt->dccpop_sc->dccpoc_val);487487+ kfree(opt->dccpop_sc->dccpoc_val);488488+ kfree(opt->dccpop_sc);489489+ opt->dccpop_sc = NULL;490490+ }491491+492492+ /* any option not confirmed, re-send it */493493+ if (!opt->dccpop_conf) {494494+ dccp_insert_feat_opt(skb, opt->dccpop_type,495495+ opt->dccpop_feat, opt->dccpop_val,496496+ opt->dccpop_len);497497+ change++;498498+ }499499+ }500500+501501+ /* Retransmit timer.502502+ * If this is the master listening sock, we don't set a timer on it. It503503+ * should be fine because if the dude doesn't receive our RESPONSE504504+ * [which will contain the CHANGE] he will send another REQUEST which505505+ * will "retrnasmit" the change.506506+ */507507+ if (change && dp->dccps_role != DCCP_ROLE_LISTEN) {508508+ dccp_pr_debug("reset feat negotiation timer %p\n", sk);509509+510510+ /* XXX don't reset the timer on re-transmissions. I.e. reset it511511+ * only when sending new stuff i guess. Currently the timer512512+ * never backs off because on re-transmission it just resets it!513513+ */514514+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,515515+ inet_csk(sk)->icsk_rto, DCCP_RTO_MAX);516516+ }517517+598518 return 0;599519}600520···565581int dccp_insert_options(struct sock *sk, struct sk_buff *skb)566582{567583 struct dccp_sock *dp = dccp_sk(sk);584584+ struct dccp_minisock *dmsk = dccp_msk(sk);568585569586 DCCP_SKB_CB(skb)->dccpd_opt_len = 0;570587571571- if (dp->dccps_send_ndp_count && dccp_insert_option_ndp(sk, skb))588588+ if (dmsk->dccpms_send_ndp_count &&589589+ dccp_insert_option_ndp(sk, skb))572590 return -1;573591574574- if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA) {575575-576576- /* Feature Negotiation */577577- if (dccp_feat_insert_opts(dp, NULL, skb))592592+ if (!dccp_packet_without_ack(skb)) {593593+ if (dmsk->dccpms_send_ack_vector &&594594+ dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) &&595595+ dccp_insert_option_ackvec(sk, skb))578596 return -1;579579-580580- if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_REQUEST) {581581- /*582582- * Obtain RTT sample from Request/Response exchange.583583- * This is currently used in CCID 3 initialisation.584584- */585585- if (dccp_insert_option_timestamp(sk, skb))586586- return -1;587587-588588- } else if (dccp_ackvec_pending(sk) &&589589- dccp_insert_option_ackvec(sk, skb)) {590590- return -1;591591- }592597 }593598594599 if (dp->dccps_hc_rx_insert_options) {···585612 return -1;586613 dp->dccps_hc_rx_insert_options = 0;587614 }615615+616616+ /* Feature negotiation */617617+ /* Data packets can't do feat negotiation */618618+ if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA &&619619+ DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATAACK &&620620+ dccp_insert_options_feat(sk, skb))621621+ return -1;622622+623623+ /*624624+ * Obtain RTT sample from Request/Response exchange.625625+ * This is currently used in CCID 3 initialisation.626626+ */627627+ if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_REQUEST &&628628+ dccp_insert_option_timestamp(sk, skb))629629+ return -1;588630589631 if (dp->dccps_timestamp_echo != 0 &&590632 dccp_insert_option_timestamp_echo(dp, NULL, skb))···612624int dccp_insert_options_rsk(struct dccp_request_sock *dreq, struct sk_buff *skb)613625{614626 DCCP_SKB_CB(skb)->dccpd_opt_len = 0;615615-616616- if (dccp_feat_insert_opts(NULL, dreq, skb))617617- return -1;618627619628 if (dreq->dreq_timestamp_echo != 0 &&620629 dccp_insert_option_timestamp_echo(NULL, dreq, skb))
+102-177
net/dccp/output.c
···2626 inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);2727}28282929-/* enqueue @skb on sk_send_head for retransmission, return clone to send now */3030-static struct sk_buff *dccp_skb_entail(struct sock *sk, struct sk_buff *skb)2929+static void dccp_skb_entail(struct sock *sk, struct sk_buff *skb)3130{3231 skb_set_owner_w(skb, sk);3332 WARN_ON(sk->sk_send_head);3433 sk->sk_send_head = skb;3535- return skb_clone(sk->sk_send_head, gfp_any());3634}37353836/*···161163 struct inet_connection_sock *icsk = inet_csk(sk);162164 struct dccp_sock *dp = dccp_sk(sk);163165 u32 ccmps = dccp_determine_ccmps(dp);164164- u32 cur_mps = ccmps ? min(pmtu, ccmps) : pmtu;166166+ int cur_mps = ccmps ? min(pmtu, ccmps) : pmtu;165167166168 /* Account for header lengths and IPv4/v6 option overhead */167169 cur_mps -= (icsk->icsk_af_ops->net_header_len + icsk->icsk_ext_hdr_len +168170 sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));169171170172 /*171171- * Leave enough headroom for common DCCP header options.172172- * This only considers options which may appear on DCCP-Data packets, as173173- * per table 3 in RFC 4340, 5.8. When running out of space for other174174- * options (eg. Ack Vector which can take up to 255 bytes), it is better175175- * to schedule a separate Ack. Thus we leave headroom for the following:176176- * - 1 byte for Slow Receiver (11.6)177177- * - 6 bytes for Timestamp (13.1)178178- * - 10 bytes for Timestamp Echo (13.3)179179- * - 8 bytes for NDP count (7.7, when activated)180180- * - 6 bytes for Data Checksum (9.3)181181- * - %DCCPAV_MIN_OPTLEN bytes for Ack Vector size (11.4, when enabled)173173+ * FIXME: this should come from the CCID infrastructure, where, say,174174+ * TFRC will say it wants TIMESTAMPS, ELAPSED time, etc, for now lets175175+ * put a rough estimate for NDP + TIMESTAMP + TIMESTAMP_ECHO + ELAPSED176176+ * TIME + TFRC_OPT_LOSS_EVENT_RATE + TFRC_OPT_RECEIVE_RATE + padding to177177+ * make it a multiple of 4182178 */183183- cur_mps -= roundup(1 + 6 + 10 + dp->dccps_send_ndp_count * 8 + 6 +184184- (dp->dccps_hc_rx_ackvec ? DCCPAV_MIN_OPTLEN : 0), 4);179179+180180+ cur_mps -= ((5 + 6 + 10 + 6 + 6 + 6 + 3) / 4) * 4;185181186182 /* And store cached results */187183 icsk->icsk_pmtu_cookie = pmtu;···200208}201209202210/**203203- * dccp_wait_for_ccid - Await CCID send permission211211+ * dccp_wait_for_ccid - Wait for ccid to tell us we can send a packet204212 * @sk: socket to wait for205205- * @delay: timeout in jiffies206206- * This is used by CCIDs which need to delay the send time in process context.213213+ * @skb: current skb to pass on for waiting214214+ * @delay: sleep timeout in milliseconds (> 0)215215+ * This function is called by default when the socket is closed, and216216+ * when a non-zero linger time is set on the socket. For consistency207217 */208208-static int dccp_wait_for_ccid(struct sock *sk, unsigned long delay)218218+static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb, int delay)209219{220220+ struct dccp_sock *dp = dccp_sk(sk);210221 DEFINE_WAIT(wait);211211- long remaining;222222+ unsigned long jiffdelay;223223+ int rc;212224213213- prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);214214- sk->sk_write_pending++;215215- release_sock(sk);225225+ do {226226+ dccp_pr_debug("delayed send by %d msec\n", delay);227227+ jiffdelay = msecs_to_jiffies(delay);216228217217- remaining = schedule_timeout(delay);229229+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);218230219219- lock_sock(sk);220220- sk->sk_write_pending--;221221- finish_wait(sk->sk_sleep, &wait);231231+ sk->sk_write_pending++;232232+ release_sock(sk);233233+ schedule_timeout(jiffdelay);234234+ lock_sock(sk);235235+ sk->sk_write_pending--;222236223223- if (signal_pending(current) || sk->sk_err)224224- return -1;225225- return remaining;226226-}237237+ if (sk->sk_err)238238+ goto do_error;239239+ if (signal_pending(current))240240+ goto do_interrupted;227241228228-/**229229- * dccp_xmit_packet - Send data packet under control of CCID230230- * Transmits next-queued payload and informs CCID to account for the packet.231231- */232232-static void dccp_xmit_packet(struct sock *sk)233233-{234234- int err, len;235235- struct dccp_sock *dp = dccp_sk(sk);236236- struct sk_buff *skb = dccp_qpolicy_pop(sk);237237-238238- if (unlikely(skb == NULL))239239- return;240240- len = skb->len;241241-242242- if (sk->sk_state == DCCP_PARTOPEN) {243243- const u32 cur_mps = dp->dccps_mss_cache - DCCP_FEATNEG_OVERHEAD;244244- /*245245- * See 8.1.5 - Handshake Completion.246246- *247247- * For robustness we resend Confirm options until the client has248248- * entered OPEN. During the initial feature negotiation, the MPS249249- * is smaller than usual, reduced by the Change/Confirm options.250250- */251251- if (!list_empty(&dp->dccps_featneg) && len > cur_mps) {252252- DCCP_WARN("Payload too large (%d) for featneg.\n", len);253253- dccp_send_ack(sk);254254- dccp_feat_list_purge(&dp->dccps_featneg);255255- }256256-257257- inet_csk_schedule_ack(sk);258258- inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,259259- inet_csk(sk)->icsk_rto,260260- DCCP_RTO_MAX);261261- DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_DATAACK;262262- } else if (dccp_ack_pending(sk)) {263263- DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_DATAACK;264264- } else {265265- DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_DATA;266266- }267267-268268- err = dccp_transmit_skb(sk, skb);269269- if (err)270270- dccp_pr_debug("transmit_skb() returned err=%d\n", err);271271- /*272272- * Register this one as sent even if an error occurred. To the remote273273- * end a local packet drop is indistinguishable from network loss, i.e.274274- * any local drop will eventually be reported via receiver feedback.275275- */276276- ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, len);277277-278278- /*279279- * If the CCID needs to transfer additional header options out-of-band280280- * (e.g. Ack Vectors or feature-negotiation options), it activates this281281- * flag to schedule a Sync. The Sync will automatically incorporate all282282- * currently pending header options, thus clearing the backlog.283283- */284284- if (dp->dccps_sync_scheduled)285285- dccp_send_sync(sk, dp->dccps_gsr, DCCP_PKT_SYNC);286286-}287287-288288-/**289289- * dccp_flush_write_queue - Drain queue at end of connection290290- * Since dccp_sendmsg queues packets without waiting for them to be sent, it may291291- * happen that the TX queue is not empty at the end of a connection. We give the292292- * HC-sender CCID a grace period of up to @time_budget jiffies. If this function293293- * returns with a non-empty write queue, it will be purged later.294294- */295295-void dccp_flush_write_queue(struct sock *sk, long *time_budget)296296-{297297- struct dccp_sock *dp = dccp_sk(sk);298298- struct sk_buff *skb;299299- long delay, rc;300300-301301- while (*time_budget > 0 && (skb = skb_peek(&sk->sk_write_queue))) {302242 rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb);243243+ } while ((delay = rc) > 0);244244+out:245245+ finish_wait(sk->sk_sleep, &wait);246246+ return rc;303247304304- switch (ccid_packet_dequeue_eval(rc)) {305305- case CCID_PACKET_WILL_DEQUEUE_LATER:306306- /*307307- * If the CCID determines when to send, the next sending308308- * time is unknown or the CCID may not even send again309309- * (e.g. remote host crashes or lost Ack packets).310310- */311311- DCCP_WARN("CCID did not manage to send all packets\n");312312- return;313313- case CCID_PACKET_DELAY:314314- delay = msecs_to_jiffies(rc);315315- if (delay > *time_budget)316316- return;317317- rc = dccp_wait_for_ccid(sk, delay);318318- if (rc < 0)319319- return;320320- *time_budget -= (delay - rc);321321- /* check again if we can send now */322322- break;323323- case CCID_PACKET_SEND_AT_ONCE:324324- dccp_xmit_packet(sk);325325- break;326326- case CCID_PACKET_ERR:327327- skb_dequeue(&sk->sk_write_queue);328328- kfree_skb(skb);329329- dccp_pr_debug("packet discarded due to err=%ld\n", rc);330330- }331331- }248248+do_error:249249+ rc = -EPIPE;250250+ goto out;251251+do_interrupted:252252+ rc = -EINTR;253253+ goto out;332254}333255334334-void dccp_write_xmit(struct sock *sk)256256+void dccp_write_xmit(struct sock *sk, int block)335257{336258 struct dccp_sock *dp = dccp_sk(sk);337259 struct sk_buff *skb;338260339339- while ((skb = dccp_qpolicy_top(sk))) {340340- int rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb);261261+ while ((skb = skb_peek(&sk->sk_write_queue))) {262262+ int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb);341263342342- switch (ccid_packet_dequeue_eval(rc)) {343343- case CCID_PACKET_WILL_DEQUEUE_LATER:344344- return;345345- case CCID_PACKET_DELAY:346346- sk_reset_timer(sk, &dp->dccps_xmit_timer,347347- jiffies + msecs_to_jiffies(rc));348348- return;349349- case CCID_PACKET_SEND_AT_ONCE:350350- dccp_xmit_packet(sk);351351- break;352352- case CCID_PACKET_ERR:353353- dccp_qpolicy_drop(sk, skb);354354- dccp_pr_debug("packet discarded due to err=%d\n", rc);264264+ if (err > 0) {265265+ if (!block) {266266+ sk_reset_timer(sk, &dp->dccps_xmit_timer,267267+ msecs_to_jiffies(err)+jiffies);268268+ break;269269+ } else270270+ err = dccp_wait_for_ccid(sk, skb, err);271271+ if (err && err != -EINTR)272272+ DCCP_BUG("err=%d after dccp_wait_for_ccid", err);273273+ }274274+275275+ skb_dequeue(&sk->sk_write_queue);276276+ if (err == 0) {277277+ struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);278278+ const int len = skb->len;279279+280280+ if (sk->sk_state == DCCP_PARTOPEN) {281281+ /* See 8.1.5. Handshake Completion */282282+ inet_csk_schedule_ack(sk);283283+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,284284+ inet_csk(sk)->icsk_rto,285285+ DCCP_RTO_MAX);286286+ dcb->dccpd_type = DCCP_PKT_DATAACK;287287+ } else if (dccp_ack_pending(sk))288288+ dcb->dccpd_type = DCCP_PKT_DATAACK;289289+ else290290+ dcb->dccpd_type = DCCP_PKT_DATA;291291+292292+ err = dccp_transmit_skb(sk, skb);293293+ ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len);294294+ if (err)295295+ DCCP_BUG("err=%d after ccid_hc_tx_packet_sent",296296+ err);297297+ } else {298298+ dccp_pr_debug("packet discarded due to err=%d\n", err);299299+ kfree_skb(skb);355300 }356301 }357302}···339410 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;340411 DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss;341412342342- /* Resolve feature dependencies resulting from choice of CCID */343343- if (dccp_feat_server_ccid_dependencies(dreq))344344- goto response_failed;345345-346346- if (dccp_insert_options_rsk(dreq, skb))347347- goto response_failed;413413+ if (dccp_insert_options_rsk(dreq, skb)) {414414+ kfree_skb(skb);415415+ return NULL;416416+ }348417349418 /* Build and checksum header */350419 dh = dccp_zeroed_hdr(skb, dccp_header_size);···363436 inet_rsk(req)->acked = 1;364437 DCCP_INC_STATS(DCCP_MIB_OUTSEGS);365438 return skb;366366-response_failed:367367- kfree_skb(skb);368368- return NULL;369439}370440371441EXPORT_SYMBOL_GPL(dccp_make_response);···447523/*448524 * Do all connect socket setups that can be done AF independent.449525 */450450-int dccp_connect(struct sock *sk)526526+static inline void dccp_connect_init(struct sock *sk)451527{452452- struct sk_buff *skb;453528 struct dccp_sock *dp = dccp_sk(sk);454529 struct dst_entry *dst = __sk_dst_get(sk);455530 struct inet_connection_sock *icsk = inet_csk(sk);···458535459536 dccp_sync_mss(sk, dst_mtu(dst));460537461461- /* do not connect if feature negotiation setup fails */462462- if (dccp_feat_finalise_settings(dccp_sk(sk)))463463- return -EPROTO;464464-465538 /* Initialise GAR as per 8.5; AWL/AWH are set in dccp_transmit_skb() */466539 dp->dccps_gar = dp->dccps_iss;540540+541541+ icsk->icsk_retransmits = 0;542542+}543543+544544+int dccp_connect(struct sock *sk)545545+{546546+ struct sk_buff *skb;547547+ struct inet_connection_sock *icsk = inet_csk(sk);548548+549549+ dccp_connect_init(sk);467550468551 skb = alloc_skb(sk->sk_prot->max_header, sk->sk_allocation);469552 if (unlikely(skb == NULL))···480551481552 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;482553483483- dccp_transmit_skb(sk, dccp_skb_entail(sk, skb));554554+ dccp_skb_entail(sk, skb);555555+ dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL));484556 DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS);485557486558 /* Timer for repeating the REQUEST until an answer. */487487- icsk->icsk_retransmits = 0;488559 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,489560 icsk->icsk_rto, DCCP_RTO_MAX);490561 return 0;···571642 DCCP_SKB_CB(skb)->dccpd_type = pkt_type;572643 DCCP_SKB_CB(skb)->dccpd_ack_seq = ackno;573644574574- /*575575- * Clear the flag in case the Sync was scheduled for out-of-band data,576576- * such as carrying a long Ack Vector.577577- */578578- dccp_sk(sk)->dccps_sync_scheduled = 0;579579-580645 dccp_transmit_skb(sk, skb);581646}582647···599676 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSE;600677601678 if (active) {602602- skb = dccp_skb_entail(sk, skb);679679+ dccp_write_xmit(sk, 1);680680+ dccp_skb_entail(sk, skb);681681+ dccp_transmit_skb(sk, skb_clone(skb, prio));603682 /*604683 * Retransmission timer for active-close: RFC 4340, 8.3 requires605684 * to retransmit the Close/CloseReq until the CLOSING/CLOSEREQ···614689 */615690 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,616691 DCCP_TIMEOUT_INIT, DCCP_RTO_MAX);617617- }618618- dccp_transmit_skb(sk, skb);692692+ } else693693+ dccp_transmit_skb(sk, skb);619694}
···6767 case DCCP_OPEN:6868 if (oldstate != DCCP_OPEN)6969 DCCP_INC_STATS(DCCP_MIB_CURRESTAB);7070- /* Client retransmits all Confirm options until entering OPEN */7171- if (oldstate == DCCP_PARTOPEN)7272- dccp_feat_list_purge(&dccp_sk(sk)->dccps_featneg);7370 break;74717572 case DCCP_CLOSED:···175178int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)176179{177180 struct dccp_sock *dp = dccp_sk(sk);181181+ struct dccp_minisock *dmsk = dccp_msk(sk);178182 struct inet_connection_sock *icsk = inet_csk(sk);183183+184184+ dccp_minisock_init(&dp->dccps_minisock);179185180186 icsk->icsk_rto = DCCP_TIMEOUT_INIT;181187 icsk->icsk_syn_retries = sysctl_dccp_request_retries;182188 sk->sk_state = DCCP_CLOSED;183189 sk->sk_write_space = dccp_write_space;184190 icsk->icsk_sync_mss = dccp_sync_mss;185185- dp->dccps_mss_cache = TCP_MIN_RCVMSS;191191+ dp->dccps_mss_cache = 536;186192 dp->dccps_rate_last = jiffies;187193 dp->dccps_role = DCCP_ROLE_UNDEFINED;188194 dp->dccps_service = DCCP_SERVICE_CODE_IS_ABSENT;189189- dp->dccps_tx_qlen = sysctl_dccp_tx_qlen;195195+ dp->dccps_l_ack_ratio = dp->dccps_r_ack_ratio = 1;190196191197 dccp_init_xmit_timers(sk);192198193193- INIT_LIST_HEAD(&dp->dccps_featneg);194194- /* control socket doesn't need feat nego */195195- if (likely(ctl_sock_initialized))196196- return dccp_feat_init(sk);199199+ /*200200+ * FIXME: We're hardcoding the CCID, and doing this at this point makes201201+ * the listening (master) sock get CCID control blocks, which is not202202+ * necessary, but for now, to not mess with the test userspace apps,203203+ * lets leave it here, later the real solution is to do this in a204204+ * setsockopt(CCIDs-I-want/accept). -acme205205+ */206206+ if (likely(ctl_sock_initialized)) {207207+ int rc = dccp_feat_init(dmsk);208208+209209+ if (rc)210210+ return rc;211211+212212+ if (dmsk->dccpms_send_ack_vector) {213213+ dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL);214214+ if (dp->dccps_hc_rx_ackvec == NULL)215215+ return -ENOMEM;216216+ }217217+ dp->dccps_hc_rx_ccid = ccid_hc_rx_new(dmsk->dccpms_rx_ccid,218218+ sk, GFP_KERNEL);219219+ dp->dccps_hc_tx_ccid = ccid_hc_tx_new(dmsk->dccpms_tx_ccid,220220+ sk, GFP_KERNEL);221221+ if (unlikely(dp->dccps_hc_rx_ccid == NULL ||222222+ dp->dccps_hc_tx_ccid == NULL)) {223223+ ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);224224+ ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);225225+ if (dmsk->dccpms_send_ack_vector) {226226+ dccp_ackvec_free(dp->dccps_hc_rx_ackvec);227227+ dp->dccps_hc_rx_ackvec = NULL;228228+ }229229+ dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;230230+ return -ENOMEM;231231+ }232232+ } else {233233+ /* control socket doesn't need feat nego */234234+ INIT_LIST_HEAD(&dmsk->dccpms_pending);235235+ INIT_LIST_HEAD(&dmsk->dccpms_conf);236236+ }237237+197238 return 0;198239}199240···240205void dccp_destroy_sock(struct sock *sk)241206{242207 struct dccp_sock *dp = dccp_sk(sk);208208+ struct dccp_minisock *dmsk = dccp_msk(sk);243209244210 /*245211 * DCCP doesn't use sk_write_queue, just sk_send_head···258222 kfree(dp->dccps_service_list);259223 dp->dccps_service_list = NULL;260224261261- if (dp->dccps_hc_rx_ackvec != NULL) {225225+ if (dmsk->dccpms_send_ack_vector) {262226 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);263227 dp->dccps_hc_rx_ackvec = NULL;264228 }···267231 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;268232269233 /* clean up feature negotiation state */270270- dccp_feat_list_purge(&dp->dccps_featneg);234234+ dccp_feat_clean(dmsk);271235}272236273237EXPORT_SYMBOL_GPL(dccp_destroy_sock);···277241 struct dccp_sock *dp = dccp_sk(sk);278242279243 dp->dccps_role = DCCP_ROLE_LISTEN;280280- /* do not start to listen if feature negotiation setup fails */281281- if (dccp_feat_finalise_settings(dp))282282- return -EPROTO;283244 return inet_csk_listen_start(sk, backlog);284245}285246···466433 return 0;467434}468435469469-static int dccp_setsockopt_cscov(struct sock *sk, int cscov, bool rx)436436+/* byte 1 is feature. the rest is the preference list */437437+static int dccp_setsockopt_change(struct sock *sk, int type,438438+ struct dccp_so_feat __user *optval)470439{471471- u8 *list, len;472472- int i, rc;473473-474474- if (cscov < 0 || cscov > 15)475475- return -EINVAL;476476- /*477477- * Populate a list of permissible values, in the range cscov...15. This478478- * is necessary since feature negotiation of single values only works if479479- * both sides incidentally choose the same value. Since the list starts480480- * lowest-value first, negotiation will pick the smallest shared value.481481- */482482- if (cscov == 0)483483- return 0;484484- len = 16 - cscov;485485-486486- list = kmalloc(len, GFP_KERNEL);487487- if (list == NULL)488488- return -ENOBUFS;489489-490490- for (i = 0; i < len; i++)491491- list[i] = cscov++;492492-493493- rc = dccp_feat_register_sp(sk, DCCPF_MIN_CSUM_COVER, rx, list, len);494494-495495- if (rc == 0) {496496- if (rx)497497- dccp_sk(sk)->dccps_pcrlen = cscov;498498- else499499- dccp_sk(sk)->dccps_pcslen = cscov;500500- }501501- kfree(list);502502- return rc;503503-}504504-505505-static int dccp_setsockopt_ccid(struct sock *sk, int type,506506- char __user *optval, int optlen)507507-{440440+ struct dccp_so_feat opt;508441 u8 *val;509509- int rc = 0;442442+ int rc;510443511511- if (optlen < 1 || optlen > DCCP_FEAT_MAX_SP_VALS)444444+ if (copy_from_user(&opt, optval, sizeof(opt)))445445+ return -EFAULT;446446+ /*447447+ * rfc4340: 6.1. Change Options448448+ */449449+ if (opt.dccpsf_len < 1)512450 return -EINVAL;513451514514- val = kmalloc(optlen, GFP_KERNEL);515515- if (val == NULL)452452+ val = kmalloc(opt.dccpsf_len, GFP_KERNEL);453453+ if (!val)516454 return -ENOMEM;517455518518- if (copy_from_user(val, optval, optlen)) {519519- kfree(val);520520- return -EFAULT;456456+ if (copy_from_user(val, opt.dccpsf_val, opt.dccpsf_len)) {457457+ rc = -EFAULT;458458+ goto out_free_val;521459 }522460523523- lock_sock(sk);524524- if (type == DCCP_SOCKOPT_TX_CCID || type == DCCP_SOCKOPT_CCID)525525- rc = dccp_feat_register_sp(sk, DCCPF_CCID, 1, val, optlen);461461+ rc = dccp_feat_change(dccp_msk(sk), type, opt.dccpsf_feat,462462+ val, opt.dccpsf_len, GFP_KERNEL);463463+ if (rc)464464+ goto out_free_val;526465527527- if (!rc && (type == DCCP_SOCKOPT_RX_CCID || type == DCCP_SOCKOPT_CCID))528528- rc = dccp_feat_register_sp(sk, DCCPF_CCID, 0, val, optlen);529529- release_sock(sk);530530-531531- kfree(val);466466+out:532467 return rc;468468+469469+out_free_val:470470+ kfree(val);471471+ goto out;533472}534473535474static int do_dccp_setsockopt(struct sock *sk, int level, int optname,···510505 struct dccp_sock *dp = dccp_sk(sk);511506 int val, err = 0;512507513513- switch (optname) {514514- case DCCP_SOCKOPT_PACKET_SIZE:515515- DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n");516516- return 0;517517- case DCCP_SOCKOPT_CHANGE_L:518518- case DCCP_SOCKOPT_CHANGE_R:519519- DCCP_WARN("sockopt(CHANGE_L/R) is deprecated: fix your app\n");520520- return 0;521521- case DCCP_SOCKOPT_CCID:522522- case DCCP_SOCKOPT_RX_CCID:523523- case DCCP_SOCKOPT_TX_CCID:524524- return dccp_setsockopt_ccid(sk, optname, optval, optlen);525525- }526526-527527- if (optlen < (int)sizeof(int))508508+ if (optlen < sizeof(int))528509 return -EINVAL;529510530511 if (get_user(val, (int __user *)optval))···521530522531 lock_sock(sk);523532 switch (optname) {533533+ case DCCP_SOCKOPT_PACKET_SIZE:534534+ DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n");535535+ err = 0;536536+ break;537537+ case DCCP_SOCKOPT_CHANGE_L:538538+ if (optlen != sizeof(struct dccp_so_feat))539539+ err = -EINVAL;540540+ else541541+ err = dccp_setsockopt_change(sk, DCCPO_CHANGE_L,542542+ (struct dccp_so_feat __user *)543543+ optval);544544+ break;545545+ case DCCP_SOCKOPT_CHANGE_R:546546+ if (optlen != sizeof(struct dccp_so_feat))547547+ err = -EINVAL;548548+ else549549+ err = dccp_setsockopt_change(sk, DCCPO_CHANGE_R,550550+ (struct dccp_so_feat __user *)551551+ optval);552552+ break;524553 case DCCP_SOCKOPT_SERVER_TIMEWAIT:525554 if (dp->dccps_role != DCCP_ROLE_SERVER)526555 err = -EOPNOTSUPP;527556 else528557 dp->dccps_server_timewait = (val != 0);529558 break;530530- case DCCP_SOCKOPT_SEND_CSCOV:531531- err = dccp_setsockopt_cscov(sk, val, false);532532- break;533533- case DCCP_SOCKOPT_RECV_CSCOV:534534- err = dccp_setsockopt_cscov(sk, val, true);535535- break;536536- case DCCP_SOCKOPT_QPOLICY_ID:537537- if (sk->sk_state != DCCP_CLOSED)538538- err = -EISCONN;539539- else if (val < 0 || val >= DCCPQ_POLICY_MAX)559559+ case DCCP_SOCKOPT_SEND_CSCOV: /* sender side, RFC 4340, sec. 9.2 */560560+ if (val < 0 || val > 15)540561 err = -EINVAL;541562 else542542- dp->dccps_qpolicy = val;563563+ dp->dccps_pcslen = val;543564 break;544544- case DCCP_SOCKOPT_QPOLICY_TXQLEN:545545- if (val < 0)565565+ case DCCP_SOCKOPT_RECV_CSCOV: /* receiver side, RFC 4340 sec. 9.2.1 */566566+ if (val < 0 || val > 15)546567 err = -EINVAL;547547- else548548- dp->dccps_tx_qlen = val;568568+ else {569569+ dp->dccps_pcrlen = val;570570+ /* FIXME: add feature negotiation,571571+ * ChangeL(MinimumChecksumCoverage, val) */572572+ }549573 break;550574 default:551575 err = -ENOPROTOOPT;552576 break;553577 }554554- release_sock(sk);555578579579+ release_sock(sk);556580 return err;557581}558582···648642 case DCCP_SOCKOPT_GET_CUR_MPS:649643 val = dp->dccps_mss_cache;650644 break;651651- case DCCP_SOCKOPT_AVAILABLE_CCIDS:652652- return ccid_getsockopt_builtin_ccids(sk, len, optval, optlen);653653- case DCCP_SOCKOPT_TX_CCID:654654- val = ccid_get_current_tx_ccid(dp);655655- if (val < 0)656656- return -ENOPROTOOPT;657657- break;658658- case DCCP_SOCKOPT_RX_CCID:659659- val = ccid_get_current_rx_ccid(dp);660660- if (val < 0)661661- return -ENOPROTOOPT;662662- break;663645 case DCCP_SOCKOPT_SERVER_TIMEWAIT:664646 val = dp->dccps_server_timewait;665647 break;···656662 break;657663 case DCCP_SOCKOPT_RECV_CSCOV:658664 val = dp->dccps_pcrlen;659659- break;660660- case DCCP_SOCKOPT_QPOLICY_ID:661661- val = dp->dccps_qpolicy;662662- break;663663- case DCCP_SOCKOPT_QPOLICY_TXQLEN:664664- val = dp->dccps_tx_qlen;665665 break;666666 case 128 ... 191:667667 return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname,···699711EXPORT_SYMBOL_GPL(compat_dccp_getsockopt);700712#endif701713702702-static int dccp_msghdr_parse(struct msghdr *msg, struct sk_buff *skb)703703-{704704- struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);705705-706706- /*707707- * Assign an (opaque) qpolicy priority value to skb->priority.708708- *709709- * We are overloading this skb field for use with the qpolicy subystem.710710- * The skb->priority is normally used for the SO_PRIORITY option, which711711- * is initialised from sk_priority. Since the assignment of sk_priority712712- * to skb->priority happens later (on layer 3), we overload this field713713- * for use with queueing priorities as long as the skb is on layer 4.714714- * The default priority value (if nothing is set) is 0.715715- */716716- skb->priority = 0;717717-718718- for (; cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) {719719-720720- if (!CMSG_OK(msg, cmsg))721721- return -EINVAL;722722-723723- if (cmsg->cmsg_level != SOL_DCCP)724724- continue;725725-726726- if (cmsg->cmsg_type <= DCCP_SCM_QPOLICY_MAX &&727727- !dccp_qpolicy_param_ok(skb->sk, cmsg->cmsg_type))728728- return -EINVAL;729729-730730- switch (cmsg->cmsg_type) {731731- case DCCP_SCM_PRIORITY:732732- if (cmsg->cmsg_len != CMSG_LEN(sizeof(__u32)))733733- return -EINVAL;734734- skb->priority = *(__u32 *)CMSG_DATA(cmsg);735735- break;736736- default:737737- return -EINVAL;738738- }739739- }740740- return 0;741741-}742742-743714int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,744715 size_t len)745716{···714767715768 lock_sock(sk);716769717717- if (dccp_qpolicy_full(sk)) {770770+ if (sysctl_dccp_tx_qlen &&771771+ (sk->sk_write_queue.qlen >= sysctl_dccp_tx_qlen)) {718772 rc = -EAGAIN;719773 goto out_release;720774 }···743795 if (rc != 0)744796 goto out_discard;745797746746- rc = dccp_msghdr_parse(msg, skb);747747- if (rc != 0)748748- goto out_discard;749749-750750- dccp_qpolicy_push(sk, skb);751751- dccp_write_xmit(sk);798798+ skb_queue_tail(&sk->sk_write_queue, skb);799799+ dccp_write_xmit(sk,0);752800out_release:753801 release_sock(sk);754802 return rc ? : len;···9671023 /* Check zero linger _after_ checking for unread data. */9681024 sk->sk_prot->disconnect(sk, 0);9691025 } else if (sk->sk_state != DCCP_CLOSED) {970970- /*971971- * Normal connection termination. May need to wait if there are972972- * still packets in the TX queue that are delayed by the CCID.973973- */974974- dccp_flush_write_queue(sk, &timeout);9751026 dccp_terminate_connection(sk);9761027 }977977-978978- /*979979- * Flush write queue. This may be necessary in several cases:980980- * - we have been closed by the peer but still have application data;981981- * - abortive termination (unread data or zero linger time),982982- * - normal termination but queue could not be flushed within time limit983983- */984984- __skb_queue_purge(&sk->sk_write_queue);98510289861029 sk_stream_wait_close(sk, timeout);9871030
-137
net/dccp/qpolicy.c
···11-/*22- * net/dccp/qpolicy.c33- *44- * Policy-based packet dequeueing interface for DCCP.55- *66- * Copyright (c) 2008 Tomasz Grobelny <tomasz@grobelny.oswiecenia.net>77- *88- * This program is free software; you can redistribute it and/or99- * modify it under the terms of the GNU General Public License v21010- * as published by the Free Software Foundation.1111- */1212-#include "dccp.h"1313-1414-/*1515- * Simple Dequeueing Policy:1616- * If tx_qlen is different from 0, enqueue up to tx_qlen elements.1717- */1818-static void qpolicy_simple_push(struct sock *sk, struct sk_buff *skb)1919-{2020- skb_queue_tail(&sk->sk_write_queue, skb);2121-}2222-2323-static bool qpolicy_simple_full(struct sock *sk)2424-{2525- return dccp_sk(sk)->dccps_tx_qlen &&2626- sk->sk_write_queue.qlen >= dccp_sk(sk)->dccps_tx_qlen;2727-}2828-2929-static struct sk_buff *qpolicy_simple_top(struct sock *sk)3030-{3131- return skb_peek(&sk->sk_write_queue);3232-}3333-3434-/*3535- * Priority-based Dequeueing Policy:3636- * If tx_qlen is different from 0 and the queue has reached its upper bound3737- * of tx_qlen elements, replace older packets lowest-priority-first.3838- */3939-static struct sk_buff *qpolicy_prio_best_skb(struct sock *sk)4040-{4141- struct sk_buff *skb, *best = NULL;4242-4343- skb_queue_walk(&sk->sk_write_queue, skb)4444- if (best == NULL || skb->priority > best->priority)4545- best = skb;4646- return best;4747-}4848-4949-static struct sk_buff *qpolicy_prio_worst_skb(struct sock *sk)5050-{5151- struct sk_buff *skb, *worst = NULL;5252-5353- skb_queue_walk(&sk->sk_write_queue, skb)5454- if (worst == NULL || skb->priority < worst->priority)5555- worst = skb;5656- return worst;5757-}5858-5959-static bool qpolicy_prio_full(struct sock *sk)6060-{6161- if (qpolicy_simple_full(sk))6262- dccp_qpolicy_drop(sk, qpolicy_prio_worst_skb(sk));6363- return false;6464-}6565-6666-/**6767- * struct dccp_qpolicy_operations - TX Packet Dequeueing Interface6868- * @push: add a new @skb to the write queue6969- * @full: indicates that no more packets will be admitted7070- * @top: peeks at whatever the queueing policy defines as its `top'7171- */7272-static struct dccp_qpolicy_operations {7373- void (*push) (struct sock *sk, struct sk_buff *skb);7474- bool (*full) (struct sock *sk);7575- struct sk_buff* (*top) (struct sock *sk);7676- __be32 params;7777-7878-} qpol_table[DCCPQ_POLICY_MAX] = {7979- [DCCPQ_POLICY_SIMPLE] = {8080- .push = qpolicy_simple_push,8181- .full = qpolicy_simple_full,8282- .top = qpolicy_simple_top,8383- .params = 0,8484- },8585- [DCCPQ_POLICY_PRIO] = {8686- .push = qpolicy_simple_push,8787- .full = qpolicy_prio_full,8888- .top = qpolicy_prio_best_skb,8989- .params = DCCP_SCM_PRIORITY,9090- },9191-};9292-9393-/*9494- * Externally visible interface9595- */9696-void dccp_qpolicy_push(struct sock *sk, struct sk_buff *skb)9797-{9898- qpol_table[dccp_sk(sk)->dccps_qpolicy].push(sk, skb);9999-}100100-101101-bool dccp_qpolicy_full(struct sock *sk)102102-{103103- return qpol_table[dccp_sk(sk)->dccps_qpolicy].full(sk);104104-}105105-106106-void dccp_qpolicy_drop(struct sock *sk, struct sk_buff *skb)107107-{108108- if (skb != NULL) {109109- skb_unlink(skb, &sk->sk_write_queue);110110- kfree_skb(skb);111111- }112112-}113113-114114-struct sk_buff *dccp_qpolicy_top(struct sock *sk)115115-{116116- return qpol_table[dccp_sk(sk)->dccps_qpolicy].top(sk);117117-}118118-119119-struct sk_buff *dccp_qpolicy_pop(struct sock *sk)120120-{121121- struct sk_buff *skb = dccp_qpolicy_top(sk);122122-123123- /* Clear any skb fields that we used internally */124124- skb->priority = 0;125125-126126- if (skb)127127- skb_unlink(skb, &sk->sk_write_queue);128128- return skb;129129-}130130-131131-bool dccp_qpolicy_param_ok(struct sock *sk, __be32 param)132132-{133133- /* check if exactly one bit is set */134134- if (!param || (param & (param - 1)))135135- return false;136136- return (qpol_table[dccp_sk(sk)->dccps_qpolicy].params & param) == param;137137-}
···8787{8888 struct inet_connection_sock *icsk = inet_csk(sk);89899090+ /* retransmit timer is used for feature negotiation throughout9191+ * connection. In this case, no packet is re-transmitted, but rather an9292+ * ack is generated and pending changes are placed into its options.9393+ */9494+ if (sk->sk_send_head == NULL) {9595+ dccp_pr_debug("feat negotiation retransmit timeout %p\n", sk);9696+ if (sk->sk_state == DCCP_OPEN)9797+ dccp_send_ack(sk);9898+ goto backoff;9999+ }100100+90101 /*91102 * More than than 4MSL (8 minutes) has passed, a RESET(aborted) was92103 * sent, no need to retransmit, this sock is dead.···126115 return;127116 }128117118118+backoff:129119 icsk->icsk_backoff++;130120131121 icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX);···249237 sock_put(sk);250238}251239252252-/**253253- * dccp_write_xmitlet - Workhorse for CCID packet dequeueing interface254254- * See the comments above %ccid_dequeueing_decision for supported modes.255255- */256256-static void dccp_write_xmitlet(unsigned long data)240240+/* Transmit-delay timer: used by the CCIDs to delay actual send time */241241+static void dccp_write_xmit_timer(unsigned long data)257242{258243 struct sock *sk = (struct sock *)data;244244+ struct dccp_sock *dp = dccp_sk(sk);259245260246 bh_lock_sock(sk);261247 if (sock_owned_by_user(sk))262262- sk_reset_timer(sk, &dccp_sk(sk)->dccps_xmit_timer, jiffies + 1);248248+ sk_reset_timer(sk, &dp->dccps_xmit_timer, jiffies+1);263249 else264264- dccp_write_xmit(sk);250250+ dccp_write_xmit(sk, 0);265251 bh_unlock_sock(sk);252252+ sock_put(sk);266253}267254268268-static void dccp_write_xmit_timer(unsigned long data)255255+static void dccp_init_write_xmit_timer(struct sock *sk)269256{270270- dccp_write_xmitlet(data);271271- sock_put((struct sock *)data);257257+ struct dccp_sock *dp = dccp_sk(sk);258258+259259+ setup_timer(&dp->dccps_xmit_timer, dccp_write_xmit_timer,260260+ (unsigned long)sk);272261}273262274263void dccp_init_xmit_timers(struct sock *sk)275264{276276- struct dccp_sock *dp = dccp_sk(sk);277277-278278- tasklet_init(&dp->dccps_xmitlet, dccp_write_xmitlet, (unsigned long)sk);279279- setup_timer(&dp->dccps_xmit_timer, dccp_write_xmit_timer,280280- (unsigned long)sk);265265+ dccp_init_write_xmit_timer(sk);281266 inet_csk_init_xmit_timers(sk, &dccp_write_timer, &dccp_delack_timer,282267 &dccp_keepalive_timer);283268}···290281{291282 s64 delta = ktime_us_delta(ktime_get_real(), dccp_timestamp_seed);292283293293- return div_u64(delta, DCCP_TIME_RESOLUTION);284284+ do_div(delta, 10);285285+ return delta;294286}295287EXPORT_SYMBOL_GPL(dccp_timestamp);296288
+15-2
net/ipv4/tcp_input.c
···811811 }812812}813813814814+/* Numbers are taken from RFC3390.815815+ *816816+ * John Heffner states:817817+ *818818+ * The RFC specifies a window of no more than 4380 bytes819819+ * unless 2*MSS > 4380. Reading the pseudocode in the RFC820820+ * is a bit misleading because they use a clamp at 4380 bytes821821+ * rather than use a multiplier in the relevant range.822822+ */814823__u32 tcp_init_cwnd(struct tcp_sock *tp, struct dst_entry *dst)815824{816825 __u32 cwnd = (dst ? dst_metric(dst, RTAX_INITCWND) : 0);817826818818- if (!cwnd)819819- cwnd = rfc3390_bytes_to_packets(tp->mss_cache);827827+ if (!cwnd) {828828+ if (tp->mss_cache > 1460)829829+ cwnd = 2;830830+ else831831+ cwnd = (tp->mss_cache > 1095) ? 3 : 4;832832+ }820833 return min_t(__u32, cwnd, tp->snd_cwnd_clamp);821834}822835