Commit 98e684bd authored by David S. Miller's avatar David S. Miller
parents e254c274 536bb20b
...@@ -165,8 +165,10 @@ enum { ...@@ -165,8 +165,10 @@ enum {
DCCPO_TIMESTAMP_ECHO = 42, DCCPO_TIMESTAMP_ECHO = 42,
DCCPO_ELAPSED_TIME = 43, DCCPO_ELAPSED_TIME = 43,
DCCPO_MAX = 45, DCCPO_MAX = 45,
DCCPO_MIN_CCID_SPECIFIC = 128, DCCPO_MIN_RX_CCID_SPECIFIC = 128, /* from sender to receiver */
DCCPO_MAX_CCID_SPECIFIC = 255, DCCPO_MAX_RX_CCID_SPECIFIC = 191,
DCCPO_MIN_TX_CCID_SPECIFIC = 192, /* from receiver to sender */
DCCPO_MAX_TX_CCID_SPECIFIC = 255,
}; };
/* maximum size of a single TLV-encoded DCCP option (sans type/len bytes) */ /* maximum size of a single TLV-encoded DCCP option (sans type/len bytes) */
#define DCCP_SINGLE_OPT_MAXLEN 253 #define DCCP_SINGLE_OPT_MAXLEN 253
......
...@@ -62,18 +62,14 @@ struct ccid_operations { ...@@ -62,18 +62,14 @@ struct ccid_operations {
void (*ccid_hc_tx_exit)(struct sock *sk); void (*ccid_hc_tx_exit)(struct sock *sk);
void (*ccid_hc_rx_packet_recv)(struct sock *sk, void (*ccid_hc_rx_packet_recv)(struct sock *sk,
struct sk_buff *skb); struct sk_buff *skb);
int (*ccid_hc_rx_parse_options)(struct sock *sk, int (*ccid_hc_rx_parse_options)(struct sock *sk, u8 pkt,
unsigned char option, u8 opt, u8 *val, u8 len);
unsigned char len, u16 idx,
unsigned char* value);
int (*ccid_hc_rx_insert_options)(struct sock *sk, int (*ccid_hc_rx_insert_options)(struct sock *sk,
struct sk_buff *skb); struct sk_buff *skb);
void (*ccid_hc_tx_packet_recv)(struct sock *sk, void (*ccid_hc_tx_packet_recv)(struct sock *sk,
struct sk_buff *skb); struct sk_buff *skb);
int (*ccid_hc_tx_parse_options)(struct sock *sk, int (*ccid_hc_tx_parse_options)(struct sock *sk, u8 pkt,
unsigned char option, u8 opt, u8 *val, u8 len);
unsigned char len, u16 idx,
unsigned char* value);
int (*ccid_hc_tx_send_packet)(struct sock *sk, int (*ccid_hc_tx_send_packet)(struct sock *sk,
struct sk_buff *skb); struct sk_buff *skb);
void (*ccid_hc_tx_packet_sent)(struct sock *sk, void (*ccid_hc_tx_packet_sent)(struct sock *sk,
...@@ -168,27 +164,31 @@ static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk, ...@@ -168,27 +164,31 @@ static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb); ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
} }
/**
* ccid_hc_tx_parse_options - Parse CCID-specific options sent by the receiver
* @pkt: type of packet that @opt appears on (RFC 4340, 5.1)
* @opt: the CCID-specific option type (RFC 4340, 5.8 and 10.3)
* @val: value of @opt
* @len: length of @val in bytes
*/
static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
unsigned char option, u8 pkt, u8 opt, u8 *val, u8 len)
unsigned char len, u16 idx,
unsigned char* value)
{ {
int rc = 0; if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL)
if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL) return 0;
rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx, return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
value);
return rc;
} }
/**
* ccid_hc_rx_parse_options - Parse CCID-specific options sent by the sender
* Arguments are analogous to ccid_hc_tx_parse_options()
*/
static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk, static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
unsigned char option, u8 pkt, u8 opt, u8 *val, u8 len)
unsigned char len, u16 idx,
unsigned char* value)
{ {
int rc = 0; if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL)
if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL) return 0;
rc = ccid->ccid_ops->ccid_hc_rx_parse_options(sk, option, len, idx, value); return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
return rc;
} }
static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk, static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
......
...@@ -54,7 +54,6 @@ static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state) ...@@ -54,7 +54,6 @@ static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)
[TFRC_SSTATE_NO_SENT] = "NO_SENT", [TFRC_SSTATE_NO_SENT] = "NO_SENT",
[TFRC_SSTATE_NO_FBACK] = "NO_FBACK", [TFRC_SSTATE_NO_FBACK] = "NO_FBACK",
[TFRC_SSTATE_FBACK] = "FBACK", [TFRC_SSTATE_FBACK] = "FBACK",
[TFRC_SSTATE_TERM] = "TERM",
}; };
return ccid3_state_names[state]; return ccid3_state_names[state];
...@@ -208,10 +207,13 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) ...@@ -208,10 +207,13 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
ccid3_pr_debug("%s(%p, state=%s) - entry\n", dccp_role(sk), sk, ccid3_pr_debug("%s(%p, state=%s) - entry\n", dccp_role(sk), sk,
ccid3_tx_state_name(hc->tx_state)); ccid3_tx_state_name(hc->tx_state));
/* Ignore and do not restart after leaving the established state */
if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN))
goto out;
/* Reset feedback state to "no feedback received" */
if (hc->tx_state == TFRC_SSTATE_FBACK) if (hc->tx_state == TFRC_SSTATE_FBACK)
ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
else if (hc->tx_state != TFRC_SSTATE_NO_FBACK)
goto out;
/* /*
* Determine new allowed sending rate X as per draft rfc3448bis-00, 4.4 * Determine new allowed sending rate X as per draft rfc3448bis-00, 4.4
...@@ -287,8 +289,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) ...@@ -287,8 +289,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
if (unlikely(skb->len == 0)) if (unlikely(skb->len == 0))
return -EBADMSG; return -EBADMSG;
switch (hc->tx_state) { if (hc->tx_state == TFRC_SSTATE_NO_SENT) {
case TFRC_SSTATE_NO_SENT:
sk_reset_timer(sk, &hc->tx_no_feedback_timer, (jiffies + sk_reset_timer(sk, &hc->tx_no_feedback_timer, (jiffies +
usecs_to_jiffies(TFRC_INITIAL_TIMEOUT))); usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)));
hc->tx_last_win_count = 0; hc->tx_last_win_count = 0;
...@@ -323,9 +324,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) ...@@ -323,9 +324,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
ccid3_update_send_interval(hc); ccid3_update_send_interval(hc);
ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
break;
case TFRC_SSTATE_NO_FBACK: } else {
case TFRC_SSTATE_FBACK:
delay = ktime_us_delta(hc->tx_t_nom, now); delay = ktime_us_delta(hc->tx_t_nom, now);
ccid3_pr_debug("delay=%ld\n", (long)delay); ccid3_pr_debug("delay=%ld\n", (long)delay);
/* /*
...@@ -340,10 +340,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) ...@@ -340,10 +340,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
return (u32)delay / USEC_PER_MSEC; return (u32)delay / USEC_PER_MSEC;
ccid3_hc_tx_update_win_count(hc, now); ccid3_hc_tx_update_win_count(hc, now);
break;
case TFRC_SSTATE_TERM:
DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
return -EINVAL;
} }
/* prepare to send now (add options etc.) */ /* prepare to send now (add options etc.) */
...@@ -369,21 +365,15 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, ...@@ -369,21 +365,15 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more,
static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
{ {
struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
struct ccid3_options_received *opt_recv = &hc->tx_options_received;
struct tfrc_tx_hist_entry *acked; struct tfrc_tx_hist_entry *acked;
ktime_t now; ktime_t now;
unsigned long t_nfb; unsigned long t_nfb;
u32 pinv, r_sample; u32 r_sample;
/* we are only interested in ACKs */ /* we are only interested in ACKs */
if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK || if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK ||
DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK)) DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK))
return; return;
/* ... and only in the established state */
if (hc->tx_state != TFRC_SSTATE_FBACK &&
hc->tx_state != TFRC_SSTATE_NO_FBACK)
return;
/* /*
* Locate the acknowledged packet in the TX history. * Locate the acknowledged packet in the TX history.
* *
...@@ -403,17 +393,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) ...@@ -403,17 +393,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
r_sample = dccp_sample_rtt(sk, ktime_us_delta(now, acked->stamp)); r_sample = dccp_sample_rtt(sk, ktime_us_delta(now, acked->stamp));
hc->tx_rtt = tfrc_ewma(hc->tx_rtt, r_sample, 9); hc->tx_rtt = tfrc_ewma(hc->tx_rtt, r_sample, 9);
/* Update receive rate in units of 64 * bytes/second */
hc->tx_x_recv = opt_recv->ccid3or_receive_rate;
hc->tx_x_recv <<= 6;
/* Update loss event rate (which is scaled by 1e6) */
pinv = opt_recv->ccid3or_loss_event_rate;
if (pinv == ~0U || pinv == 0) /* see RFC 4342, 8.5 */
hc->tx_p = 0;
else /* can not exceed 100% */
hc->tx_p = scaled_div(1, pinv);
/* /*
* Update allowed sending rate X as per draft rfc3448bis-00, 4.2/3 * Update allowed sending rate X as per draft rfc3448bis-00, 4.2/3
*/ */
...@@ -481,30 +460,36 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) ...@@ -481,30 +460,36 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
jiffies + usecs_to_jiffies(t_nfb)); jiffies + usecs_to_jiffies(t_nfb));
} }
static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, static int ccid3_hc_tx_parse_options(struct sock *sk, u8 packet_type,
unsigned char len, u16 idx, u8 option, u8 *optval, u8 optlen)
unsigned char *value)
{ {
struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
struct ccid3_options_received *opt_recv = &hc->tx_options_received;
__be32 opt_val; __be32 opt_val;
switch (option) { switch (option) {
case TFRC_OPT_RECEIVE_RATE: case TFRC_OPT_RECEIVE_RATE:
case TFRC_OPT_LOSS_EVENT_RATE: case TFRC_OPT_LOSS_EVENT_RATE:
if (unlikely(len != 4)) { /* Must be ignored on Data packets, cf. RFC 4342 8.3 and 8.5 */
if (packet_type == DCCP_PKT_DATA)
break;
if (unlikely(optlen != 4)) {
DCCP_WARN("%s(%p), invalid len %d for %u\n", DCCP_WARN("%s(%p), invalid len %d for %u\n",
dccp_role(sk), sk, len, option); dccp_role(sk), sk, optlen, option);
return -EINVAL; return -EINVAL;
} }
opt_val = ntohl(get_unaligned((__be32 *)value)); opt_val = ntohl(get_unaligned((__be32 *)optval));
if (option == TFRC_OPT_RECEIVE_RATE) { if (option == TFRC_OPT_RECEIVE_RATE) {
opt_recv->ccid3or_receive_rate = opt_val; /* Receive Rate is kept in units of 64 bytes/second */
hc->tx_x_recv = opt_val;
hc->tx_x_recv <<= 6;
ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n", ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
dccp_role(sk), sk, opt_val); dccp_role(sk), sk, opt_val);
} else { } else {
opt_recv->ccid3or_loss_event_rate = opt_val; /* Update the fixpoint Loss Event Rate fraction */
hc->tx_p = tfrc_invert_loss_event_rate(opt_val);
ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n", ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
dccp_role(sk), sk, opt_val); dccp_role(sk), sk, opt_val);
} }
...@@ -527,9 +512,7 @@ static void ccid3_hc_tx_exit(struct sock *sk) ...@@ -527,9 +512,7 @@ static void ccid3_hc_tx_exit(struct sock *sk)
{ {
struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM);
sk_stop_timer(sk, &hc->tx_no_feedback_timer); sk_stop_timer(sk, &hc->tx_no_feedback_timer);
tfrc_tx_hist_purge(&hc->tx_hist); tfrc_tx_hist_purge(&hc->tx_hist);
} }
...@@ -588,7 +571,6 @@ static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state) ...@@ -588,7 +571,6 @@ static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state)
static const char *const ccid3_rx_state_names[] = { static const char *const ccid3_rx_state_names[] = {
[TFRC_RSTATE_NO_DATA] = "NO_DATA", [TFRC_RSTATE_NO_DATA] = "NO_DATA",
[TFRC_RSTATE_DATA] = "DATA", [TFRC_RSTATE_DATA] = "DATA",
[TFRC_RSTATE_TERM] = "TERM",
}; };
return ccid3_rx_state_names[state]; return ccid3_rx_state_names[state];
...@@ -614,14 +596,9 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk, ...@@ -614,14 +596,9 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk,
{ {
struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk);
struct dccp_sock *dp = dccp_sk(sk); struct dccp_sock *dp = dccp_sk(sk);
ktime_t now; ktime_t now = ktime_get_real();
s64 delta = 0; s64 delta = 0;
if (unlikely(hc->rx_state == TFRC_RSTATE_TERM))
return;
now = ktime_get_real();
switch (fbtype) { switch (fbtype) {
case CCID3_FBACK_INITIAL: case CCID3_FBACK_INITIAL:
hc->rx_x_recv = 0; hc->rx_x_recv = 0;
...@@ -825,8 +802,6 @@ static void ccid3_hc_rx_exit(struct sock *sk) ...@@ -825,8 +802,6 @@ static void ccid3_hc_rx_exit(struct sock *sk)
{ {
struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk);
ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);
tfrc_rx_hist_purge(&hc->rx_hist); tfrc_rx_hist_purge(&hc->rx_hist);
tfrc_lh_cleanup(&hc->rx_li_hist); tfrc_lh_cleanup(&hc->rx_li_hist);
} }
...@@ -851,8 +826,7 @@ static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len, ...@@ -851,8 +826,7 @@ static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len,
return -EINVAL; return -EINVAL;
rx_info.tfrcrx_x_recv = hc->rx_x_recv; rx_info.tfrcrx_x_recv = hc->rx_x_recv;
rx_info.tfrcrx_rtt = hc->rx_rtt; rx_info.tfrcrx_rtt = hc->rx_rtt;
rx_info.tfrcrx_p = hc->rx_pinv == 0 ? ~0U : rx_info.tfrcrx_p = tfrc_invert_loss_event_rate(hc->rx_pinv);
scaled_div(1, hc->rx_pinv);
len = sizeof(rx_info); len = sizeof(rx_info);
val = &rx_info; val = &rx_info;
break; break;
......
...@@ -67,17 +67,11 @@ enum ccid3_options { ...@@ -67,17 +67,11 @@ enum ccid3_options {
TFRC_OPT_RECEIVE_RATE = 194, TFRC_OPT_RECEIVE_RATE = 194,
}; };
struct ccid3_options_received {
u32 ccid3or_loss_event_rate;
u32 ccid3or_receive_rate;
};
/* TFRC sender states */ /* TFRC sender states */
enum ccid3_hc_tx_states { enum ccid3_hc_tx_states {
TFRC_SSTATE_NO_SENT = 1, TFRC_SSTATE_NO_SENT = 1,
TFRC_SSTATE_NO_FBACK, TFRC_SSTATE_NO_FBACK,
TFRC_SSTATE_FBACK, TFRC_SSTATE_FBACK,
TFRC_SSTATE_TERM,
}; };
/** /**
...@@ -98,7 +92,6 @@ enum ccid3_hc_tx_states { ...@@ -98,7 +92,6 @@ enum ccid3_hc_tx_states {
* @tx_t_ld: Time last doubled during slow start * @tx_t_ld: Time last doubled during slow start
* @tx_t_nom: Nominal send time of next packet * @tx_t_nom: Nominal send time of next packet
* @tx_hist: Packet history * @tx_hist: Packet history
* @tx_options_received: Parsed set of retrieved options
*/ */
struct ccid3_hc_tx_sock { struct ccid3_hc_tx_sock {
u64 tx_x; u64 tx_x;
...@@ -116,7 +109,6 @@ struct ccid3_hc_tx_sock { ...@@ -116,7 +109,6 @@ struct ccid3_hc_tx_sock {
ktime_t tx_t_ld; ktime_t tx_t_ld;
ktime_t tx_t_nom; ktime_t tx_t_nom;
struct tfrc_tx_hist_entry *tx_hist; struct tfrc_tx_hist_entry *tx_hist;
struct ccid3_options_received tx_options_received;
}; };
static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
...@@ -130,7 +122,6 @@ static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) ...@@ -130,7 +122,6 @@ static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
enum ccid3_hc_rx_states { enum ccid3_hc_rx_states {
TFRC_RSTATE_NO_DATA = 1, TFRC_RSTATE_NO_DATA = 1,
TFRC_RSTATE_DATA, TFRC_RSTATE_DATA,
TFRC_RSTATE_TERM = 127,
}; };
/** /**
......
...@@ -57,6 +57,7 @@ static inline u32 tfrc_ewma(const u32 avg, const u32 newval, const u8 weight) ...@@ -57,6 +57,7 @@ static inline u32 tfrc_ewma(const u32 avg, const u32 newval, const u8 weight)
extern u32 tfrc_calc_x(u16 s, u32 R, u32 p); extern u32 tfrc_calc_x(u16 s, u32 R, u32 p);
extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue); extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue);
extern u32 tfrc_invert_loss_event_rate(u32 loss_event_rate);
extern int tfrc_tx_packet_history_init(void); extern int tfrc_tx_packet_history_init(void);
extern void tfrc_tx_packet_history_exit(void); extern void tfrc_tx_packet_history_exit(void);
......
...@@ -687,3 +687,17 @@ u32 tfrc_calc_x_reverse_lookup(u32 fvalue) ...@@ -687,3 +687,17 @@ u32 tfrc_calc_x_reverse_lookup(u32 fvalue)
index = tfrc_binsearch(fvalue, 0); index = tfrc_binsearch(fvalue, 0);
return (index + 1) * 1000000 / TFRC_CALC_X_ARRSIZE; return (index + 1) * 1000000 / TFRC_CALC_X_ARRSIZE;
} }
/**
* tfrc_invert_loss_event_rate - Compute p so that 10^6 corresponds to 100%
* When @loss_event_rate is large, there is a chance that p is truncated to 0.
* To avoid re-entering slow-start in that case, we set p = TFRC_SMALLEST_P > 0.
*/
u32 tfrc_invert_loss_event_rate(u32 loss_event_rate)
{
if (loss_event_rate == UINT_MAX) /* see RFC 4342, 8.5 */
return 0;
if (unlikely(loss_event_rate == 0)) /* map 1/0 into 100% */
return 1000000;
return max_t(u32, scaled_div(1, loss_event_rate), TFRC_SMALLEST_P);
}
...@@ -96,18 +96,11 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, ...@@ -96,18 +96,11 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
} }
/* /*
* CCID-Specific Options (from RFC 4340, sec. 10.3):
*
* Option numbers 128 through 191 are for options sent from the
* HC-Sender to the HC-Receiver; option numbers 192 through 255
* are for options sent from the HC-Receiver to the HC-Sender.
*
* CCID-specific options are ignored during connection setup, as * CCID-specific options are ignored during connection setup, as
* negotiation may still be in progress (see RFC 4340, 10.3). * negotiation may still be in progress (see RFC 4340, 10.3).
* The same applies to Ack Vectors, as these depend on the CCID. * The same applies to Ack Vectors, as these depend on the CCID.
*
*/ */
if (dreq != NULL && (opt >= 128 || if (dreq != NULL && (opt >= DCCPO_MIN_RX_CCID_SPECIFIC ||
opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1)) opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1))
goto ignore_option; goto ignore_option;
...@@ -226,23 +219,15 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, ...@@ -226,23 +219,15 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n", dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n",
dccp_role(sk), elapsed_time); dccp_role(sk), elapsed_time);
break; break;
case 128 ... 191: { case DCCPO_MIN_RX_CCID_SPECIFIC ... DCCPO_MAX_RX_CCID_SPECIFIC:
const u16 idx = value - options;
if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk, if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk,
opt, len, idx, pkt_type, opt, value, len))
value) != 0)
goto out_invalid_option; goto out_invalid_option;
}
break; break;
case 192 ... 255: { case DCCPO_MIN_TX_CCID_SPECIFIC ... DCCPO_MAX_TX_CCID_SPECIFIC:
const u16 idx = value - options;
if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk, if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk,
opt, len, idx, pkt_type, opt, value, len))
value) != 0)
goto out_invalid_option; goto out_invalid_option;
}
break; break;
default: default:
DCCP_CRIT("DCCP(%p): option %d(len=%d) not " DCCP_CRIT("DCCP(%p): option %d(len=%d) not "
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment