diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-09-04 01:30:19 -0400 |
---|---|---|
committer | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-09-04 01:45:29 -0400 |
commit | c664d4f4e2963ee355b1b0e77461eb844d1b288d (patch) | |
tree | b799cbd6bc0b3764a527b1b7b71012215b67e62f /net/dccp | |
parent | f8a644c07e6f38b2c3cbaf99990e867d670d207b (diff) |
dccp: Preference list reconciliation
This provides two functions to
* reconcile preference lists (with appropriate return codes) and
* reorder the preference list if successful reconciliation changed the
preferred value.
The patch also removes the old code for processing SP/NN Change options, since
new code to process these is mostly there already; related references have been
commented out.
The code for processing Change options follows in the next patch.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Diffstat (limited to 'net/dccp')
-rw-r--r-- | net/dccp/feat.c | 77 |
1 files changed, 75 insertions, 2 deletions
diff --git a/net/dccp/feat.c b/net/dccp/feat.c index da686464462d..d53077bd40bf 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c | |||
@@ -718,6 +718,76 @@ static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val) | |||
718 | return 0; | 718 | return 0; |
719 | } | 719 | } |
720 | 720 | ||
721 | /* Select the first entry in @servlist that also occurs in @clilist (6.3.1) */ | ||
722 | static int dccp_feat_preflist_match(u8 *servlist, u8 slen, u8 *clilist, u8 clen) | ||
723 | { | ||
724 | u8 c, s; | ||
725 | |||
726 | for (s = 0; s < slen; s++) | ||
727 | for (c = 0; c < clen; c++) | ||
728 | if (servlist[s] == clilist[c]) | ||
729 | return servlist[s]; | ||
730 | return -1; | ||
731 | } | ||
732 | |||
733 | /** | ||
734 | * dccp_feat_prefer - Move preferred entry to the start of array | ||
735 | * Reorder the @array_len elements in @array so that @preferred_value comes | ||
736 | * first. Returns >0 to indicate that @preferred_value does occur in @array. | ||
737 | */ | ||
738 | static u8 dccp_feat_prefer(u8 preferred_value, u8 *array, u8 array_len) | ||
739 | { | ||
740 | u8 i, does_occur = 0; | ||
741 | |||
742 | if (array != NULL) { | ||
743 | for (i = 0; i < array_len; i++) | ||
744 | if (array[i] == preferred_value) { | ||
745 | array[i] = array[0]; | ||
746 | does_occur++; | ||
747 | } | ||
748 | if (does_occur) | ||
749 | array[0] = preferred_value; | ||
750 | } | ||
751 | return does_occur; | ||
752 | } | ||
753 | |||
754 | /** | ||
755 | * dccp_feat_reconcile - Reconcile SP preference lists | ||
756 | * @fval: SP list to reconcile into | ||
757 | * @arr: received SP preference list | ||
758 | * @len: length of @arr in bytes | ||
759 | * @is_server: whether this side is the server (and @fv is the server's list) | ||
760 | * @reorder: whether to reorder the list in @fv after reconciling with @arr | ||
761 | * When successful, > 0 is returned and the reconciled list is in @fval. | ||
762 | * A value of 0 means that negotiation failed (no shared entry). | ||
763 | */ | ||
764 | static int dccp_feat_reconcile(dccp_feat_val *fv, u8 *arr, u8 len, | ||
765 | bool is_server, bool reorder) | ||
766 | { | ||
767 | int rc; | ||
768 | |||
769 | if (!fv->sp.vec || !arr) { | ||
770 | DCCP_CRIT("NULL feature value or array"); | ||
771 | return 0; | ||
772 | } | ||
773 | |||
774 | if (is_server) | ||
775 | rc = dccp_feat_preflist_match(fv->sp.vec, fv->sp.len, arr, len); | ||
776 | else | ||
777 | rc = dccp_feat_preflist_match(arr, len, fv->sp.vec, fv->sp.len); | ||
778 | |||
779 | if (!reorder) | ||
780 | return rc; | ||
781 | if (rc < 0) | ||
782 | return 0; | ||
783 | |||
784 | /* | ||
785 | * Reorder list: used for activating features and in dccp_insert_fn_opt. | ||
786 | */ | ||
787 | return dccp_feat_prefer(rc, fv->sp.vec, fv->sp.len); | ||
788 | } | ||
789 | |||
790 | #ifdef __this_is_the_old_framework_and_will_be_removed_later_in_a_subsequent_patch | ||
721 | static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt, | 791 | static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt, |
722 | u8 *rpref, u8 rlen) | 792 | u8 *rpref, u8 rlen) |
723 | { | 793 | { |
@@ -913,6 +983,7 @@ static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) | |||
913 | 983 | ||
914 | return 0; | 984 | return 0; |
915 | } | 985 | } |
986 | #endif /* (later) */ | ||
916 | 987 | ||
917 | static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk, | 988 | static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk, |
918 | u8 type, u8 feature) | 989 | u8 type, u8 feature) |
@@ -988,12 +1059,14 @@ int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) | |||
988 | switch (feature) { | 1059 | switch (feature) { |
989 | /* deal with SP features */ | 1060 | /* deal with SP features */ |
990 | case DCCPF_CCID: | 1061 | case DCCPF_CCID: |
991 | rc = dccp_feat_sp(sk, type, feature, val, len); | 1062 | /* XXX Obsoleted by next patch |
1063 | rc = dccp_feat_sp(sk, type, feature, val, len); */ | ||
992 | break; | 1064 | break; |
993 | 1065 | ||
994 | /* deal with NN features */ | 1066 | /* deal with NN features */ |
995 | case DCCPF_ACK_RATIO: | 1067 | case DCCPF_ACK_RATIO: |
996 | rc = dccp_feat_nn(sk, type, feature, val, len); | 1068 | /* XXX Obsoleted by next patch |
1069 | rc = dccp_feat_nn(sk, type, feature, val, len); */ | ||
997 | break; | 1070 | break; |
998 | 1071 | ||
999 | /* XXX implement other features */ | 1072 | /* XXX implement other features */ |