Source-Changes-HG archive

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

[src/trunk]: src/sys/net80211 Define for more bits in the Service field of th...



details:   https://anonhg.NetBSD.org/src/rev/cf6db84715d6
branches:  trunk
changeset: 572106:cf6db84715d6
user:      dyoung <dyoung%NetBSD.org@localhost>
date:      Sun Dec 19 08:08:06 2004 +0000

description:
Define for more bits in the Service field of the 802.11 PLCP Header.

For use by the subroutine ieee80211_compute_duration, add struct
ieee80211_duration, and #define a number of microsecond constants
used for the transmit timing of 802.11 packets.

Add the subroutine ieee80211_compute_duration, which computes for
any packet the appropriate 802.11 Duration field, the PLCP Length
field, as well as the Duration and Length fields for an RTS frame.

atw(4), rtw(4), future drivers, and possibly ath(4) will share
ieee80211_compute_duration.

diffstat:

 sys/net80211/ieee80211.h        |   46 +++++++++-
 sys/net80211/ieee80211_output.c |  179 +++++++++++++++++++++++++++++++++++++++-
 sys/net80211/ieee80211_proto.h  |    5 +-
 3 files changed, 224 insertions(+), 6 deletions(-)

diffs (296 lines):

diff -r a747b3159788 -r cf6db84715d6 sys/net80211/ieee80211.h
--- a/sys/net80211/ieee80211.h  Sun Dec 19 06:42:24 2004 +0000
+++ b/sys/net80211/ieee80211.h  Sun Dec 19 08:08:06 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ieee80211.h,v 1.7 2004/07/23 05:33:23 mycroft Exp $    */
+/*     $NetBSD: ieee80211.h,v 1.8 2004/12/19 08:08:06 dyoung Exp $     */
 /*-
  * Copyright (c) 2001 Atsushi Onoe
  * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
@@ -54,6 +54,8 @@
 
 #define IEEE80211_PLCP_SFD      0xF3A0 
 #define IEEE80211_PLCP_SERVICE  0x00
+#define IEEE80211_PLCP_SERVICE_PBCC  0x08      /* PBCC encoded */
+#define IEEE80211_PLCP_SERVICE_LENEXT  0x80    /* length extension bit */
 
 /*
  * generic definitions for IEEE 802.11 frames
@@ -539,11 +541,15 @@
 };
 
 #define        IEEE80211_WEP_KEYLEN            5       /* 40bit */
+#define        IEEE80211_WEP_NKID              4       /* number of key ids */
+
+/* WEP header constants */
 #define        IEEE80211_WEP_IVLEN             3       /* 24bit */
 #define        IEEE80211_WEP_KIDLEN            1       /* 1 octet */
 #define        IEEE80211_WEP_CRCLEN            4       /* CRC-32 */
-#define        IEEE80211_WEP_NKID              4       /* number of key ids */
-
+#define        IEEE80211_WEP_TOTLEN            (IEEE80211_WEP_IVLEN + \
+                                        IEEE80211_WEP_KIDLEN + \
+                                        IEEE80211_WEP_CRCLEN)
 /*
  * 802.11i defines an extended IV for use with non-WEP ciphers.
  * When the EXTIV bit is set in the key id byte an additional
@@ -600,6 +606,40 @@
 #define        IEEE80211_RTS_MIN               1
 #define        IEEE80211_RTS_MAX               IEEE80211_MAX_LEN
 
+/*
+ * 802.11 frame duration definitions.
+ */
+
+struct ieee80211_duration {
+       uint16_t        d_rts_dur;
+       uint16_t        d_data_dur;
+       uint16_t        d_plcp_len;
+       uint8_t         d_plcp_svc;
+};
+
+/* One Time Unit (TU) is 1Kus = 1024 microseconds. */
+#define IEEE80211_DUR_TU               1024
+
+/* IEEE 802.11b durations for DSSS PHY in microseconds */
+#define IEEE80211_DUR_DS_LONG_PREAMBLE 144
+#define IEEE80211_DUR_DS_SHORT_PREAMBLE        72
+#define IEEE80211_DUR_DS_FAST_PLCPHDR  24
+#define IEEE80211_DUR_DS_SLOW_PLCPHDR  48
+#define IEEE80211_DUR_DS_SLOW_ACK      112
+#define IEEE80211_DUR_DS_FAST_ACK      56
+#define IEEE80211_DUR_DS_SLOW_CTS      112
+#define IEEE80211_DUR_DS_FAST_CTS      56
+#define IEEE80211_DUR_DS_SLOT          20
+#define IEEE80211_DUR_DS_SIFS          10
+#define IEEE80211_DUR_DS_PIFS  (IEEE80211_DUR_DS_SIFS + IEEE80211_DUR_DS_SLOT)
+#define IEEE80211_DUR_DS_DIFS  (IEEE80211_DUR_DS_SIFS + \
+                                2 * IEEE80211_DUR_DS_SLOT)
+#define IEEE80211_DUR_DS_EIFS  (IEEE80211_DUR_DS_SIFS + \
+                                IEEE80211_DUR_DS_SLOW_ACK + \
+                                IEEE80211_DUR_DS_LONG_PREAMBLE + \
+                                IEEE80211_DUR_DS_SLOW_PLCPHDR + \
+                                IEEE80211_DUR_DIFS)
+
 enum {
        IEEE80211_AUTH_NONE     = 0,
        IEEE80211_AUTH_OPEN     = 1,            /* open */
diff -r a747b3159788 -r cf6db84715d6 sys/net80211/ieee80211_output.c
--- a/sys/net80211/ieee80211_output.c   Sun Dec 19 06:42:24 2004 +0000
+++ b/sys/net80211/ieee80211_output.c   Sun Dec 19 08:08:06 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ieee80211_output.c,v 1.17 2004/08/10 00:57:22 dyoung Exp $     */
+/*     $NetBSD: ieee80211_output.c,v 1.18 2004/12/19 08:08:06 dyoung Exp $     */
 /*-
  * Copyright (c) 2001 Atsushi Onoe
  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
@@ -35,7 +35,7 @@
 #ifdef __FreeBSD__
 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_output.c,v 1.10 2004/04/02 23:25:39 sam Exp $");
 #else
-__KERNEL_RCSID(0, "$NetBSD: ieee80211_output.c,v 1.17 2004/08/10 00:57:22 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ieee80211_output.c,v 1.18 2004/12/19 08:08:06 dyoung Exp $");
 #endif
 
 #include "opt_inet.h"
@@ -274,6 +274,181 @@
 }
 
 /*
+ * Arguments in:
+ *
+ * paylen:  payload length (no FCS, no WEP header)
+ *
+ * hdrlen:  header length
+ *
+ * rate:    MSDU speed, units 500kb/s
+ *
+ * flags:   IEEE80211_F_SHPREAMBLE (use short preamble),
+ *          IEEE80211_F_SHSLOT (use short slot length)
+ *
+ * Arguments out:
+ *
+ * d:       802.11 Duration field for data frame,
+ *          PLCP Length for data frame,
+ *          PLCP Service field for data frame,
+ *          802.11 Duration field for RTS
+ */
+static int
+ieee80211_compute_duration1(int len, uint32_t flags, int rate,
+    struct ieee80211_duration *d)
+{
+       int ack, bitlen, cts, data_dur, remainder;
+
+       /* RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK
+        * DATA reserves medium for SIFS | ACK
+        */
+
+       bitlen = len * 8;
+
+#if 0
+       /* RTS is always sent at 1 Mb/s.  (XXX Really?) */
+       d->d_rts_plcp_len = sizeof(struct ieee80211_frame_rts) * 8;
+#endif
+       d->d_plcp_svc = 0;
+
+       switch (rate) {
+       case 2:         /* 1 Mb/s */
+       case 4:         /* 2 Mb/s */
+               data_dur = (bitlen * 2) / rate;
+
+               /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */
+               cts = IEEE80211_DUR_DS_SLOW_CTS;
+               ack = IEEE80211_DUR_DS_SLOW_ACK;
+               break;
+       case 44:        /* 22  Mb/s */
+               d->d_plcp_svc = IEEE80211_PLCP_SERVICE_PBCC;
+               /*FALLTHROUGH*/
+       case 11:        /* 5.5 Mb/s */
+       case 22:        /* 11  Mb/s */
+               remainder = (bitlen * 2) % rate;
+
+               if (remainder != 0)
+                       data_dur = (bitlen * 2) / rate + 1;
+               else
+                       data_dur = (bitlen * 2) / rate;
+
+               if (rate == 22 && remainder <= 6)
+                       d->d_plcp_svc |= IEEE80211_PLCP_SERVICE_LENEXT;
+
+               /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */
+               cts = IEEE80211_DUR_DS_FAST_CTS;
+               ack = IEEE80211_DUR_DS_FAST_ACK;
+               break;
+       default:
+               /* TBD */
+               return -1;
+       }
+
+       d->d_rts_dur = data_dur + 3 * (IEEE80211_DUR_DS_SIFS +
+           IEEE80211_DUR_DS_SHORT_PREAMBLE +
+           IEEE80211_DUR_DS_FAST_PLCPHDR) + cts + ack;
+       d->d_data_dur = data_dur + IEEE80211_DUR_DS_SIFS +
+           2 * (IEEE80211_DUR_DS_SHORT_PREAMBLE +
+                IEEE80211_DUR_DS_FAST_PLCPHDR) + ack;
+
+       d->d_plcp_len = data_dur;
+
+       if ((flags & IEEE80211_F_SHPREAMBLE) != 0)
+               return 0;
+
+       d->d_rts_dur += 3 * (IEEE80211_DUR_DS_LONG_PREAMBLE -
+                            IEEE80211_DUR_DS_SHORT_PREAMBLE) +
+                       3 * (IEEE80211_DUR_DS_SLOW_PLCPHDR -
+                            IEEE80211_DUR_DS_FAST_PLCPHDR);
+       d->d_data_dur += 2 * (IEEE80211_DUR_DS_LONG_PREAMBLE -
+                             IEEE80211_DUR_DS_SHORT_PREAMBLE) +
+                        2 * (IEEE80211_DUR_DS_SLOW_PLCPHDR -
+                             IEEE80211_DUR_DS_FAST_PLCPHDR);
+       return 0;
+}
+
+/*
+ * Arguments in:
+ *
+ * wh:      802.11 header
+ *
+ * paylen:  payload length (no FCS, no WEP header)
+ *
+ * rate:    MSDU speed, units 500kb/s
+ *
+ * fraglen: fragment length, set to maximum (or higher) for no
+ *          fragmentation
+ *
+ * flags:   IEEE80211_F_PRIVACY (hardware adds WEP),
+ *          IEEE80211_F_SHPREAMBLE (use short preamble),
+ *          IEEE80211_F_SHSLOT (use short slot length)
+ *
+ * Arguments out:
+ *
+ * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
+ *     of first/only fragment
+ *
+ * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
+ *     of first/only fragment
+ */
+int
+ieee80211_compute_duration(struct ieee80211_frame *wh, int paylen,
+    uint32_t flags, int fraglen, int rate, struct ieee80211_duration *d0,
+    struct ieee80211_duration *dn, int *npktp)
+{
+       int rc;
+       int firstlen, hdrlen, lastlen, lastlen0, npkt, overlen;
+
+       if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
+               hdrlen = sizeof(struct ieee80211_frame_addr4);
+       else
+               hdrlen = sizeof(struct ieee80211_frame);
+
+       if ((flags & IEEE80211_F_PRIVACY) != 0) {
+               overlen = IEEE80211_WEP_TOTLEN + IEEE80211_CRC_LEN;
+#if 0  /* 802.11 lets us extend a fragment's length by the length of
+        * a WEP header, AFTER fragmentation.  Might want to disable
+        * this while fancy link adaptations are running.
+        */
+               fraglen -= IEEE80211_WEP_TOTLEN;
+#endif
+#if 0  /* Ditto CRC? */
+               fraglen -= IEEE80211_CRC_LEN;
+#endif
+       } else
+               overlen = IEEE80211_CRC_LEN;
+
+       npkt = paylen / fraglen;
+       lastlen0 = paylen % fraglen;
+
+       if (npkt == 0) {
+               /* no fragments */
+               lastlen = paylen + overlen;
+       } else if (lastlen0 != 0) {
+               /* a short fragment */
+               lastlen = lastlen0 + overlen;
+               npkt++;
+       } else
+               lastlen = fraglen + overlen;
+
+       if (npktp != NULL)
+               *npktp = npkt;
+
+       if (npkt > 1)
+               firstlen = fraglen + overlen;
+       else
+               firstlen = paylen + overlen;
+
+       rc = ieee80211_compute_duration1(firstlen + hdrlen, flags, rate, d0);
+       if (rc == -1)
+               return rc;
+       if (npkt > 1) {
+               *dn = *d0;
+               return 0;
+       }
+       return ieee80211_compute_duration1(lastlen + hdrlen, flags, rate, dn);
+}
+
+/*
  * Add a supported rates element id to a frame.
  */
 u_int8_t *
diff -r a747b3159788 -r cf6db84715d6 sys/net80211/ieee80211_proto.h
--- a/sys/net80211/ieee80211_proto.h    Sun Dec 19 06:42:24 2004 +0000
+++ b/sys/net80211/ieee80211_proto.h    Sun Dec 19 08:08:06 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ieee80211_proto.h,v 1.5 2004/07/28 08:12:49 dyoung Exp $       */
+/*     $NetBSD: ieee80211_proto.h,v 1.6 2004/12/19 08:08:06 dyoung Exp $       */
 /*-
  * Copyright (c) 2001 Atsushi Onoe
  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
@@ -78,6 +78,9 @@
 extern void ieee80211_dump_pkt(u_int8_t *, int, int, int);
 extern int ieee80211_ibss_merge(struct ieee80211com *,
                struct ieee80211_node *, u_int64_t);
+extern int ieee80211_compute_duration(struct ieee80211_frame *, int,
+               uint32_t, int, int, struct ieee80211_duration *,
+               struct ieee80211_duration *, int *);
 
 extern const char *ieee80211_state_name[IEEE80211_S_MAX];
 #endif /* _NET80211_IEEE80211_PROTO_H_ */



Home | Main Index | Thread Index | Old Index