]> rtime.felk.cvut.cz Git - frescor/fwp.git/blobdiff - fwp/mngr/fwp_admctrl.c
Allow bypassing FWP by setting FWP_BYPASS environment variable
[frescor/fwp.git] / fwp / mngr / fwp_admctrl.c
index def2faaa8abb46595d31fef9ecaca305be22cbd0..e5f98eb492d83d83fd5a397616ac490922c0efb1 100644 (file)
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FWP (Frescor WLAN Protocol)                     */
+/*                                                                       */
+/* FWP is free software; you can redistribute it and/or modify it        */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FWP is distributed in the hope that it will be        */
+/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty   */
+/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   */
+/* General Public License for more details. You should have received a   */
+/* copy of the GNU General Public License along with FWP; see file       */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FWP header files in a file,         */
+/* instantiating FWP generics or templates, or linking other files       */
+/* with FWP objects to produce an executable application, does not       */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+#include <fres_sa_scenario.h>
+#include <fwp.h>
+#include "fwp_idl.h"
 #include "fwp_admctrl.h"
-#include "fwp_vres.h"
+#include <ul_log.h>
+#include <ul_logreg.h>
+#include "fwp_utils.h"
 
-static int nr_negotiated =0;
-/***/
+UL_LOG_CUST(ulogd_fwp_admctrl);
+ul_log_domain_t ulogd_fwp_admctrl = {UL_LOGL_MSG, "fwp_admctrl"};
+UL_LOGREG_SINGLE_DOMAIN_INIT_FUNCTION(fwp_admctrl_logreg_domains, ulogd_fwp_admctrl);
 
-void fwp_admctrl_stupid(fwp_contract_data_t *contdata)
+/* TODO: Find out the real value and determine what influences it (MTU
+ *      of the interface minus header sizes?).  */
+#define MTU 1472
+#define UDP_HEADER_SIZE 8
+#define IP_HEADER_SIZE 20
+#define LLC_HEADER_SIZE 2      /* ??? */
+#define MAC_HEADER_SIZE 26     /* With QoS field added */
+#define MAC_FCS_SIZE 4
+
+#define RTS_FRAME_SIZE 20
+#define CTS_FRAME_SIZE 14
+#define ACK_FRAME_SIZE 14
+
+#define ASLOTTIME_USEC 20      /* 802.11g-2003 p. 46 */
+#define ASIFSTIME_USEC 10
+#define ADIFSTIME_USEC (ASIFSTIME_USEC + 2*ASLOTTIME_USEC)
+#define AAIFSTIME_USEC(n) (ASIFSTIME_USEC + (n)*ASLOTTIME_USEC)
+
+/* Default values from 802.11e */
+const int aifsn[FWP_AC_NUM] = { 2, 2, 3, 7 };
+const int cwmin[FWP_AC_NUM] = { 3, 7, 15, 15 };
+
+/* Experimental konstants - weight of backoff */
+const int pisvejc[FWP_AC_NUM] = { 6, 5, 2, 2 };
+
+int fwp_reserved_utilization;
+
+/**
+ * Calucaltes frame duration in microseconds. If the real duration is
+ * represented by a fractional number, the value is rounded up.
+ *
+ * @param length Number of bytes in PSDU.
+ * @param rate_bps Transmit rate of PSDU. The rate should correspond
+ *            to other parameters accoring to 19.3.2 (802.11g)
+ * @param erp_ofdm Whether Extended Rate PHY (part of 802.11g) and ERP-OFDM
+ *            modulation is used.
+ * @param short_preamble Whether short preamble (HR/DSSS/short) is
+ *            used (802.11b)
+ *
+ * @return The number of microseconds or a negative number in case of error.
+ */
+static int frame_duration(uint16_t length, int rate_bps, bool erp_ofdm, bool short_preamble)
 {
-       contdata->vres_params.ac_id = FWP_AC_VI;
-       contdata->vres_params.budget = 100;
-       contdata->vres_params.period_usec = 20; 
+       uint32_t duration_usec = 0;
+
+       if (!erp_ofdm) {
+               duration_usec = ((int64_t)(length) * 8 * SEC_TO_USEC / rate_bps);
+               if (short_preamble) {
+                       /* For HR/DSSS/short (2, 5.5 and 11 Mbit,
+                        * 802.11b-1999), also for DSSS-OFDM rates and
+                        * ERP-PBCC rates.
+                        * Preamble sent at 1 MBit, header at 2 Mbit */
+                       duration_usec += 72/*bits*/+48/*bits*//2;
+               } else {
+                       /* For DSSS PHY (1 and 2 Mbit rates,
+                        * 802.11-1999) and for DSS-OFDM and ERP-PBCC
+                        * rates. Always sent at 1 MBit */
+                       duration_usec += 144/*bits*/+48/*bits*/;
+               }
+       } else {
+#define MBIT_TO_INDEX(rate_Mbps)  ((rate_Mbps)/3 - 2)
+               const int N_dbps[] = {
+                       [MBIT_TO_INDEX(6)] = 24,
+                       [MBIT_TO_INDEX(9)] = 36,
+                       [MBIT_TO_INDEX(12)] = 48,
+                       [MBIT_TO_INDEX(18)] = 72,
+                       [MBIT_TO_INDEX(24)] = 96,
+                       [MBIT_TO_INDEX(36)] = 144,
+                       [MBIT_TO_INDEX(48)] = 192,
+                       [MBIT_TO_INDEX(54)] = 216
+               };
+               int rate_idx = MBIT_TO_INDEX(rate_bps/1000/1000);
+#undef MBIT_TO_INDEX
+               if (rate_idx < 0 ||
+                   rate_idx >= sizeof(N_dbps)/sizeof(*N_dbps) ||
+                   N_dbps[rate_idx] == 0)
+                       return -1;
+
+               duration_usec += 16 + 4; /* Preamble, SIGNAL */
+               int bits =
+                       16 +        /* SERVICE */
+                       length * 8 +
+                       6;          /* tail bits */
+               int Nsym = (bits + N_dbps[rate_idx] - 1)/N_dbps[rate_idx];
+
+               duration_usec += Nsym * 4;
+
+               duration_usec += 6; /* signal extension */
+       }
+       return duration_usec;
+}
+
+int fwp_admctrl_utilization(struct fres_sa_scenario *scenario, void *priv,
+                                bool *schedulable)
+{
+       int utilization = 0;
+       struct frm_fwp_priv *pr = priv;
+       const int rate = pr->rate_mbps*1000*1000;
+       struct fres_sa_contract *c;
+       long int period_usec;
+       fres_block_fwp_sched *fwp_sched;
+
+       size_t bytes; 
+       long int duration_usec, tmp_usec;
+       int fragments;
+       int ac = FWP_AC_VO; 
        
-       if (nr_negotiated <= 2) { 
-               nr_negotiated++;
-               contdata->status =  FWP_CONT_RESERVED;  
+       fres_sa_scenario_for_each_no_cancel_contract(scenario, c) {
+               fres_block_basic *basic;
+               char id[40];
+               fres_contract_id_to_string(id, &c->contract->id, sizeof(id));
+               basic = fres_contract_get_basic(c->contract);
+
+               frsh_network_budget_to_bytes(FRSH_NETPF_FWP,&basic->budget,&bytes);
+               ul_logmsg("processing: id=%s, period=%ld ms, budget=%lu bytes\n",
+                      id,
+                      fosa_rel_time_to_msec(basic->period),
+                      (long unsigned int)bytes);
+
+               period_usec = basic ? fosa_rel_time_to_msec(basic->period)*1000 : 0;
+
+               /* Calculate protocol overhead */
+               fragments = (bytes + MTU - 1) / MTU;
+
+               if (fragments == 0 && period_usec != 0)
+                       continue;
+
+               const int data_overhead = UDP_HEADER_SIZE + IP_HEADER_SIZE +
+                       LLC_HEADER_SIZE + MAC_FCS_SIZE;
+
+               duration_usec = frame_duration(data_overhead + bytes%MTU, rate, 
+                                              pr->erp_ofdm, pr->short_preamble);
+               tmp_usec = frame_duration(data_overhead + MTU, rate,
+                                         pr->erp_ofdm, pr->short_preamble);
+               duration_usec += tmp_usec*(fragments-1);
+               /* Add average backoff - assume there is no collision */
+               tmp_usec = ASLOTTIME_USEC*fragments*pisvejc[ac];
+               duration_usec += (aifsn[ac] + cwmin[ac]/2)*tmp_usec;
+               /* We use ACK and ignore burst */
+               tmp_usec = frame_duration(ACK_FRAME_SIZE, rate,
+                                         pr->erp_ofdm, pr->short_preamble)
+                       + ASIFSTIME_USEC; 
+               duration_usec += fragments * tmp_usec; 
+               //printf("duration: %ld ms\n", duration_usec/1000);
+
+               /* TODO: If STA-to-STA, multiply it by two. Note that
+                * AP may use different values for backoff. */
+               duration_usec *= 2; /* For demo, we have always STA-to-STA */
+
+               if (c->contract == c->new) {
+                       if (period_usec == 0) {
+                               ul_logmsg("Period is zero!\n");
+                               goto not_schedulable;
+                       }
+
+                       frsh_rel_time_t deadline;
+                       long int d;
+                       if (fres_contract_get_deadline(&c->contract, &deadline)) {
+                               d = fosa_rel_time_to_msec(deadline)*1000;
+                       } else {
+                               d = 100/*sec*/*1000*1000;
+                       }
+                       if (d < 30/*msec*/*1000) {
+                               ul_logmsg("Deadline shorter than 30 ms!\n");
+                               goto not_schedulable;
+                       };
+                       
+                       fwp_sched = malloc(sizeof(*fwp_sched));
+                       fwp_sched->ac_id =
+                               d <  100*1000 ? FWP_AC_VO :
+                               d <  500*1000 ? FWP_AC_VI :
+                               d < 1000*1000 ? FWP_AC_BE :
+                               FWP_AC_BK;
+                       fres_contract_add_block(c->contract, FRES_BLOCK_FWP_SCHED, fwp_sched);
+               }
+
+               utilization += (long long)(duration_usec * 10000) / period_usec;
        }
+       
+       if (utilization >= 10000 * 96/100 && !pr->bypass) {
+               goto not_schedulable;
+       }
+       scenario->utilization = utilization/100; /* For GUI */
+
+       ul_logmsg("accepted\n");
+       *schedulable = true;
+       return 0;
+
+not_schedulable:
+       ul_logmsg("rejected\n");
+       *schedulable = false;
+       return 0;
 }