aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/feat.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-11-05 02:54:04 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-05 02:54:04 -0500
commit61e6473efbd6087e1db3aaa93a5266c5bfd8aa99 (patch)
tree4717cfb41ad603d5def3db557628e5d96a918e63 /net/dccp/feat.c
parent7d43d1a0f2cf535167ec7247f110a1f85cecac43 (diff)
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>
Diffstat (limited to 'net/dccp/feat.c')
-rw-r--r--net/dccp/feat.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 45e36fc7943b..9a37b6ce3aca 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -60,6 +60,79 @@ static const struct {
60}; 60};
61#define DCCP_FEAT_SUPPORTED_MAX ARRAY_SIZE(dccp_feat_table) 61#define DCCP_FEAT_SUPPORTED_MAX ARRAY_SIZE(dccp_feat_table)
62 62
63/**
64 * dccp_feat_index - Hash function to map feature number into array position
65 * Returns consecutive array index or -1 if the feature is not understood.
66 */
67static int dccp_feat_index(u8 feat_num)
68{
69 /* The first 9 entries are occupied by the types from RFC 4340, 6.4 */
70 if (feat_num > DCCPF_RESERVED && feat_num <= DCCPF_DATA_CHECKSUM)
71 return feat_num - 1;
72
73 /*
74 * Other features: add cases for new feature types here after adding
75 * them to the above table.
76 */
77 switch (feat_num) {
78 case DCCPF_SEND_LEV_RATE:
79 return DCCP_FEAT_SUPPORTED_MAX - 1;
80 }
81 return -1;
82}
83
84static u8 dccp_feat_type(u8 feat_num)
85{
86 int idx = dccp_feat_index(feat_num);
87
88 if (idx < 0)
89 return FEAT_UNKNOWN;
90 return dccp_feat_table[idx].reconciliation;
91}
92
93static void dccp_feat_val_destructor(u8 feat_num, dccp_feat_val *val)
94{
95 if (unlikely(val == NULL))
96 return;
97 if (dccp_feat_type(feat_num) == FEAT_SP)
98 kfree(val->sp.vec);
99 memset(val, 0, sizeof(*val));
100}
101
102static void dccp_feat_entry_destructor(struct dccp_feat_entry *entry)
103{
104 if (entry != NULL) {
105 dccp_feat_val_destructor(entry->feat_num, &entry->val);
106 kfree(entry);
107 }
108}
109
110/*
111 * List management functions
112 *
113 * Feature negotiation lists rely on and maintain the following invariants:
114 * - each feat_num in the list is known, i.e. we know its type and default value
115 * - each feat_num/is_local combination is unique (old entries are overwritten)
116 * - SP values are always freshly allocated
117 * - list is sorted in increasing order of feature number (faster lookup)
118 */
119
120static inline void dccp_feat_list_pop(struct dccp_feat_entry *entry)
121{
122 list_del(&entry->node);
123 dccp_feat_entry_destructor(entry);
124}
125
126void dccp_feat_list_purge(struct list_head *fn_list)
127{
128 struct dccp_feat_entry *entry, *next;
129
130 list_for_each_entry_safe(entry, next, fn_list, node)
131 dccp_feat_entry_destructor(entry);
132 INIT_LIST_HEAD(fn_list);
133}
134EXPORT_SYMBOL_GPL(dccp_feat_list_purge);
135
63int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature, 136int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
64 u8 *val, u8 len, gfp_t gfp) 137 u8 *val, u8 len, gfp_t gfp)
65{ 138{