diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-12-02 02:31:04 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-02 02:31:04 -0500 |
commit | 75757a7d0c54f8fdd414c74a6005d275032b0115 (patch) | |
tree | 768c07adad4a6f42723acfeada434c045f36a489 /net | |
parent | 8b7b6c75c6387527b195bb69100182288da94f84 (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>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-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 d90caa7198c3..fe6d557328d6 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c | |||
@@ -690,6 +690,76 @@ static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val) | |||
690 | return 0; | 690 | return 0; |
691 | } | 691 | } |
692 | 692 | ||
693 | /* Select the first entry in @servlist that also occurs in @clilist (6.3.1) */ | ||
694 | static int dccp_feat_preflist_match(u8 *servlist, u8 slen, u8 *clilist, u8 clen) | ||
695 | { | ||
696 | u8 c, s; | ||
697 | |||
698 | for (s = 0; s < slen; s++) | ||
699 | for (c = 0; c < clen; c++) | ||
700 | if (servlist[s] == clilist[c]) | ||
701 | return servlist[s]; | ||
702 | return -1; | ||
703 | } | ||
704 | |||
705 | /** | ||
706 | * dccp_feat_prefer - Move preferred entry to the start of array | ||
707 | * Reorder the @array_len elements in @array so that @preferred_value comes | ||
708 | * first. Returns >0 to indicate that @preferred_value does occur in @array. | ||
709 | */ | ||
710 | static u8 dccp_feat_prefer(u8 preferred_value, u8 *array, u8 array_len) | ||
711 | { | ||
712 | u8 i, does_occur = 0; | ||
713 | |||
714 | if (array != NULL) { | ||
715 | for (i = 0; i < array_len; i++) | ||
716 | if (array[i] == preferred_value) { | ||
717 | array[i] = array[0]; | ||
718 | does_occur++; | ||
719 | } | ||
720 | if (does_occur) | ||
721 | array[0] = preferred_value; | ||
722 | } | ||
723 | return does_occur; | ||
724 | } | ||
725 | |||
726 | /** | ||
727 | * dccp_feat_reconcile - Reconcile SP preference lists | ||
728 | * @fval: SP list to reconcile into | ||
729 | * @arr: received SP preference list | ||
730 | * @len: length of @arr in bytes | ||
731 | * @is_server: whether this side is the server (and @fv is the server's list) | ||
732 | * @reorder: whether to reorder the list in @fv after reconciling with @arr | ||
733 | * When successful, > 0 is returned and the reconciled list is in @fval. | ||
734 | * A value of 0 means that negotiation failed (no shared entry). | ||
735 | */ | ||
736 | static int dccp_feat_reconcile(dccp_feat_val *fv, u8 *arr, u8 len, | ||
737 | bool is_server, bool reorder) | ||
738 | { | ||
739 | int rc; | ||
740 | |||
741 | if (!fv->sp.vec || !arr) { | ||
742 | DCCP_CRIT("NULL feature value or array"); | ||
743 | return 0; | ||
744 | } | ||
745 | |||
746 | if (is_server) | ||
747 | rc = dccp_feat_preflist_match(fv->sp.vec, fv->sp.len, arr, len); | ||
748 | else | ||
749 | rc = dccp_feat_preflist_match(arr, len, fv->sp.vec, fv->sp.len); | ||
750 | |||
751 | if (!reorder) | ||
752 | return rc; | ||
753 | if (rc < 0) | ||
754 | return 0; | ||
755 | |||
756 | /* | ||
757 | * Reorder list: used for activating features and in dccp_insert_fn_opt. | ||
758 | */ | ||
759 | return dccp_feat_prefer(rc, fv->sp.vec, fv->sp.len); | ||
760 | } | ||
761 | |||
762 | #ifdef __this_is_the_old_framework_and_will_be_removed_later_in_a_subsequent_patch | ||
693 | static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt, | 763 | static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt, |
694 | u8 *rpref, u8 rlen) | 764 | u8 *rpref, u8 rlen) |
695 | { | 765 | { |
@@ -885,6 +955,7 @@ static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) | |||
885 | 955 | ||
886 | return 0; | 956 | return 0; |
887 | } | 957 | } |
958 | #endif /* (later) */ | ||
888 | 959 | ||
889 | static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk, | 960 | static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk, |
890 | u8 type, u8 feature) | 961 | u8 type, u8 feature) |
@@ -960,12 +1031,14 @@ int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) | |||
960 | switch (feature) { | 1031 | switch (feature) { |
961 | /* deal with SP features */ | 1032 | /* deal with SP features */ |
962 | case DCCPF_CCID: | 1033 | case DCCPF_CCID: |
963 | rc = dccp_feat_sp(sk, type, feature, val, len); | 1034 | /* XXX Obsoleted by next patch |
1035 | rc = dccp_feat_sp(sk, type, feature, val, len); */ | ||
964 | break; | 1036 | break; |
965 | 1037 | ||
966 | /* deal with NN features */ | 1038 | /* deal with NN features */ |
967 | case DCCPF_ACK_RATIO: | 1039 | case DCCPF_ACK_RATIO: |
968 | rc = dccp_feat_nn(sk, type, feature, val, len); | 1040 | /* XXX Obsoleted by next patch |
1041 | rc = dccp_feat_nn(sk, type, feature, val, len); */ | ||
969 | break; | 1042 | break; |
970 | 1043 | ||
971 | /* XXX implement other features */ | 1044 | /* XXX implement other features */ |