dccp: List management for new feature negotiation
This adds list initial fields and list management functions for the new feature negotiation implementation. Thanks to Arnaldo for suggestions and improvements. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7d43d1a0f2
commit
61e6473efb
|
@ -441,6 +441,8 @@ static inline int dccp_ack_pending(const struct sock *sk)
|
||||||
inet_csk_ack_scheduled(sk);
|
inet_csk_ack_scheduled(sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void dccp_feat_list_purge(struct list_head *fn_list);
|
||||||
|
|
||||||
extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb);
|
extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb);
|
||||||
extern int dccp_insert_options_rsk(struct dccp_request_sock*, struct sk_buff*);
|
extern int dccp_insert_options_rsk(struct dccp_request_sock*, struct sk_buff*);
|
||||||
extern int dccp_insert_option_elapsed_time(struct sock *sk,
|
extern int dccp_insert_option_elapsed_time(struct sock *sk,
|
||||||
|
|
|
@ -60,6 +60,79 @@ static const struct {
|
||||||
};
|
};
|
||||||
#define DCCP_FEAT_SUPPORTED_MAX ARRAY_SIZE(dccp_feat_table)
|
#define DCCP_FEAT_SUPPORTED_MAX ARRAY_SIZE(dccp_feat_table)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dccp_feat_index - Hash function to map feature number into array position
|
||||||
|
* Returns consecutive array index or -1 if the feature is not understood.
|
||||||
|
*/
|
||||||
|
static int dccp_feat_index(u8 feat_num)
|
||||||
|
{
|
||||||
|
/* The first 9 entries are occupied by the types from RFC 4340, 6.4 */
|
||||||
|
if (feat_num > DCCPF_RESERVED && feat_num <= DCCPF_DATA_CHECKSUM)
|
||||||
|
return feat_num - 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Other features: add cases for new feature types here after adding
|
||||||
|
* them to the above table.
|
||||||
|
*/
|
||||||
|
switch (feat_num) {
|
||||||
|
case DCCPF_SEND_LEV_RATE:
|
||||||
|
return DCCP_FEAT_SUPPORTED_MAX - 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 dccp_feat_type(u8 feat_num)
|
||||||
|
{
|
||||||
|
int idx = dccp_feat_index(feat_num);
|
||||||
|
|
||||||
|
if (idx < 0)
|
||||||
|
return FEAT_UNKNOWN;
|
||||||
|
return dccp_feat_table[idx].reconciliation;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dccp_feat_val_destructor(u8 feat_num, dccp_feat_val *val)
|
||||||
|
{
|
||||||
|
if (unlikely(val == NULL))
|
||||||
|
return;
|
||||||
|
if (dccp_feat_type(feat_num) == FEAT_SP)
|
||||||
|
kfree(val->sp.vec);
|
||||||
|
memset(val, 0, sizeof(*val));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dccp_feat_entry_destructor(struct dccp_feat_entry *entry)
|
||||||
|
{
|
||||||
|
if (entry != NULL) {
|
||||||
|
dccp_feat_val_destructor(entry->feat_num, &entry->val);
|
||||||
|
kfree(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List management functions
|
||||||
|
*
|
||||||
|
* Feature negotiation lists rely on and maintain the following invariants:
|
||||||
|
* - each feat_num in the list is known, i.e. we know its type and default value
|
||||||
|
* - each feat_num/is_local combination is unique (old entries are overwritten)
|
||||||
|
* - SP values are always freshly allocated
|
||||||
|
* - list is sorted in increasing order of feature number (faster lookup)
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline void dccp_feat_list_pop(struct dccp_feat_entry *entry)
|
||||||
|
{
|
||||||
|
list_del(&entry->node);
|
||||||
|
dccp_feat_entry_destructor(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dccp_feat_list_purge(struct list_head *fn_list)
|
||||||
|
{
|
||||||
|
struct dccp_feat_entry *entry, *next;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(entry, next, fn_list, node)
|
||||||
|
dccp_feat_entry_destructor(entry);
|
||||||
|
INIT_LIST_HEAD(fn_list);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(dccp_feat_list_purge);
|
||||||
|
|
||||||
int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
|
int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
|
||||||
u8 *val, u8 len, gfp_t gfp)
|
u8 *val, u8 len, gfp_t gfp)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue