Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netbt Handle some ``Quality of Service'' configuration o...



details:   https://anonhg.NetBSD.org/src/rev/e40f386af259
branches:  trunk
changeset: 771700:e40f386af259
user:      plunky <plunky%NetBSD.org@localhost>
date:      Tue Nov 29 13:16:27 2011 +0000

description:
Handle some ``Quality of Service'' configuration options, to
help devices requesting them blindly succeed in connecting.

should fix a problem analysed by Nat Sloss on current-users

diffstat:

 sys/netbt/l2cap_signal.c |  112 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 110 insertions(+), 2 deletions(-)

diffs (151 lines):

diff -r 4faed2f42700 -r e40f386af259 sys/netbt/l2cap_signal.c
--- a/sys/netbt/l2cap_signal.c  Tue Nov 29 13:16:26 2011 +0000
+++ b/sys/netbt/l2cap_signal.c  Tue Nov 29 13:16:27 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: l2cap_signal.c,v 1.14 2011/07/27 10:25:09 plunky Exp $ */
+/*     $NetBSD: l2cap_signal.c,v 1.15 2011/11/29 13:16:27 plunky Exp $ */
 
 /*-
  * Copyright (c) 2005 Iain Hibbert.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: l2cap_signal.c,v 1.14 2011/07/27 10:25:09 plunky Exp $");
+__KERNEL_RCSID(0, "$NetBSD: l2cap_signal.c,v 1.15 2011/11/29 13:16:27 plunky Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -59,6 +59,8 @@
 static void l2cap_recv_info_req(struct mbuf *, struct hci_link *);
 static int l2cap_send_signal(struct hci_link *, uint8_t, uint8_t, uint16_t, void *);
 static int l2cap_send_command_rej(struct hci_link *, uint8_t, uint16_t, ...);
+static void l2cap_qos_btoh(l2cap_qos_t *, void *);
+static void l2cap_qos_htob(void *, l2cap_qos_t *);
 
 /*
  * process incoming signal packets (CID 0x0001). Can contain multiple
@@ -518,6 +520,57 @@
                        break;
 
                case L2CAP_OPT_QOS:
+                       if (rp.result == L2CAP_UNKNOWN_OPTION)
+                               break;
+
+                       if (opt.length != L2CAP_OPT_QOS_SIZE)
+                               goto reject;
+
+                       /*
+                        * We don't actually support QoS, but an incoming
+                        * config request is merely advising us of their
+                        * outgoing traffic flow, so be nice.
+                        */
+                       m_copydata(m, 0, L2CAP_OPT_QOS_SIZE, &val);
+                       switch (val.qos.service_type) {
+                       case L2CAP_QOS_NO_TRAFFIC:
+                               /*
+                                * "No traffic" means they don't plan to send
+                                * any data and the fields should be ignored.
+                                */
+                               chan->lc_iqos = l2cap_default_qos;
+                               chan->lc_iqos.service_type = L2CAP_QOS_NO_TRAFFIC;
+                               break;
+
+                       case L2CAP_QOS_BEST_EFFORT:
+                               /*
+                                * "Best effort" is the default, and we may
+                                * choose to ignore the fields, try to satisfy
+                                * the parameters while giving no response, or
+                                * respond with the settings we will try to
+                                * meet.
+                                */
+                               l2cap_qos_btoh(&chan->lc_iqos, &val.qos);
+                               break;
+
+                       case L2CAP_QOS_GUARANTEED:
+                       default:
+                               /*
+                                * Anything else we don't support, so make a
+                                * counter-offer with the current settings.
+                                */
+                               if (len + sizeof(opt) + L2CAP_OPT_QOS_SIZE > sizeof(buf))
+                                       goto reject;
+
+                               rp.result = L2CAP_UNACCEPTABLE_PARAMS;
+                               memcpy(buf + len, &opt, sizeof(opt));
+                               len += sizeof(opt);
+                               l2cap_qos_htob(buf + len, &chan->lc_iqos);
+                               len += L2CAP_OPT_QOS_SIZE;
+                               break;
+                       }
+                       break;
+
                default:
                        /* ignore hints */
                        if (opt.type & L2CAP_OPT_HINT_BIT)
@@ -688,6 +741,27 @@
                                goto discon;
 
                        case L2CAP_OPT_QOS:
+                               if (opt.length != L2CAP_OPT_QOS_SIZE)
+                                       goto discon;
+
+                               /*
+                                * This may happen even if we haven't sent a
+                                * QoS request, where they need to state their
+                                * preferred incoming traffic flow.
+                                * We don't support anything, but copy in the
+                                * parameters if no action is good enough.
+                                */
+                               m_copydata(m, 0, L2CAP_OPT_QOS_SIZE, &val);
+                               switch (val.qos.service_type) {
+                               case L2CAP_QOS_NO_TRAFFIC:
+                               case L2CAP_QOS_BEST_EFFORT:
+                                       l2cap_qos_btoh(&chan->lc_oqos, &val.qos);
+                                       break;
+
+                               case L2CAP_QOS_GUARANTEED:
+                               default:
+                                       goto discon;
+                               }
                                break;
 
                        default:
@@ -1130,3 +1204,37 @@
 
        return l2cap_send_signal(link, L2CAP_CONNECT_RSP, ident, sizeof(cp), &cp);
 }
+
+/*
+ * copy in QoS buffer to host
+ */
+static void
+l2cap_qos_btoh(l2cap_qos_t *qos, void *buf)
+{
+       l2cap_qos_t *src = buf;
+
+       qos->flags = src->flags;
+       qos->service_type = src->service_type;
+       qos->token_rate = le32toh(src->token_rate);
+       qos->token_bucket_size = le32toh(src->token_bucket_size);
+       qos->peak_bandwidth = le32toh(src->peak_bandwidth);
+       qos->latency = le32toh(src->latency);
+       qos->delay_variation = le32toh(src->delay_variation);
+}
+
+/*
+ * copy out host QoS to buffer
+ */
+static void
+l2cap_qos_htob(void *buf, l2cap_qos_t *qos)
+{
+       l2cap_qos_t *dst = buf;
+
+       dst->flags = qos->flags;
+       dst->service_type = qos->service_type;
+       dst->token_rate = htole32(qos->token_rate);
+       dst->token_bucket_size = htole32(qos->token_bucket_size);
+       dst->peak_bandwidth = htole32(qos->peak_bandwidth);
+       dst->latency = htole32(qos->latency);
+       dst->delay_variation = htole32(qos->delay_variation);
+}



Home | Main Index | Thread Index | Old Index