diff spandsp-0.0.6pre17/spandsp-sim/g1050.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spandsp-0.0.6pre17/spandsp-sim/g1050.c	Fri Jun 25 15:50:58 2010 +0200
@@ -0,0 +1,1329 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * g1050.c - IP network modeling, as per G.1050/TIA-921.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2007 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: g1050.c,v 1.17 2009/06/02 14:55:36 steveu Exp $
+ */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <fcntl.h>
+#if defined(HAVE_TGMATH_H)
+#include <tgmath.h>
+#endif
+#if defined(HAVE_MATH_H)
+#define GEN_CONST
+#include <math.h>
+#endif
+#include "floating_fudge.h"
+
+#include "spandsp.h"
+#include "spandsp/g1050.h"
+
+#define PACKET_LOSS_TIME    -1
+
+#define FALSE 0
+#define TRUE (!FALSE)
+
+g1050_constants_t g1050_constants[1] =
+{
+    {
+        {
+            {   /* Side A LAN */
+                {
+                    0.004,          /*! Probability of loss rate change low->high */
+                    0.1             /*! Probability of loss rate change high->low */
+                },
+                {
+                    {
+                        0.0,        /*! Probability of an impulse */
+                        0.0,
+                    },
+                    {
+                        0.5,
+                        0.0
+                    }
+                },
+                1.0,                /*! Impulse height, based on MTU and bit rate */
+                0.0,                /*! Impulse decay coefficient */
+                0.001,              /*! Probability of packet loss due to occupancy. */
+                0.15                /*! Probability of packet loss due to a multiple access collision. */
+            },
+            {   /* Side A access link */
+                {
+                    0.0002,         /*! Probability of loss rate change low->high */
+                    0.2             /*! Probability of loss rate change high->low */
+                },
+                {
+                    {
+                        0.001,      /*! Probability of an impulse */
+                        0.0,
+                    },
+                    {
+                        0.3,
+                        0.4
+                    }
+                },
+                40.0,               /*! Impulse height, based on MTU and bit rate */
+                0.75,               /*! Impulse decay coefficient */
+                0.0005,             /*! Probability of packet loss due to occupancy. */
+                0.0                 /*! Probability of packet loss due to a multiple access collision. */
+            },
+            {   /* Side B access link */
+                {
+                    0.0002,         /*! Probability of loss rate change low->high */
+                    0.2             /*! Probability of loss rate change high->low */
+                },
+                {
+                    {
+                        0.001,      /*! Probability of an impulse */
+                        0.0,
+                    },
+                    {
+                        0.3,
+                        0.4
+                    }
+                },
+                40.0,               /*! Impulse height, based on MTU and bit rate */
+                0.75,               /*! Impulse decay coefficient */
+                0.0005,             /*! Probability of packet loss due to occupancy. */
+                0.0                 /*! Probability of packet loss due to a multiple access collision. */
+            },
+            {   /* Side B LAN */
+                {
+                    0.004,          /*! Probability of loss rate change low->high */
+                    0.1             /*! Probability of loss rate change high->low */
+                },
+                {
+                    {
+                        0.0,        /*! Probability of an impulse */
+                        0.0,
+                    },
+                    {
+                        0.5,
+                        0.0
+                    }
+                },
+                1.0,                /*! Impulse height, based on MTU and bit rate */
+                0.0,                /*! Impulse decay coefficient */
+                0.001,              /*! Probability of packet loss due to occupancy. */
+                0.15                /*! Probability of packet loss due to a multiple access collision. */
+            }
+        }
+    }
+};
+
+g1050_channel_speeds_t g1050_speed_patterns[168] =
+{
+    {  4000000, 0,   128000,   768000, 0,   4000000, 0,   128000,   768000, 0, 0.360},
+    {  4000000, 0,   128000,   768000, 0,  20000000, 0,   128000,   768000, 0, 0.720},
+    {  4000000, 0,   128000,   768000, 0, 100000000, 0,   128000,   768000, 0, 0.360},
+    { 20000000, 0,   128000,   768000, 0,  20000000, 0,   128000,   768000, 0, 0.360},
+    { 20000000, 0,   128000,   768000, 0, 100000000, 0,   128000,   768000, 0, 0.360},
+    {100000000, 0,   128000,   768000, 0, 100000000, 0,   128000,   768000, 0, 0.090},
+    {  4000000, 0,   128000,  1536000, 0,   4000000, 0,   384000,   768000, 0, 0.720},
+    {  4000000, 0,   128000,  1536000, 0,  20000000, 0,   384000,   768000, 0, 1.470},
+    {  4000000, 0,   128000,  1536000, 0, 100000000, 0,   384000,   768000, 0, 0.840},
+    { 20000000, 0,   128000,  1536000, 0,  20000000, 0,   384000,   768000, 0, 0.750},
+    { 20000000, 0,   128000,  1536000, 0, 100000000, 0,   384000,   768000, 0, 0.855},
+    {100000000, 0,   128000,  1536000, 0, 100000000, 0,   384000,   768000, 0, 0.240},
+    {  4000000, 0,   128000,  3000000, 0,   4000000, 0,   384000,   768000, 0, 0.120},
+    {  4000000, 0,   128000,  3000000, 0,  20000000, 0,   384000,   768000, 0, 0.420},
+    {  4000000, 0,   128000,  3000000, 0, 100000000, 0,   384000,   768000, 0, 0.840},
+    { 20000000, 0,   128000,  3000000, 0,  20000000, 0,   384000,   768000, 0, 0.300},
+    { 20000000, 0,   128000,  3000000, 0, 100000000, 0,   384000,   768000, 0, 0.930},
+    {100000000, 0,   128000,  3000000, 0, 100000000, 0,   384000,   768000, 0, 0.390},
+    {  4000000, 0,   384000,   768000, 0,   4000000, 0,   128000,  1536000, 0, 0.720},
+    {  4000000, 0,   384000,   768000, 0,  20000000, 0,   128000,  1536000, 0, 1.470},
+    {  4000000, 0,   384000,   768000, 0, 100000000, 0,   128000,  1536000, 0, 0.840},
+    { 20000000, 0,   384000,   768000, 0,  20000000, 0,   128000,  1536000, 0, 0.750},
+    { 20000000, 0,   384000,   768000, 0, 100000000, 0,   128000,  1536000, 0, 0.855},
+    {100000000, 0,   384000,   768000, 0, 100000000, 0,   128000,  1536000, 0, 0.240},
+    {  4000000, 0,   384000,  1536000, 0,   4000000, 0,   384000,  1536000, 0, 1.440},
+    {  4000000, 0,   384000,  1536000, 0,  20000000, 0,   384000,  1536000, 0, 3.000},
+    {  4000000, 0,   384000,  1536000, 0, 100000000, 0,   384000,  1536000, 0, 1.920},
+    { 20000000, 0,   384000,  1536000, 0,  20000000, 0,   384000,  1536000, 0, 1.563},
+    { 20000000, 0,   384000,  1536000, 0, 100000000, 0,   384000,  1536000, 0, 2.000},
+    {100000000, 0,   384000,  1536000, 0, 100000000, 0,   384000,  1536000, 0, 0.640},
+    {  4000000, 0,   384000,  3000000, 0,   4000000, 0,   384000,  1536000, 0, 0.240},
+    {  4000000, 0,   384000,  3000000, 0,  20000000, 0,   384000,  1536000, 0, 0.850},
+    {  4000000, 0,   384000,  3000000, 0, 100000000, 0,   384000,  1536000, 0, 1.720},
+    { 20000000, 0,   384000,  3000000, 0,  20000000, 0,   384000,  1536000, 0, 0.625},
+    { 20000000, 0,   384000,  3000000, 0, 100000000, 0,   384000,  1536000, 0, 2.025},
+    {100000000, 0,   384000,  3000000, 0, 100000000, 0,   384000,  1536000, 0, 1.040},
+    {  4000000, 0,   384000,   768000, 0,   4000000, 0,   128000,  3000000, 0, 0.120},
+    {  4000000, 0,   384000,   768000, 0,  20000000, 0,   128000,  3000000, 0, 0.420},
+    {  4000000, 0,   384000,   768000, 0, 100000000, 0,   128000,  3000000, 0, 0.840},
+    { 20000000, 0,   384000,   768000, 0,  20000000, 0,   128000,  3000000, 0, 0.300},
+    { 20000000, 0,   384000,   768000, 0, 100000000, 0,   128000,  3000000, 0, 0.930},
+    {100000000, 0,   384000,   768000, 0, 100000000, 0,   128000,  3000000, 0, 0.390},
+    {  4000000, 0,   384000,  1536000, 0,   4000000, 0,   384000,  3000000, 0, 0.240},
+    {  4000000, 0,   384000,  1536000, 0,  20000000, 0,   384000,  3000000, 0, 0.850},
+    {  4000000, 0,   384000,  1536000, 0, 100000000, 0,   384000,  3000000, 0, 1.720},
+    { 20000000, 0,   384000,  1536000, 0,  20000000, 0,   384000,  3000000, 0, 0.625},
+    { 20000000, 0,   384000,  1536000, 0, 100000000, 0,   384000,  3000000, 0, 2.025},
+    {100000000, 0,   384000,  1536000, 0, 100000000, 0,   384000,  3000000, 0, 1.040},
+    {  4000000, 0,   384000,  3000000, 0,   4000000, 0,   384000,  3000000, 0, 0.040},
+    {  4000000, 0,   384000,  3000000, 0,  20000000, 0,   384000,  3000000, 0, 0.200},
+    {  4000000, 0,   384000,  3000000, 0, 100000000, 0,   384000,  3000000, 0, 0.520},
+    { 20000000, 0,   384000,  3000000, 0,  20000000, 0,   384000,  3000000, 0, 0.250},
+    { 20000000, 0,   384000,  3000000, 0, 100000000, 0,   384000,  3000000, 0, 1.300},
+    {100000000, 0,   384000,  3000000, 0, 100000000, 0,   384000,  3000000, 0, 1.690},
+    {  4000000, 0,   128000,  1536000, 0,  20000000, 0,   768000,  1536000, 0, 0.090},
+    {  4000000, 0,   128000,  1536000, 0, 100000000, 0,   768000,  1536000, 0, 0.360},
+    { 20000000, 0,   128000,  1536000, 0,  20000000, 0,   768000,  1536000, 0, 0.090},
+    { 20000000, 0,   128000,  1536000, 0, 100000000, 0,   768000,  1536000, 0, 0.405},
+    {100000000, 0,   128000,  1536000, 0, 100000000, 0,   768000,  1536000, 0, 0.180},
+    {  4000000, 0,   128000,  7000000, 0,  20000000, 0,   768000,   768000, 0, 0.270},
+    {  4000000, 0,   128000,  7000000, 0, 100000000, 0,   768000,   768000, 0, 1.080},
+    { 20000000, 0,   128000,  7000000, 0,  20000000, 0,   768000,   768000, 0, 0.270},
+    { 20000000, 0,   128000,  7000000, 0, 100000000, 0,   768000,   768000, 0, 1.215},
+    {100000000, 0,   128000,  7000000, 0, 100000000, 0,   768000,   768000, 0, 0.540},
+    {  4000000, 0,   128000, 13000000, 0,  20000000, 0,   768000, 13000000, 0, 0.030},
+    {  4000000, 0,   128000, 13000000, 0, 100000000, 0,   768000, 13000000, 0, 0.120},
+    { 20000000, 0,   128000, 13000000, 0,  20000000, 0,   768000, 13000000, 0, 0.030},
+    { 20000000, 0,   128000, 13000000, 0, 100000000, 0,   768000, 13000000, 0, 0.135},
+    {100000000, 0,   128000, 13000000, 0, 100000000, 0,   768000, 13000000, 0, 0.060},
+    {  4000000, 0,   384000,  1536000, 0,  20000000, 0,  1536000,  1536000, 0, 0.180},
+    {  4000000, 0,   384000,  1536000, 0, 100000000, 0,  1536000,  1536000, 0, 0.720},
+    { 20000000, 0,   384000,  1536000, 0,  20000000, 0,  1536000,  1536000, 0, 0.188},
+    { 20000000, 0,   384000,  1536000, 0, 100000000, 0,  1536000,  1536000, 0, 0.870},
+    {100000000, 0,   384000,  1536000, 0, 100000000, 0,  1536000,  1536000, 0, 0.480},
+    {  4000000, 0,   384000,  7000000, 0,  20000000, 0,   768000,  1536000, 0, 0.540},
+    {  4000000, 0,   384000,  7000000, 0, 100000000, 0,   768000,  1536000, 0, 2.160},
+    { 20000000, 0,   384000,  7000000, 0,  20000000, 0,   768000,  1536000, 0, 0.563},
+    { 20000000, 0,   384000,  7000000, 0, 100000000, 0,   768000,  1536000, 0, 2.610},
+    {100000000, 0,   384000,  7000000, 0, 100000000, 0,   768000,  1536000, 0, 1.440},
+    {  4000000, 0,   384000, 13000000, 0,  20000000, 0,  1536000, 13000000, 0, 0.060},
+    {  4000000, 0,   384000, 13000000, 0, 100000000, 0,  1536000, 13000000, 0, 0.240},
+    { 20000000, 0,   384000, 13000000, 0,  20000000, 0,  1536000, 13000000, 0, 0.063},
+    { 20000000, 0,   384000, 13000000, 0, 100000000, 0,  1536000, 13000000, 0, 0.290},
+    {100000000, 0,   384000, 13000000, 0, 100000000, 0,  1536000, 13000000, 0, 0.160},
+    {  4000000, 0,   384000,  1536000, 0,  20000000, 0,  1536000,  3000000, 0, 0.030},
+    {  4000000, 0,   384000,  1536000, 0, 100000000, 0,  1536000,  3000000, 0, 0.120},
+    { 20000000, 0,   384000,  1536000, 0,  20000000, 0,  1536000,  3000000, 0, 0.075},
+    { 20000000, 0,   384000,  1536000, 0, 100000000, 0,  1536000,  3000000, 0, 0.495},
+    {100000000, 0,   384000,  1536000, 0, 100000000, 0,  1536000,  3000000, 0, 0.780},
+    {  4000000, 0,   384000,  7000000, 0,  20000000, 0,   768000,  3000000, 0, 0.090},
+    {  4000000, 0,   384000,  7000000, 0, 100000000, 0,   768000,  3000000, 0, 0.360},
+    { 20000000, 0,   384000,  7000000, 0,  20000000, 0,   768000,  3000000, 0, 0.225},
+    { 20000000, 0,   384000,  7000000, 0, 100000000, 0,   768000,  3000000, 0, 1.485},
+    {100000000, 0,   384000,  7000000, 0, 100000000, 0,   768000,  3000000, 0, 2.340},
+    {  4000000, 0,   384000, 13000000, 0,  20000000, 0,  3000000, 13000000, 0, 0.010},
+    {  4000000, 0,   384000, 13000000, 0, 100000000, 0,  3000000, 13000000, 0, 0.040},
+    { 20000000, 0,   384000, 13000000, 0,  20000000, 0,  3000000, 13000000, 0, 0.025},
+    { 20000000, 0,   384000, 13000000, 0, 100000000, 0,  3000000, 13000000, 0, 0.165},
+    {100000000, 0,   384000, 13000000, 0, 100000000, 0,  3000000, 13000000, 0, 0.260},
+    {  4000000, 0,   768000,  1536000, 0,  20000000, 0,   128000,  1536000, 0, 0.090},
+    { 20000000, 0,   768000,  1536000, 0,  20000000, 0,   128000,  1536000, 0, 0.090},
+    { 20000000, 0,   768000,  1536000, 0, 100000000, 0,   128000,  1536000, 0, 0.405},
+    {  4000000, 0,   768000,  1536000, 0, 100000000, 0,   128000,  1536000, 0, 0.360},
+    {100000000, 0,   768000,  1536000, 0, 100000000, 0,   128000,  1536000, 0, 0.180},
+    {  4000000, 0,  1536000,  1536000, 0,  20000000, 0,   384000,  1536000, 0, 0.180},
+    { 20000000, 0,  1536000,  1536000, 0,  20000000, 0,   384000,  1536000, 0, 0.188},
+    { 20000000, 0,  1536000,  1536000, 0, 100000000, 0,   384000,  1536000, 0, 0.870},
+    {  4000000, 0,  1536000,  1536000, 0, 100000000, 0,   384000,  1536000, 0, 0.720},
+    {100000000, 0,  1536000,  1536000, 0, 100000000, 0,   384000,  1536000, 0, 0.480},
+    {  4000000, 0,  1536000,  3000000, 0,  20000000, 0,   384000,  1536000, 0, 0.030},
+    { 20000000, 0,  1536000,  3000000, 0,  20000000, 0,   384000,  1536000, 0, 0.075},
+    { 20000000, 0,  1536000,  3000000, 0, 100000000, 0,   384000,  1536000, 0, 0.495},
+    {  4000000, 0,  1536000,  3000000, 0, 100000000, 0,   384000,  1536000, 0, 0.120},
+    {100000000, 0,  1536000,  3000000, 0, 100000000, 0,   384000,  1536000, 0, 0.780},
+    {  4000000, 0,   768000,   768000, 0,  20000000, 0,   128000,  7000000, 0, 0.270},
+    { 20000000, 0,   768000,   768000, 0,  20000000, 0,   128000,  7000000, 0, 0.270},
+    { 20000000, 0,   768000,   768000, 0, 100000000, 0,   128000,  7000000, 0, 1.215},
+    {  4000000, 0,   768000,   768000, 0, 100000000, 0,   128000,  7000000, 0, 1.080},
+    {100000000, 0,   768000,   768000, 0, 100000000, 0,   128000,  7000000, 0, 0.540},
+    {  4000000, 0,   768000,  1536000, 0,  20000000, 0,   384000,  7000000, 0, 0.540},
+    { 20000000, 0,   768000,  1536000, 0,  20000000, 0,   384000,  7000000, 0, 0.563},
+    { 20000000, 0,   768000,  1536000, 0, 100000000, 0,   384000,  7000000, 0, 2.610},
+    {  4000000, 0,   768000,  1536000, 0, 100000000, 0,   384000,  7000000, 0, 2.160},
+    {100000000, 0,   768000,  1536000, 0, 100000000, 0,   384000,  7000000, 0, 1.440},
+    {  4000000, 0,   768000,  3000000, 0,  20000000, 0,   384000,  7000000, 0, 0.090},
+    { 20000000, 0,   768000,  3000000, 0,  20000000, 0,   384000,  7000000, 0, 0.225},
+    { 20000000, 0,   768000,  3000000, 0, 100000000, 0,   384000,  7000000, 0, 1.485},
+    {  4000000, 0,   768000,  3000000, 0, 100000000, 0,   384000,  7000000, 0, 0.360},
+    {100000000, 0,   768000,  3000000, 0, 100000000, 0,   384000,  7000000, 0, 2.340},
+    {  4000000, 0,   768000, 13000000, 0,  20000000, 0,   128000, 13000000, 0, 0.030},
+    { 20000000, 0,   768000, 13000000, 0,  20000000, 0,   128000, 13000000, 0, 0.030},
+    { 20000000, 0,   768000, 13000000, 0, 100000000, 0,   128000, 13000000, 0, 0.135},
+    {  4000000, 0,   768000, 13000000, 0, 100000000, 0,   128000, 13000000, 0, 0.120},
+    {100000000, 0,   768000, 13000000, 0, 100000000, 0,   128000, 13000000, 0, 0.060},
+    {  4000000, 0,  1536000, 13000000, 0,  20000000, 0,   384000, 13000000, 0, 0.060},
+    { 20000000, 0,  1536000, 13000000, 0,  20000000, 0,   384000, 13000000, 0, 0.063},
+    { 20000000, 0,  1536000, 13000000, 0, 100000000, 0,   384000, 13000000, 0, 0.290},
+    {  4000000, 0,  1536000, 13000000, 0, 100000000, 0,   384000, 13000000, 0, 0.240},
+    {100000000, 0,  1536000, 13000000, 0, 100000000, 0,   384000, 13000000, 0, 0.160},
+    {  4000000, 0,  3000000, 13000000, 0,  20000000, 0,   384000, 13000000, 0, 0.010},
+    { 20000000, 0,  3000000, 13000000, 0,  20000000, 0,   384000, 13000000, 0, 0.025},
+    { 20000000, 0,  3000000, 13000000, 0, 100000000, 0,   384000, 13000000, 0, 0.165},
+    {  4000000, 0,  3000000, 13000000, 0, 100000000, 0,   384000, 13000000, 0, 0.040},
+    {100000000, 0,  3000000, 13000000, 0, 100000000, 0,   384000, 13000000, 0, 0.260},
+    { 20000000, 0,  1536000,  1536000, 0,  20000000, 0,  1536000,  1536000, 0, 0.023},
+    { 20000000, 0,  1536000,  1536000, 0, 100000000, 0,  1536000,  1536000, 0, 0.180},
+    {100000000, 0,  1536000,  1536000, 0, 100000000, 0,  1536000,  1536000, 0, 0.360},
+    { 20000000, 0,  1536000,  7000000, 0,  20000000, 0,   768000,  1536000, 0, 0.068},
+    { 20000000, 0,  1536000,  7000000, 0, 100000000, 0,   768000,  1536000, 0, 0.540},
+    {100000000, 0,  1536000,  7000000, 0, 100000000, 0,   768000,  1536000, 0, 1.080},
+    { 20000000, 0,  1536000, 13000000, 0,  20000000, 0,  1536000, 13000000, 0, 0.015},
+    { 20000000, 0,  1536000, 13000000, 0, 100000000, 0,  1536000, 13000000, 0, 0.120},
+    {100000000, 0,  1536000, 13000000, 0, 100000000, 0,  1536000, 13000000, 0, 0.240},
+    { 20000000, 0,   768000,  1536000, 0,  20000000, 0,  1536000,  7000000, 0, 0.068},
+    { 20000000, 0,   768000,  1536000, 0, 100000000, 0,  1536000,  7000000, 0, 0.540},
+    {100000000, 0,   768000,  1536000, 0, 100000000, 0,  1536000,  7000000, 0, 1.080},
+    { 20000000, 0,   768000,  7000000, 0,  20000000, 0,   768000,  7000000, 0, 0.203},
+    { 20000000, 0,   768000,  7000000, 0, 100000000, 0,   768000,  7000000, 0, 1.620},
+    {100000000, 0,   768000,  7000000, 0, 100000000, 0,   768000,  7000000, 0, 3.240},
+    { 20000000, 0,   768000, 13000000, 0,  20000000, 0,  7000000, 13000000, 0, 0.023},
+    { 20000000, 0,   768000, 13000000, 0, 100000000, 0,  7000000, 13000000, 0, 0.180},
+    {100000000, 0,   768000, 13000000, 0, 100000000, 0,  7000000, 13000000, 0, 0.360},
+    { 20000000, 0,  7000000, 13000000, 0,  20000000, 0,   768000, 13000000, 0, 0.023},
+    { 20000000, 0,  7000000, 13000000, 0, 100000000, 0,   768000, 13000000, 0, 0.180},
+    {100000000, 0,  7000000, 13000000, 0, 100000000, 0,   768000, 13000000, 0, 0.360},
+    { 20000000, 0, 13000000, 13000000, 0,  20000000, 0, 13000000, 13000000, 0, 0.003},
+    { 20000000, 0, 13000000, 13000000, 0, 100000000, 0, 13000000, 13000000, 0, 0.020},
+    {100000000, 0, 13000000, 13000000, 0, 100000000, 0, 13000000, 13000000, 0, 0.040}
+};
+
+g1050_model_t g1050_standard_models[9] =
+{
+    {   /* Severity 0 - no impairment */
+        {
+            0,          /*! Percentage likelihood of occurance in scenario A */
+            0,          /*! Percentage likelihood of occurance in scenario B */
+            0,          /*! Percentage likelihood of occurance in scenario C */
+        },
+        {
+            0.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            0.0,        /*! Percentage occupancy */
+            512,        /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            0.0,        /*! Basic delay of the regional backbone, in seconds */
+            0.0,        /*! Basic delay of the intercontinental backbone, in seconds */
+            0.0,        /*! Percentage packet loss of the backbone */
+            0.0,        /*! Maximum jitter of the backbone, in seconds */
+            0.0,        /*! Interval between the backbone route flapping between two paths, in seconds */
+            0.0,        /*! The difference in backbone delay between the two routes we flap between, in seconds */
+            0.0,        /*! The interval between link failures, in seconds */
+            0.0,        /*! The duration of link failures, in seconds */
+            0.0,        /*! Probability of packet loss in the backbone, in percent */
+            0.0         /*! Probability of a packet going out of sequence in the backbone. */
+        },
+        {
+            0.0,        /*! Percentage occupancy */
+            512,        /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            0.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        }
+    },
+    {   /* Severity A */
+        {
+            50,         /*! Percentage likelihood of occurance in scenario A */
+            5,          /*! Percentage likelihood of occurance in scenario B */
+            5,          /*! Percentage likelihood of occurance in scenario C */
+        },
+        {
+            1.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        },
+        {
+            0.0,        /*! Percentage occupancy */
+            512,        /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            0.004,      /*! Basic delay of the regional backbone, in seconds */
+            0.016,      /*! Basic delay of the intercontinental backbone, in seconds */
+            0.0,        /*! Percentage packet loss of the backbone */
+            0.005,      /*! Maximum jitter of the backbone, in seconds */
+            0.0,        /*! Interval between the backbone route flapping between two paths, in seconds */
+            0.0,        /*! The difference in backbone delay between the two routes we flap between, in seconds */
+            0.0,        /*! The interval between link failures, in seconds */
+            0.0,        /*! The duration of link failures, in seconds */
+            0.0,        /*! Probability of packet loss in the backbone, in percent */
+            0.0         /*! Probability of a packet going out of sequence in the backbone. */
+        },
+        {
+            0.0,        /*! Percentage occupancy */
+            512,        /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            1.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        }
+    },
+    {   /* Severity B */
+        {
+            30,         /*! Percentage likelihood of occurance in scenario A */
+            25,         /*! Percentage likelihood of occurance in scenario B */
+            5,          /*! Percentage likelihood of occurance in scenario C */
+        },
+        {
+            2.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        },
+        {
+            1.0,        /*! Percentage occupancy */
+            512,        /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            0.008,      /*! Basic delay of the regional backbone, in seconds */
+            0.032,      /*! Basic delay of the intercontinental backbone, in seconds */
+            0.01,       /*! Percentage packet loss of the backbone */
+            0.01,       /*! Maximum jitter of the backbone, in seconds */
+            3600.0,     /*! Interval between the backbone route flapping between two paths, in seconds */
+            0.002,      /*! The difference in backbone delay between the two routes we flap between, in seconds */
+            3600.0,     /*! The interval between link failures, in seconds */
+            0.064,      /*! The duration of link failures, in seconds */
+            0.0,        /*! Probability of packet loss in the backbone, in percent */
+            0.0         /*! Probability of a packet going out of sequence in the backbone. */
+        },
+        {
+            1.0,        /*! Percentage occupancy */
+            512,        /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            2.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        }
+    },
+    {   /* Severity C */
+        {
+            15,         /*! Percentage likelihood of occurance in scenario A */
+            30,         /*! Percentage likelihood of occurance in scenario B */
+            10,         /*! Percentage likelihood of occurance in scenario C */
+        },
+        {
+            3.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        },
+        {
+            2.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            0.016,      /*! Basic delay of the regional backbone, in seconds */
+            0.064,      /*! Basic delay of the intercontinental backbone, in seconds */
+            0.02,       /*! Percentage packet loss of the backbone */
+            0.016,      /*! Maximum jitter of the backbone, in seconds */
+            1800.0,     /*! Interval between the backbone route flapping between two paths, in seconds */
+            0.004,      /*! The difference in backbone delay between the two routes we flap between, in seconds */
+            1800.0,     /*! The interval between link failures, in seconds */
+            0.128,      /*! The duration of link failures, in seconds */
+            0.0,        /*! Probability of packet loss in the backbone, in percent */
+            0.0         /*! Probability of a packet going out of sequence in the backbone. */
+        },
+        {
+            2.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            3.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        }
+    },
+    {   /* Severity D */
+        {
+            5,          /*! Percentage likelihood of occurance in scenario A */
+            25,         /*! Percentage likelihood of occurance in scenario B */
+            15,         /*! Percentage likelihood of occurance in scenario C */
+        },
+        {
+            5.0,         /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        },
+        {
+            4.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            0.032,      /*! Basic delay of the regional backbone, in seconds */
+            0.128,      /*! Basic delay of the intercontinental backbone, in seconds */
+            0.04,       /*! Percentage packet loss of the backbone */
+            0.04,       /*! Maximum jitter of the backbone, in seconds */
+            900.0,      /*! Interval between the backbone route flapping between two paths, in seconds */
+            0.008,      /*! The difference in backbone delay between the two routes we flap between, in seconds */
+            900.0,      /*! The interval between link failures, in seconds */
+            0.256,      /*! The duration of link failures, in seconds */
+            0.0,        /*! Probability of packet loss in the backbone, in percent */
+            0.0         /*! Probability of a packet going out of sequence in the backbone. */
+        },
+        {
+            4.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            5.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        }
+    },
+    {   /* Severity E */
+        {
+            0,          /*! Percentage likelihood of occurance in scenario A */
+            10,         /*! Percentage likelihood of occurance in scenario B */
+            20,         /*! Percentage likelihood of occurance in scenario C */
+        },
+        {
+            8.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        },
+        {
+            8.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            0.064,      /*! Basic delay of the regional backbone, in seconds */
+            0.196,      /*! Basic delay of the intercontinental backbone, in seconds */
+            0.1,        /*! Percentage packet loss of the backbone */
+            0.07,       /*! Maximum jitter of the backbone, in seconds */
+            480.0,      /*! Interval between the backbone route flapping between two paths, in seconds */
+            0.016,      /*! The difference in backbone delay between the two routes we flap between, in seconds */
+            480.0,      /*! The interval between link failures, in seconds */
+            0.4,        /*! The duration of link failures, in seconds */
+            0.0,        /*! Probability of packet loss in the backbone, in percent */
+            0.0         /*! Probability of a packet going out of sequence in the backbone. */
+        },
+        {
+            8.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            8.0,        /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        }
+    },
+    {   /* Severity F */
+        {
+            0,          /*! Percentage likelihood of occurance in scenario A */
+            0,          /*! Percentage likelihood of occurance in scenario B */
+            25,         /*! Percentage likelihood of occurance in scenario C */
+        },
+        {
+            12.0,       /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        },
+        {
+            15.0,       /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            0.128,      /*! Basic delay of the regional backbone, in seconds */
+            0.256,      /*! Basic delay of the intercontinental backbone, in seconds */
+            0.2,        /*! Percentage packet loss of the backbone */
+            0.1,        /*! Maximum jitter of the backbone, in seconds */
+            240.0,      /*! Interval between the backbone route flapping between two paths, in seconds */
+            0.032,      /*! The difference in backbone delay between the two routes we flap between, in seconds */
+            240.0,      /*! The interval between link failures, in seconds */
+            0.8,        /*! The duration of link failures, in seconds */
+            0.0,        /*! Probability of packet loss in the backbone, in percent */
+            0.0         /*! Probability of a packet going out of sequence in the backbone. */
+        },
+        {
+            15.0,       /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            12.0,       /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        }
+    },
+    {   /* Severity G */
+        {
+            0,          /*! Percentage likelihood of occurance in scenario A */
+            0,          /*! Percentage likelihood of occurance in scenario B */
+            15,         /*! Percentage likelihood of occurance in scenario C */
+        },
+        {
+            16.0,       /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        },
+        {
+            30.0,       /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            0.256,      /*! Basic delay of the regional backbone, in seconds */
+            0.512,      /*! Basic delay of the intercontinental backbone, in seconds */
+            0.5,        /*! Percentage packet loss of the backbone */
+            0.15,       /*! Maximum jitter of the backbone, in seconds */
+            120.0,      /*! Interval between the backbone route flapping between two paths, in seconds */
+            0.064,      /*! The difference in backbone delay between the two routes we flap between, in seconds */
+            120.0,      /*! The interval between link failures, in seconds */
+            1.6,        /*! The duration of link failures, in seconds */
+            0.0,        /*! Probability of packet loss in the backbone, in percent */
+            0.0         /*! Probability of a packet going out of sequence in the backbone. */
+        },
+        {
+            30.0,       /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            16.0,       /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        }
+    },
+    {   /* Severity H */
+        {
+            0,          /*! Percentage likelihood of occurance in scenario A */
+            0,          /*! Percentage likelihood of occurance in scenario B */
+            5,          /*! Percentage likelihood of occurance in scenario C */
+        },
+        {
+            20.0,       /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        },
+        {
+            50.0,       /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            0.512,      /*! Basic delay of the regional backbone, in seconds */
+            0.768,      /*! Basic delay of the intercontinental backbone, in seconds */
+            1.0,        /*! Percentage packet loss of the backbone */
+            0.5,        /*! Maximum jitter of the backbone, in seconds */
+            60.0,       /*! Interval between the backbone route flapping between two paths, in seconds */
+            0.128,      /*! The difference in backbone delay between the two routes we flap between, in seconds */
+            60.0,       /*! The interval between link failures, in seconds */
+            3.0,        /*! The duration of link failures, in seconds */
+            1.0,        /*! Probability of packet loss in the backbone, in percent */
+            1.0         /*! Probability of a packet going out of sequence in the backbone. */
+        },
+        {
+            50.0,       /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0         /*! Peak jitter */
+        },
+        {
+            20.0,       /*! Percentage occupancy */
+            1508,       /*! MTU */
+            0.0015      /*! Peak jitter */
+        }
+    }
+};
+
+#if defined(HAVE_DRAND48)
+static __inline__ void q1050_rand_init(void)
+{
+    srand48(time(NULL));
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ double q1050_rand(void)
+{
+    return drand48();
+}
+/*- End of function --------------------------------------------------------*/
+#else
+static __inline__ void q1050_rand_init(void)
+{
+    srand(time(NULL));
+}
+/*- End of function --------------------------------------------------------*/
+
+static __inline__ double q1050_rand(void)
+{
+    return (double) rand()/(double) RAND_MAX;
+}
+/*- End of function --------------------------------------------------------*/
+#endif
+
+static __inline__ double scale_probability(double prob, double scale)
+{
+    /* Re-calculate probability based on a different time interval */
+    return 1.0 - pow(1.0 - prob, scale);
+}
+/*- End of function --------------------------------------------------------*/
+
+static void g1050_segment_init(g1050_segment_state_t *s,
+                               int link_type,
+                               g1050_segment_constants_t *constants,
+                               g1050_segment_model_t *parms,
+                               int bit_rate,
+                               int multiple_access,
+                               int qos_enabled,
+                               int packet_size,
+                               int packet_rate)
+{
+    double x;
+    double packet_interval;
+
+    memset(s, 0, sizeof(*s));
+
+    packet_interval = 1000.0/packet_rate;
+    /* Some calculatons are common to both LAN and access links, and those that are not. */
+    s->link_type = link_type;
+    s->prob_loss_rate_change[0] = scale_probability(constants->prob_loss_rate_change[0]*parms->percentage_occupancy, 1.0/packet_interval);
+
+    s->serial_delay = packet_size*8.0/bit_rate;
+    if (link_type == G1050_LAN_LINK)
+    {
+        s->prob_loss_rate_change[1] = scale_probability(constants->prob_loss_rate_change[1], 1.0/packet_interval);
+        s->prob_impulse[0] = constants->prob_impulse[0][0];
+        s->prob_impulse[1] = constants->prob_impulse[1][0];
+        s->impulse_coeff = constants->impulse_coeff;
+        s->impulse_height = parms->mtu*(8.0/bit_rate)*(1.0 + parms->percentage_occupancy/constants->impulse_height);
+    }
+    else if (link_type == G1050_ACCESS_LINK)
+    {
+        s->prob_loss_rate_change[1] = scale_probability(constants->prob_loss_rate_change[1]/(1.0 + parms->percentage_occupancy), 1.0/packet_interval);
+        s->prob_impulse[0] = scale_probability(constants->prob_impulse[0][0] + (parms->percentage_occupancy/2000.0), 1.0/packet_interval);
+        s->prob_impulse[1] = scale_probability(constants->prob_impulse[1][0] + (constants->prob_impulse[1][1]*parms->percentage_occupancy/100.0), 1.0/packet_interval);
+        s->impulse_coeff = 1.0 - scale_probability(1.0 - constants->impulse_coeff, 1.0/packet_interval);
+        x = (1.0 - constants->impulse_coeff)/(1.0 - s->impulse_coeff);
+        s->impulse_height = x*parms->mtu*(8.0/bit_rate)*(1.0 + parms->percentage_occupancy/constants->impulse_height);
+    }
+
+    /* The following are calculated the same way for LAN and access links */
+    s->prob_packet_loss = constants->prob_packet_loss*parms->percentage_occupancy;
+    s->qos_enabled = qos_enabled;
+    s->multiple_access = multiple_access;
+    s->prob_packet_collision_loss = constants->prob_packet_collision_loss;
+    s->max_jitter = parms->max_jitter;
+
+    /* The following is common state information to all links. */
+    s->high_loss = FALSE;
+    s->congestion_delay = 0.0;
+    s->last_arrival_time = 0.0;
+
+    /* Count of packets lost in this segment. */
+    s->lost_packets = 0;
+    s->lost_packets_2 = 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void g1050_core_init(g1050_core_state_t *s, g1050_core_model_t *parms, int packet_rate)
+{
+    memset(s, 0, sizeof(*s));
+
+    /* Set up route flapping. */
+    /* This is the length of the period of both the delayed duration and the non-delayed. */
+    s->route_flap_interval = parms->route_flap_interval*G1050_TICKS_PER_SEC;
+
+    /* How much additional delay is added or subtracted during route flaps. */
+    s->route_flap_delta = parms->route_flap_delay;
+
+    /* Current tick count. This is initialized so that we are part way into the first
+       CLEAN interval before the first change occurs. This is a random portion of the
+       period. When we reach the first flap, the flapping in both directions becomes
+       periodic. */
+    s->route_flap_counter = s->route_flap_interval - 99 - floor(s->route_flap_interval*q1050_rand());
+    s->link_failure_interval_ticks = parms->link_failure_interval*G1050_TICKS_PER_SEC;
+
+    /* Link failures occur when the count reaches this number of ticks. */
+    /* Duration of a failure. */
+    s->link_failure_duration_ticks = floor((G1050_TICKS_PER_SEC*parms->link_failure_duration));
+    /* How far into the first CLEAN interval we are. This is like the route flap initialzation. */
+    s->link_failure_counter = s->link_failure_interval_ticks - 99 - floor(s->link_failure_interval_ticks*q1050_rand());
+    s->link_recovery_counter = s->link_failure_duration_ticks;
+    
+    s->base_delay = parms->base_regional_delay;
+    s->max_jitter = parms->max_jitter;
+    s->prob_packet_loss = parms->prob_packet_loss/100.0;
+    s->prob_oos = parms->prob_oos/100.0;
+    s->last_arrival_time = 0.0;
+    s->delay_delta = 0;
+
+    /* Count of packets lost in this segment. */
+    s->lost_packets = 0;
+    s->lost_packets_2 = 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void g1050_segment_model(g1050_segment_state_t *s, double delays[], int len)
+{
+    int i;
+    int lose;
+    int was_high_loss;
+    double impulse;
+    double slice_delay;
+
+    /* Compute delay and loss value for each time slice. */
+    for (i = 0;  i < len;  i++)
+    {
+        lose = FALSE;
+        /* Initialize delay to the serial delay plus some jitter. */
+        slice_delay = s->serial_delay + s->max_jitter*q1050_rand();
+        /* If no QoS, do congestion delay and packet loss analysis. */
+        if (!s->qos_enabled)
+        {
+            /* To match the logic in G.1050 we need to record the current loss state, before
+               checking if we should change. */
+            was_high_loss = s->high_loss;
+            /* Toggle between the low-loss and high-loss states, based on the transition probability. */
+            if (q1050_rand() < s->prob_loss_rate_change[was_high_loss])
+                s->high_loss = !s->high_loss;
+            impulse = 0.0;
+            if (q1050_rand() < s->prob_impulse[was_high_loss])
+            {
+                impulse = s->impulse_height;
+                if (!was_high_loss  ||  s->link_type == G1050_LAN_LINK)
+                    impulse *= q1050_rand();
+            }
+
+            if (was_high_loss  &&  q1050_rand() < s->prob_packet_loss)
+                lose = TRUE;
+            /* Single pole LPF for the congestion delay impulses. */
+            s->congestion_delay = s->congestion_delay*s->impulse_coeff + impulse*(1.0 - s->impulse_coeff);
+            slice_delay += s->congestion_delay;
+        }
+        /* If duplex mismatch on LAN, packet loss based on loss probability. */
+        if (s->multiple_access  &&  (q1050_rand() < s->prob_packet_collision_loss))
+            lose = TRUE;
+        /* Put computed delay into time slice array. */
+        if (lose)
+        {
+            delays[i] = PACKET_LOSS_TIME;
+            s->lost_packets++;
+        }
+        else
+        {
+            delays[i] = slice_delay;
+        }
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
+static void g1050_core_model(g1050_core_state_t *s, double delays[], int len)
+{
+    int32_t i;
+    int lose;
+    double jitter_delay;
+
+    for (i = 0;  i < len;  i++)
+    {
+        lose = FALSE;
+        jitter_delay = s->base_delay + s->max_jitter*q1050_rand();
+        /* Route flapping */
+        if (--s->route_flap_counter <= 0)
+        {
+            /* Route changed */
+            s->delay_delta = s->route_flap_delta - s->delay_delta;
+            s->route_flap_counter = s->route_flap_interval;
+        }
+        if (q1050_rand() < s->prob_packet_loss)
+            lose = TRUE;
+        /* Link failures */
+        if (--s->link_failure_counter <= 0)
+        {
+            /* We are in a link failure */
+            lose = TRUE;
+            if (--s->link_recovery_counter <= 0)
+            {
+                /* Leave failure state. */
+                s->link_failure_counter = s->link_failure_interval_ticks;
+                s->link_recovery_counter = s->link_failure_duration_ticks;
+                lose = FALSE;
+            }
+        }
+        if (lose)
+        {
+            delays[i] = PACKET_LOSS_TIME;
+            s->lost_packets++;
+        }
+        else
+        {
+            delays[i] = jitter_delay + s->delay_delta;
+        }
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
+static int g1050_segment_delay(g1050_segment_state_t *s,
+                               double base_time,
+                               double arrival_times[],
+                               double delays[],
+                               int num_packets)
+{
+    int i;
+    int32_t departure_time;
+    int lost_packets;
+
+    /* Add appropriate delays to the packets for the segments before the core. */
+    lost_packets = 0;
+    for (i = 0;  i < num_packets;  i++)
+    {
+        /* Apply half a millisecond of rounding, as we working in millisecond steps. */
+        departure_time = (arrival_times[i] + 0.0005 - base_time)*G1050_TICKS_PER_SEC;
+        if (arrival_times[i] == PACKET_LOSS_TIME)
+        {
+            /* Lost already */
+        }
+        else if (delays[departure_time] == PACKET_LOSS_TIME)
+        {
+            arrival_times[i] = PACKET_LOSS_TIME;
+            lost_packets++;
+        }
+        else
+        {
+            arrival_times[i] += delays[departure_time];
+            if (arrival_times[i] < s->last_arrival_time)
+                arrival_times[i] = s->last_arrival_time;
+            else
+                s->last_arrival_time = arrival_times[i];
+        }
+    }
+    return lost_packets;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int g1050_segment_delay_preserve_order(g1050_segment_state_t *s,
+                                              double base_time,
+                                              double arrival_times_a[],
+                                              double arrival_times_b[],
+                                              double delays[],
+                                              int num_packets)
+{
+    int i;
+    int j;
+    int departure_time;
+    double last_arrival_time;
+    double last_arrival_time_temp;
+    int lost_packets;
+
+    /* Add appropriate delays to the packets for the segments after the core. */
+    last_arrival_time = 0.0;
+    last_arrival_time_temp = 0.0;
+    lost_packets = 0;
+    for (i = 0;  i < num_packets;  i++)
+    {
+        /* We need to preserve the order that came out of the core, so we
+           use an alternate array for the results.  */
+        /* Apply half a millisecond of rounding, as we working in millisecond steps. */
+        departure_time = (arrival_times_a[i] + 0.0005 - base_time)*G1050_TICKS_PER_SEC;
+        if (arrival_times_a[i] == PACKET_LOSS_TIME)
+        {
+            /* Lost already */
+            arrival_times_b[i] = PACKET_LOSS_TIME;
+        }
+        else if (delays[departure_time] == PACKET_LOSS_TIME)
+        {
+            arrival_times_b[i] = PACKET_LOSS_TIME;
+            lost_packets++;
+        }
+        else
+        {
+            arrival_times_b[i] = arrival_times_a[i] + delays[departure_time];
+            if (arrival_times_a[i] < last_arrival_time)
+            {
+                /* If a legitimate out of sequence packet is detected, search
+                   back a fixed amount of time to preserve order. */
+                for (j = i - 1;  j >= 0;  j--)
+                {
+                    if ((arrival_times_a[j] != PACKET_LOSS_TIME)
+                        &&
+                        (arrival_times_b[j] != PACKET_LOSS_TIME))
+                    {
+                        if ((arrival_times_a[i] - arrival_times_a[j]) > SEARCHBACK_PERIOD)
+                            break;
+                        if ((arrival_times_a[j] > arrival_times_a[i])
+                            &&
+                            (arrival_times_b[j] < arrival_times_b[i]))
+                        {
+                            arrival_times_b[j] = arrival_times_b[i];
+                        }
+                    }
+                }
+            }
+            else
+            {
+                last_arrival_time = arrival_times_a[i];
+                if (arrival_times_b[i] < last_arrival_time_temp)
+                    arrival_times_b[i] = last_arrival_time_temp;
+                else
+                    last_arrival_time_temp = arrival_times_b[i];
+            }
+        }
+    }
+    return lost_packets;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int g1050_core_delay(g1050_core_state_t *s,
+                            double base_time,
+                            double arrival_times[],
+                            double delays[],
+                            int num_packets)
+{
+    int i;
+    int departure_time;
+    int lost_packets;
+
+    /* This element does NOT preserve packet order. */
+    lost_packets = 0;
+    for (i = 0;  i < num_packets;  i++)
+    {
+        /* Apply half a millisecond of rounding, as we working in millisecond steps. */
+        departure_time = (arrival_times[i] + 0.0005 - base_time)*G1050_TICKS_PER_SEC;
+        if (arrival_times[i] == PACKET_LOSS_TIME)
+        {
+            /* Lost already */
+        }
+        else if (delays[departure_time] == PACKET_LOSS_TIME)
+        {
+            arrival_times[i] = PACKET_LOSS_TIME;
+            lost_packets++;
+        }
+        else
+        {
+            /* Not lost. Compute arrival time. */
+            arrival_times[i] += delays[departure_time];
+            if (arrival_times[i] < s->last_arrival_time)
+            {
+                /* This packet is EARLIER than the last one. It is out of order! */
+                /* Do we allow it to stay out of order? */
+                if (q1050_rand() >= s->prob_oos)
+                    arrival_times[i] = s->last_arrival_time;
+            }
+            else
+            {
+                /* Packet is in the correct order, relative to the last one. */
+                s->last_arrival_time = arrival_times[i];
+            }
+        }
+    }
+    return lost_packets;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void g1050_simulate_chunk(g1050_state_t *s)
+{
+    int i;
+    
+    s->base_time += 1.0;
+
+    memcpy(&s->segment[0].delays[0], &s->segment[0].delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->segment[0].delays[0]));
+    g1050_segment_model(&s->segment[0], &s->segment[0].delays[2*G1050_TICKS_PER_SEC], G1050_TICKS_PER_SEC);
+
+    memcpy(&s->segment[1].delays[0], &s->segment[1].delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->segment[1].delays[0]));
+    g1050_segment_model(&s->segment[1], &s->segment[1].delays[2*G1050_TICKS_PER_SEC], G1050_TICKS_PER_SEC);
+
+    memcpy(&s->core.delays[0], &s->core.delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->core.delays[0]));
+    g1050_core_model(&s->core, &s->core.delays[2*G1050_TICKS_PER_SEC], G1050_TICKS_PER_SEC);
+
+    memcpy(&s->segment[2].delays[0], &s->segment[2].delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->segment[2].delays[0]));
+    g1050_segment_model(&s->segment[2], &s->segment[2].delays[2*G1050_TICKS_PER_SEC], G1050_TICKS_PER_SEC);
+
+    memcpy(&s->segment[3].delays[0], &s->segment[3].delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->segment[3].delays[0]));
+    g1050_segment_model(&s->segment[3], &s->segment[3].delays[2*G1050_TICKS_PER_SEC], G1050_TICKS_PER_SEC);
+
+    memcpy(&s->arrival_times_1[0], &s->arrival_times_1[s->packet_rate], 2*s->packet_rate*sizeof(s->arrival_times_1[0]));
+    memcpy(&s->arrival_times_2[0], &s->arrival_times_2[s->packet_rate], 2*s->packet_rate*sizeof(s->arrival_times_2[0]));
+    for (i = 0;  i < s->packet_rate;  i++)
+    {
+        s->arrival_times_1[2*s->packet_rate + i] = s->base_time + 2.0 + (double) i/(double) s->packet_rate;
+        s->arrival_times_2[2*s->packet_rate + i] = 0.0;
+    }
+
+    s->segment[0].lost_packets_2 += g1050_segment_delay(&s->segment[0], s->base_time, s->arrival_times_1, s->segment[0].delays, s->packet_rate);
+    s->segment[1].lost_packets_2 += g1050_segment_delay(&s->segment[1], s->base_time, s->arrival_times_1, s->segment[1].delays, s->packet_rate);
+    s->core.lost_packets_2 += g1050_core_delay(&s->core, s->base_time, s->arrival_times_1, s->core.delays, s->packet_rate);
+    s->segment[2].lost_packets_2 += g1050_segment_delay_preserve_order(&s->segment[2], s->base_time, s->arrival_times_1, s->arrival_times_2, s->segment[2].delays, s->packet_rate);
+    s->segment[3].lost_packets_2 += g1050_segment_delay_preserve_order(&s->segment[3], s->base_time, s->arrival_times_2, s->arrival_times_1, s->segment[3].delays, s->packet_rate);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(g1050_state_t *) g1050_init(int model,
+                                         int speed_pattern,
+                                         int packet_size,
+                                         int packet_rate)
+{
+    g1050_state_t *s;
+    g1050_constants_t *constants;
+    g1050_channel_speeds_t *sp;
+    g1050_model_t *mo;
+    int i;
+
+    /* If the random generator has not been seeded it might give endless
+       zeroes - it depends on the platform. */
+    for (i = 0;  i < 10;  i++)
+    {
+        if (q1050_rand() != 0.0)
+            break;
+    }
+    if (i >= 10)
+        q1050_rand_init();
+    if ((s = (g1050_state_t *) malloc(sizeof(*s))) == NULL)
+        return NULL;
+    memset(s, 0, sizeof(*s));
+
+    constants = &g1050_constants[0];
+    sp = &g1050_speed_patterns[speed_pattern - 1];
+    mo = &g1050_standard_models[model];
+
+    memset(s, 0, sizeof(*s));
+    
+    s->packet_rate = packet_rate;
+    s->packet_size = packet_size;
+
+    g1050_segment_init(&s->segment[0],
+                       G1050_LAN_LINK,
+                       &constants->segment[0],
+                       &mo->sidea_lan,
+                       sp->sidea_lan_bit_rate,
+                       sp->sidea_lan_multiple_access,
+                       FALSE,
+                       packet_size,
+                       packet_rate);
+    g1050_segment_init(&s->segment[1],
+                       G1050_ACCESS_LINK,
+                       &constants->segment[1],
+                       &mo->sidea_access_link,
+                       sp->sidea_access_link_bit_rate_ab,
+                       FALSE,
+                       sp->sidea_access_link_qos_enabled,
+                       packet_size,
+                       packet_rate);
+    g1050_core_init(&s->core, &mo->core, packet_rate);
+    g1050_segment_init(&s->segment[2],
+                       G1050_ACCESS_LINK,
+                       &constants->segment[2],
+                       &mo->sideb_access_link,
+                       sp->sideb_access_link_bit_rate_ba,
+                       FALSE,
+                       sp->sideb_access_link_qos_enabled,
+                       packet_size,
+                       packet_rate);
+    g1050_segment_init(&s->segment[3],
+                       G1050_LAN_LINK,
+                       &constants->segment[3],
+                       &mo->sideb_lan,
+                       sp->sideb_lan_bit_rate,
+                       sp->sideb_lan_multiple_access,
+                       FALSE,
+                       packet_size,
+                       packet_rate);
+
+    s->base_time = 0.0;
+    /* Start with enough of the future modelled to allow for the worst jitter.
+       After this we will always keep at least 2 seconds of the future modelled. */
+    g1050_segment_model(&s->segment[0], s->segment[0].delays, 3*G1050_TICKS_PER_SEC);
+    g1050_segment_model(&s->segment[1], s->segment[1].delays, 3*G1050_TICKS_PER_SEC);
+    g1050_core_model(&s->core, s->core.delays, 3*G1050_TICKS_PER_SEC);
+    g1050_segment_model(&s->segment[2], s->segment[2].delays, 3*G1050_TICKS_PER_SEC);
+    g1050_segment_model(&s->segment[3], s->segment[3].delays, 3*G1050_TICKS_PER_SEC);
+
+    /* Initialise the arrival times to the departure times */
+    for (i = 0;  i < 3*s->packet_rate;  i++)
+    {
+        s->arrival_times_1[i] = s->base_time + (double) i/(double)s->packet_rate;
+        s->arrival_times_2[i] = 0.0;
+    }
+
+    s->segment[0].lost_packets_2 += g1050_segment_delay(&s->segment[0], s->base_time, s->arrival_times_1, s->segment[0].delays, s->packet_rate);
+    s->segment[1].lost_packets_2 += g1050_segment_delay(&s->segment[1], s->base_time, s->arrival_times_1, s->segment[1].delays, s->packet_rate);
+    s->core.lost_packets_2 += g1050_core_delay(&s->core, s->base_time, s->arrival_times_1, s->core.delays, s->packet_rate);
+    s->segment[2].lost_packets_2 += g1050_segment_delay_preserve_order(&s->segment[2], s->base_time, s->arrival_times_1, s->arrival_times_2, s->segment[2].delays, s->packet_rate);
+    s->segment[3].lost_packets_2 += g1050_segment_delay_preserve_order(&s->segment[3], s->base_time, s->arrival_times_2, s->arrival_times_1, s->segment[3].delays, s->packet_rate);
+
+    s->first = NULL;
+    s->last = NULL;
+    return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(void) g1050_dump_parms(int model, int speed_pattern)
+{
+    g1050_channel_speeds_t *sp;
+    g1050_model_t *mo;
+    
+    sp = &g1050_speed_patterns[speed_pattern - 1];
+    mo = &g1050_standard_models[model];
+
+    printf("Model %d%c\n", speed_pattern, 'A' + model - 1);
+    printf("LOO %.6f%% %.6f%% %.6f%%\n", mo->loo[0]*sp->loo/100.0, mo->loo[1]*sp->loo/100.0, mo->loo[2]*sp->loo/100.0);
+    printf("Side A LAN %dbps, %.3f%% occupancy, MTU %d, %s MA\n", sp->sidea_lan_bit_rate, mo->sidea_lan.percentage_occupancy, mo->sidea_lan.mtu, (sp->sidea_lan_multiple_access)  ?  ""  :  "no");
+    printf("Side A access %dbps, %.3f%% occupancy, MTU %d, %s QoS\n", sp->sidea_access_link_bit_rate_ab, mo->sidea_access_link.percentage_occupancy, mo->sidea_access_link.mtu, (sp->sidea_access_link_qos_enabled)  ?  ""  :  "no");
+    printf("Core delay %.4fs (%.4fs), peak jitter %.4fs, prob loss %.4f%%, prob OOS %.4f%%\n", mo->core.base_regional_delay, mo->core.base_intercontinental_delay, mo->core.max_jitter, mo->core.prob_packet_loss, mo->core.prob_oos);
+    printf("     Route flap interval %.4fs, delay change %.4fs\n", mo->core.route_flap_interval, mo->core.route_flap_delay);
+    printf("     Link failure interval %.4fs, duration %.4fs\n", mo->core.link_failure_interval, mo->core.link_failure_duration);
+    printf("Side B access %dbps, %.3f%% occupancy, MTU %d, %s QoS\n", sp->sideb_access_link_bit_rate_ba, mo->sideb_access_link.percentage_occupancy, mo->sideb_access_link.mtu, (sp->sideb_access_link_qos_enabled)  ?  ""  :  "no");
+    printf("Side B LAN %dbps, %.3f%% occupancy, MTU %d, %s MA\n", sp->sideb_lan_bit_rate, mo->sideb_lan.percentage_occupancy, mo->sideb_lan.mtu, (sp->sideb_lan_multiple_access)  ?  ""  :  "no");
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) g1050_put(g1050_state_t *s, const uint8_t buf[], int len, int seq_no, double departure_time)
+{
+    g1050_queue_element_t *element;
+    g1050_queue_element_t *e;
+    double arrival_time;
+
+    while (departure_time >= s->base_time + 1.0)
+        g1050_simulate_chunk(s);
+    arrival_time = s->arrival_times_1[(int) ((departure_time - s->base_time)*(double) s->packet_rate + 0.5)];
+    if (arrival_time < 0)
+    {
+        /* This packet is lost */
+        return 0;
+    }
+    if ((element = (g1050_queue_element_t *) malloc(sizeof(*element) + len)) == NULL)
+        return -1;
+    element->next = NULL;
+    element->prev = NULL;
+    element->seq_no = seq_no;
+    element->departure_time = departure_time;
+    element->arrival_time = arrival_time;
+    element->len = len;
+    memcpy(element->pkt, buf, len);
+    /* Add it to the queue, in order */
+    if (s->last == NULL)
+    {
+        /* The queue is empty */
+        s->first =
+        s->last = element;
+    }
+    else
+    {
+        for (e = s->last;  e;  e = e->prev)
+        {
+            if (e->arrival_time <= arrival_time)
+                break;
+        }
+        if (e)
+        {
+            element->next = e->next; 
+            element->prev = e; 
+            e->next = element;
+        }
+        else
+        {
+            element->next = s->first;
+            s->first = element;
+        }
+        if (element->next)
+            element->next->prev = element;
+        else
+            s->last = element;
+    }
+    //printf(">> Seq %d, departs %f, arrives %f\n", seq_no, departure_time, arrival_time);
+    return len;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) g1050_get(g1050_state_t *s, uint8_t buf[], int max_len, double current_time, int *seq_no, double *departure_time, double *arrival_time)
+{
+    int len;
+    g1050_queue_element_t *element;
+
+    element = s->first;
+    if (element == NULL)
+    {
+        if (seq_no)
+            *seq_no = -1;
+        if (departure_time)
+            *departure_time = -1;
+        if (arrival_time)
+            *arrival_time = -1;
+        return -1;
+    }
+    if (element->arrival_time > current_time)
+    {
+        if (seq_no)
+            *seq_no = element->seq_no;
+        if (departure_time)
+            *departure_time = element->departure_time;
+        if (arrival_time)
+            *arrival_time = element->arrival_time;
+        return -1;
+    }
+    /* Return the first packet in the queue */
+    len = element->len;
+    memcpy(buf, element->pkt, len);
+    if (seq_no)
+        *seq_no = element->seq_no;
+    if (departure_time)
+        *departure_time = element->departure_time;
+    if (arrival_time)
+        *arrival_time = element->arrival_time;
+    //printf("<< Seq %d, arrives %f (%f)\n", element->seq_no, element->arrival_time, current_time);
+
+    /* Remove it from the queue */
+    if (s->first == s->last)
+        s->last = NULL;
+    s->first = element->next;
+    if (element->next)
+        element->next->prev = NULL;
+    free(element);
+    return len;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(void) g1050_queue_dump(g1050_state_t *s)
+{
+    g1050_queue_element_t *e;
+
+    printf("Queue scanned forewards\n");
+    for (e = s->first;  e;  e = e->next)
+        printf("Seq %5d, arrival %10.4f, len %3d\n", e->seq_no, e->arrival_time, e->len);
+    printf("Queue scanned backwards\n");
+    for (e = s->last;  e;  e = e->prev)
+        printf("Seq %5d, arrival %10.4f, len %3d\n", e->seq_no, e->arrival_time, e->len);
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.