Merge remote branch 'repo/master' into stats
authorBen Pfaff <blp@cs.stanford.edu>
Tue, 15 Apr 2008 16:57:38 +0000 (09:57 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Tue, 15 Apr 2008 16:57:38 +0000 (09:57 -0700)
Conflicts:

datapath/table-mac.c

31 files changed:
ChangeLog
README
configure.ac
datapath/Makefile.am
datapath/chain.c
datapath/datapath.c
datapath/forward.c
datapath/forward.h
datapath/linux-2.4/Makefile.in
datapath/linux-2.4/compat-2.4/compat24.c
datapath/linux-2.4/compat-2.4/genetlink.c
datapath/linux-2.4/compat-2.4/include-arm/asm/atomic.h
datapath/linux-2.4/compat-2.4/include-mips/asm/atomic.h
datapath/linux-2.4/compat-2.4/include-mips/asm/barrier.h
datapath/linux-2.4/compat-2.4/include-mips/asm/break.h [new file with mode: 0644]
datapath/linux-2.4/compat-2.4/include-mips/asm/page.h [new file with mode: 0644]
datapath/linux-2.4/compat-2.4/include-mips/asm/system.h
datapath/linux-2.4/compat-2.4/include/linux/delay.h
datapath/linux-2.4/compat-2.4/include/linux/llc.h [new file with mode: 0644]
datapath/linux-2.4/compat-2.4/include/linux/module.h
datapath/linux-2.4/compat-2.4/random32.c
datapath/linux-2.6/Makefile.in
datapath/table-mac.c [deleted file]
datapath/table.h
datapath/table_t.c
datapath/unit-exports.c
datapath/unit.c
include/netlink.h
include/openflow-netlink.h
include/openflow.h
lib/netlink.c

index 056f51a..97aa447 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+v0.2.2 - 13 Apr 2008
+--------------------
+    - Removed MAC tables
+    - Various bug fixes and tweaks
+
 v0.2.1 - 28 Mar 2008
 --------------------
     - Fixed build problem when SSL enabled
diff --git a/README b/README
index d5fa422..3031bfe 100644 (file)
--- a/README
+++ b/README
@@ -52,7 +52,7 @@ This distribution includes some additional software as well:
           OpenFlow switches, commanding them to act as regular MAC
           learning switches.
 
-        - vlogconf, a utility that can adjust the logging levels of a
+       - vlogconf, a utility that can adjust the logging levels of a
           running secchan or controller.
 
        - ofp-pki, a utility for creating and managing the public-key
index d86e553..581157e 100644 (file)
@@ -4,6 +4,7 @@ AM_INIT_AUTOMAKE
 
 AC_PROG_CC
 AC_PROG_CPP
+AC_PROG_LD
 
 AC_USE_SYSTEM_EXTENSIONS
 
@@ -27,7 +28,8 @@ CHECK_LINUX(l24, 2.4, 2.4, KSRC24, L24_ENABLED)
 AC_CHECK_HEADER([linux/netlink.h],
                 [HAVE_NETLINK=yes],
                 [HAVE_NETLINK=no],
-                [#include <sys/socket.h>])
+                [#include <sys/socket.h>
+#include <linux/types.h>])
 AM_CONDITIONAL([HAVE_NETLINK], [test "$HAVE_NETLINK" = yes])
 if test "$HAVE_NETLINK" = yes; then
    AC_DEFINE([HAVE_NETLINK], [1],
index 3dda217..64c5077 100644 (file)
@@ -8,7 +8,7 @@ endif
 
 EXTRA_DIST = linux-2.6 linux-2.4\
                        datapath.c snap.h chain.c  crc32.c  crc_t.c\
-                       flow.h forward.h table-hash.c table-mac.c\
+                       flow.h forward.h table-hash.c\
             unit.c unit.h datapath.h  chain.h  crc32.h\
             flow.c  forward.c  forward_t.c table.h\
             table-linear.c  table_t.c    unit-exports.c\
index 2f8708e..6d3784c 100644 (file)
@@ -35,9 +35,7 @@ struct sw_chain *chain_create(struct datapath *dp)
                return NULL;
        chain->dp = dp;
 
-       if (add_table(chain, table_mac_create(TABLE_MAC_NUM_BUCKETS, 
-                                               TABLE_MAC_MAX_FLOWS))
-               || add_table(chain, table_hash2_create(0x1EDC6F41, TABLE_HASH_MAX_FLOWS,
+       if (add_table(chain, table_hash2_create(0x1EDC6F41, TABLE_HASH_MAX_FLOWS,
                                                0x741B8CD7, TABLE_HASH_MAX_FLOWS))
                || add_table(chain, table_linear_create(TABLE_LINEAR_MAX_FLOWS))) {
                chain_destroy(chain);
index 0a266cb..639a483 100644 (file)
@@ -6,6 +6,7 @@
 
 /* Functions for managing the dp interface/device. */
 
+#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/if_arp.h>
 #include <linux/if_bridge.h>
@@ -531,7 +532,19 @@ int dp_output_port(struct datapath *dp, struct sk_buff *skb, int out_port)
        else if (out_port == OFPP_CONTROLLER)
                return dp_output_control(dp, skb, fwd_save_skb(skb), 0,
                                                  OFPR_ACTION);
-       else if (out_port >= OFPP_MAX)
+       else if (out_port == OFPP_TABLE) {
+               struct sw_flow_key key;
+               struct sw_flow *flow;
+
+               flow_extract(skb, skb->dev->br_port->port_no, &key);
+               flow = chain_lookup(dp->chain, &key);
+               if (likely(flow != NULL)) {
+                       flow_used(flow, skb);
+                       execute_actions(dp, skb, &key, flow->actions, flow->n_actions);
+                       return 0;
+               }
+               return -ESRCH;
+       } else if (out_port >= OFPP_MAX)
                goto bad_port;
 
        p = dp->ports[out_port];
index ced0cac..7e987e3 100644 (file)
@@ -21,9 +21,6 @@
 
 /* FIXME: do we need to use GFP_ATOMIC everywhere here? */
 
-static void execute_actions(struct datapath *, struct sk_buff *,
-                               const struct sw_flow_key *,
-                               const struct ofp_action *, int n_actions);
 static int make_writable(struct sk_buff **);
 
 static struct sk_buff *retrieve_skb(uint32_t id);
@@ -60,7 +57,7 @@ static int do_output(struct datapath *dp, struct sk_buff *skb, size_t max_len,
                                         max_len, OFPR_ACTION));
 }
 
-static void execute_actions(struct datapath *dp, struct sk_buff *skb,
+void execute_actions(struct datapath *dp, struct sk_buff *skb,
                                const struct sw_flow_key *key,
                                const struct ofp_action *actions, int n_actions)
 {
@@ -346,6 +343,7 @@ static int
 add_flow(struct sw_chain *chain, const struct ofp_flow_mod *ofm)
 {
        int error = -ENOMEM;
+       int i;
        int n_acts;
        struct sw_flow *flow;
 
@@ -357,6 +355,19 @@ add_flow(struct sw_chain *chain, const struct ofp_flow_mod *ofm)
                goto error;
        }
 
+       /* To prevent loops, make sure there's no action to send to the
+        * OFP_TABLE virtual port.
+        */
+       for (i=0; i<n_acts; i++) {
+               const struct ofp_action *a = &ofm->actions[i];
+
+               if (a->type == htons(OFPAT_OUTPUT) 
+                                       && a->arg.output.port == htons(OFPP_TABLE)) {
+                       /* xxx Send fancy new error message? */
+                       goto error;
+               }
+       }
+
        /* Allocate memory. */
        flow = flow_alloc(n_acts, GFP_ATOMIC);
        if (flow == NULL)
index 3e7686f..ce4d3b1 100644 (file)
@@ -2,6 +2,7 @@
 #define FORWARD_H 1
 
 #include <linux/types.h>
+#include "datapath.h"
 #include "flow.h"
 
 struct sk_buff;
@@ -29,6 +30,9 @@ uint32_t fwd_save_skb(struct sk_buff *skb);
 
 void fwd_exit(void);
 
+void execute_actions(struct datapath *, struct sk_buff *,
+                       const struct sw_flow_key *, 
+                       const struct ofp_action *, int n_actions);
 struct sk_buff *execute_setter(struct sk_buff *, uint16_t,
                        const struct sw_flow_key *, const struct ofp_action *);
 
index 8e4ba5b..25a53b3 100644 (file)
@@ -6,7 +6,7 @@ export KVERSION = 2.4
 export VMDIR = @VMDIR@
 
 SHAREDFILES = ../chain.c ../crc32.c ../table-hash.c ../table-linear.c  \
-              ../table-mac.c ../forward.c ../flow.c ../unit-exports.c  \
+              ../forward.c ../flow.c ../unit-exports.c  \
                          ../dp_dev.c ../datapath_t.c
 
 SIMLINKFILES = $(patsubst ../%,%, $(SHAREDFILES))
@@ -38,7 +38,7 @@ SHARED_T_FILES =                                \
     ../unit.c
 UNIT_CFILES = $(patsubst ../%,%, $(SHARED_T_FILES))
 
-kFILES = ../datapath.h                                 \
+HFILES = ../datapath.h                                 \
        ../chain.h                              \
        ../crc32.h                              \
        ../flow.h                               \
index bbacf31..f00569d 100644 (file)
@@ -2,6 +2,7 @@
  * Distributed under the terms of the GNU GPL version 2.
  */
 
+#include <linux/init.h>
 #include <linux/module.h>
 #include "compat24.h"
 
index c9fc55a..fe7812a 100644 (file)
@@ -6,6 +6,7 @@
  *                             Johannes Berg <johannes@sipsolutions.net>
  */
 
+#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
index 1a1bb45..4b77008 100644 (file)
@@ -3,8 +3,6 @@
 
 #include_next <asm/atomic.h>
 
-#error "Cribbed from linux-2.6/include/asm-arm/atomic.h but untested"
-
 #ifdef __KERNEL__
 
 #if __LINUX_ARM_ARCH__ >= 6
@@ -40,11 +38,11 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
        int ret;
        unsigned long flags;
 
-       raw_local_irq_save(flags);
+       local_irq_save(flags);
        ret = v->counter;
        if (likely(ret == old))
                v->counter = new;
-       raw_local_irq_restore(flags);
+       local_irq_restore(flags);
 
        return ret;
 }
index 735c616..09802e5 100644 (file)
@@ -4,8 +4,6 @@
 #include_next <asm/atomic.h>
 #include <asm/system.h>
 
-#error "Cribbed from linux-2.6/include/asm-mips but not tested."
-
 #define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
 
 #endif /* asm/atomic.h */
index ae1d646..8a51548 100644 (file)
@@ -3,8 +3,6 @@
 
 #include <asm/system.h>
 
-#error "Cribbed from linux-2.6/include/asm-mips/barrier.h but untested."
-
 /* Not sure whether these really need to be defined, but the conservative
  * choice seems to be to define them. */
 #define CONFIG_WEAK_ORDERING 1
diff --git a/datapath/linux-2.4/compat-2.4/include-mips/asm/break.h b/datapath/linux-2.4/compat-2.4/include-mips/asm/break.h
new file mode 100644 (file)
index 0000000..53b0641
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __ASM_MIPS_BREAK_H_WRAPPER
+#define __ASM_MIPS_BREAK_H_WRAPPER 1
+
+#include <linux/version.h>
+#include_next <asm/break.h>
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25)
+
+/*
+ * The following break codes are or were in use for specific purposes in
+ * other MIPS operating systems.  Linux/MIPS doesn't use all of them.  The
+ * unused ones are here as placeholders; we might encounter them in
+ * non-Linux/MIPS object files or make use of them in the future.
+ */
+#define BRK_USERBP  0   /* User bp (used by debuggers) */
+#define BRK_KERNELBP    1   /* Break in the kernel */
+#define BRK_ABORT   2   /* Sometimes used by abort(3) to SIGIOT */
+#define BRK_BD_TAKEN    3   /* For bd slot emulation - not implemented */
+#define BRK_BD_NOTTAKEN 4   /* For bd slot emulation - not implemented */
+#define BRK_SSTEPBP 5   /* User bp (used by debuggers) */
+#define BRK_OVERFLOW    6   /* Overflow check */
+#define BRK_DIVZERO 7   /* Divide by zero check */
+#define BRK_RANGE   8   /* Range error check */
+#define BRK_STACKOVERFLOW 9 /* For Ada stackchecking */
+#define BRK_NORLD   10  /* No rld found - not used by Linux/MIPS */
+#define _BRK_THREADBP   11  /* For threads, user bp (used by debuggers) */
+#define BRK_MULOVF  1023    /* Multiply overflow */
+#define BRK_BUG     512 /* Used by BUG() */
+
+#endif /* linux kernel < 2.4.25 */
+
+#endif /* asm/break.h */
diff --git a/datapath/linux-2.4/compat-2.4/include-mips/asm/page.h b/datapath/linux-2.4/compat-2.4/include-mips/asm/page.h
new file mode 100644 (file)
index 0000000..93a3dff
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __ASM_MIPS_PAGE_H_WRAPPER
+#define __ASM_MIPS_PAGE_H_WRAPPER 1
+
+#include <linux/version.h>
+#include_next <asm/page.h>
+#include <asm/break.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25)
+
+#define BUG()                                                           \
+do {                                                                    \
+        __asm__ __volatile__("break %0" : : "i" (BRK_BUG));             \
+} while (0)
+
+#endif /* linux kernel < 2.4.25 */
+
+#endif /* asm/page.h */
index c1b0815..815b853 100644 (file)
@@ -3,8 +3,6 @@
 
 #include_next <asm/system.h>
 
-#error "Cribbed from linux-2.6/include/asm-mips/system.h but untested."
-
 #define __HAVE_ARCH_CMPXCHG 1
 
 static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
@@ -52,11 +50,11 @@ static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
        } else {
                unsigned long flags;
 
-               raw_local_irq_save(flags);
+               local_irq_save(flags);
                retval = *m;
                if (retval == old)
                        *m = new;
-               raw_local_irq_restore(flags);   /* implies memory barrier  */
+               local_irq_restore(flags);       /* implies memory barrier  */
        }
 
        smp_llsc_mb();
@@ -158,11 +156,11 @@ static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
        } else {
                unsigned long flags;
 
-               raw_local_irq_save(flags);
+               local_irq_save(flags);
                retval = *m;
                if (retval == old)
                        *m = new;
-               raw_local_irq_restore(flags);   /* implies memory barrier  */
+               local_irq_restore(flags);       /* implies memory barrier  */
        }
 
        smp_llsc_mb();
index a50f96c..a144f1c 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/version.h>
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,29)
 #include <linux/time.h>
+#include <linux/sched.h>
 #include <asm/param.h>
 /*
  * We define MAX_MSEC_OFFSET as the maximal value that can be accepted by
diff --git a/datapath/linux-2.4/compat-2.4/include/linux/llc.h b/datapath/linux-2.4/compat-2.4/include/linux/llc.h
new file mode 100644 (file)
index 0000000..09f2e6d
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef __LINUX_LLC_H
+#define __LINUX_LLC_H
+/*
+ * IEEE 802.2 User Interface SAPs for Linux, data structures and indicators.
+ *
+ * Copyright (c) 2001 by Jay Schulist <jschlst@samba.org>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#define __LLC_SOCK_SIZE__ 16   /* sizeof(sockaddr_llc), word align. */
+struct sockaddr_llc {
+       sa_family_t     sllc_family;    /* AF_LLC */
+       sa_family_t     sllc_arphrd;    /* ARPHRD_ETHER */
+       unsigned char   sllc_test;
+       unsigned char   sllc_xid;
+       unsigned char   sllc_ua;        /* UA data, only for SOCK_STREAM. */
+       unsigned char   sllc_sap;
+       unsigned char   sllc_mac[IFHWADDRLEN];
+       unsigned char   __pad[__LLC_SOCK_SIZE__ - sizeof(sa_family_t) * 2 -
+                             sizeof(unsigned char) * 4 - IFHWADDRLEN];
+};
+
+/* sockopt definitions. */
+enum llc_sockopts {
+       LLC_OPT_UNKNOWN = 0,
+       LLC_OPT_RETRY,          /* max retrans attempts. */
+       LLC_OPT_SIZE,           /* max PDU size (octets). */
+       LLC_OPT_ACK_TMR_EXP,    /* ack expire time (secs). */
+       LLC_OPT_P_TMR_EXP,      /* pf cycle expire time (secs). */
+       LLC_OPT_REJ_TMR_EXP,    /* rej sent expire time (secs). */
+       LLC_OPT_BUSY_TMR_EXP,   /* busy state expire time (secs). */
+       LLC_OPT_TX_WIN,         /* tx window size. */
+       LLC_OPT_RX_WIN,         /* rx window size. */
+       LLC_OPT_MAX
+};
+
+#define LLC_OPT_MAX_RETRY       100
+#define LLC_OPT_MAX_SIZE       4196
+#define LLC_OPT_MAX_WIN                 127
+#define LLC_OPT_MAX_ACK_TMR_EXP          60
+#define LLC_OPT_MAX_P_TMR_EXP    60
+#define LLC_OPT_MAX_REJ_TMR_EXP          60
+#define LLC_OPT_MAX_BUSY_TMR_EXP  60
+
+/* LLC SAP types. */
+#define LLC_SAP_NULL   0x00            /* NULL SAP.                    */
+#define LLC_SAP_LLC    0x02            /* LLC Sublayer Managment.      */
+#define LLC_SAP_SNA    0x04            /* SNA Path Control.            */
+#define LLC_SAP_PNM    0x0E            /* Proway Network Managment.    */      
+#define LLC_SAP_IP     0x06            /* TCP/IP.                      */
+#define LLC_SAP_BSPAN  0x42            /* Bridge Spanning Tree Proto   */
+#define LLC_SAP_MMS    0x4E            /* Manufacturing Message Srv.   */
+#define LLC_SAP_8208   0x7E            /* ISO 8208                     */
+#define LLC_SAP_3COM   0x80            /* 3COM.                        */
+#define LLC_SAP_PRO    0x8E            /* Proway Active Station List   */
+#define LLC_SAP_SNAP   0xAA            /* SNAP.                        */
+#define LLC_SAP_BANYAN 0xBC            /* Banyan.                      */
+#define LLC_SAP_IPX    0xE0            /* IPX/SPX.                     */
+#define LLC_SAP_NETBEUI        0xF0            /* NetBEUI.                     */
+#define LLC_SAP_LANMGR 0xF4            /* LanManager.                  */
+#define LLC_SAP_IMPL   0xF8            /* IMPL                         */
+#define LLC_SAP_DISC   0xFC            /* Discovery                    */
+#define LLC_SAP_OSI    0xFE            /* OSI Network Layers.          */
+#define LLC_SAP_LAR    0xDC            /* LAN Address Resolution       */
+#define LLC_SAP_RM     0xD4            /* Resource Management          */
+#define LLC_SAP_GLOBAL 0xFF            /* Global SAP.                  */
+
+#ifdef __KERNEL__
+#define LLC_SAP_DYN_START      0xC0
+#define LLC_SAP_DYN_STOP       0xDE
+#define LLC_SAP_DYN_TRIES      4
+
+#define llc_ui_skb_cb(__skb) ((struct sockaddr_llc *)&((__skb)->cb[0]))
+#endif /* __KERNEL__ */
+#endif /* __LINUX_LLC_H */
index 797a330..8ba5b78 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __LINUX_MODULE_WRAPPER_H
 #define __LINUX_MODULE_WRAPPER_H 1
 
+#include <linux/kernel.h>
 #include_next <linux/module.h>
 
 static inline int try_module_get(struct module *module)
index 3a19e73..f3c30e1 100644 (file)
@@ -33,8 +33,9 @@
 
 */
 
-#include <linux/types.h>
+#include <linux/init.h>
 #include <linux/module.h>
+#include <linux/types.h>
 #include <linux/jiffies.h>
 #include <linux/random.h>
 #include <linux/threads.h>
index 5a7cb55..1540203 100644 (file)
@@ -12,7 +12,7 @@ CFLAGS_EXTRA += -I $(srcdir)/.. -I $(srcdir)/datapath/  -I $(top_srcdir)/include
 # Files shared between 2.4 and 2.6 builds
 
 SHAREDFILES = ../chain.c ../crc32.c ../table-hash.c ../table-linear.c  \
-                       ../table-mac.c ../forward.c ../flow.c ../unit-exports.c \
+                       ../forward.c ../flow.c ../unit-exports.c \
                        ../datapath_t.c ../dp_dev.c \
                        compat-2.6/genetlink.c \
                        compat-2.6/random32.c 
diff --git a/datapath/table-mac.c b/datapath/table-mac.c
deleted file mode 100644 (file)
index 3d7e473..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Distributed under the terms of the GNU GPL version 2.
- * Copyright (c) 2007, 2008 The Board of Trustees of The Leland 
- * Stanford Junior University
- */
-
-#include "table.h"
-#include "crc32.h"
-#include "flow.h"
-#include "openflow.h"
-#include "datapath.h"
-
-#include <linux/slab.h>
-
-struct sw_table_mac {
-       struct sw_table swt;
-       spinlock_t lock;
-       struct crc32 crc32;
-       atomic_t n_flows;
-       unsigned int max_flows;
-       unsigned int bucket_mask; /* Number of buckets minus 1. */
-       struct hlist_head *buckets;
-};
-
-static struct hlist_head *find_bucket(struct sw_table *swt,
-                                                                        const struct sw_flow_key *key)
-{
-       struct sw_table_mac *tm = (struct sw_table_mac *) swt;
-       unsigned int crc = crc32_calculate(&tm->crc32, key, sizeof *key);
-       return &tm->buckets[crc & tm->bucket_mask];
-}
-
-static struct sw_flow *table_mac_lookup(struct sw_table *swt,
-                                                                               const struct sw_flow_key *key)
-{
-       struct hlist_head *bucket = find_bucket(swt, key);
-       struct hlist_node *pos;
-       struct sw_flow *flow;
-       hlist_for_each_entry_rcu (flow, pos, bucket, u.hnode)
-               if (!memcmp(key->dl_src, flow->key.dl_src, 6))
-                       return flow;
-       return NULL;
-}
-
-static int table_mac_insert(struct sw_table *swt, struct sw_flow *flow)
-{
-       struct sw_table_mac *tm = (struct sw_table_mac *) swt;
-       struct hlist_head *bucket;
-       struct hlist_node *pos;
-       unsigned long int flags;
-       struct sw_flow *f;
-
-       /* MAC table only handles flows that match on Ethernet
-          source address and wildcard everything else. */
-       if (likely(flow->key.wildcards != (OFPFW_ALL & ~OFPFW_DL_SRC)))
-                       return 0;
-       bucket = find_bucket(swt, &flow->key);
-
-       spin_lock_irqsave(&tm->lock, flags);
-       hlist_for_each_entry_rcu (f, pos, bucket, u.hnode) {
-               if (!memcmp(f->key.dl_src, flow->key.dl_src, 6)
-                                       && flow_del(f)) {
-                       hlist_replace_rcu(&f->u.hnode, &flow->u.hnode);
-                       spin_unlock_irqrestore(&tm->lock, flags);
-                       flow_deferred_free(f);
-                       return 1;
-               }
-       }
-
-       /* Table overflow? */
-       if (atomic_read(&tm->n_flows) >= tm->max_flows) {
-               spin_unlock_irqrestore(&tm->lock, flags);
-               return 0; 
-       }
-       atomic_inc(&tm->n_flows);
-
-       hlist_add_head_rcu(&flow->u.hnode, bucket);
-       spin_unlock_irqrestore(&tm->lock, flags);
-       return 1;
-}
-
-static int do_delete(struct sw_table *swt, struct sw_flow *flow)
-{
-       if (flow_del(flow)) {
-               hlist_del_rcu(&flow->u.hnode);
-               flow_deferred_free(flow);
-               return 1;
-       }
-       return 0;
-}
-
-/* Returns number of deleted flows. */
-static int table_mac_delete(struct sw_table *swt,
-                       const struct sw_flow_key *key, int strict)
-{
-               struct sw_table_mac *tm = (struct sw_table_mac *) swt;
-
-       if (key->wildcards == (OFPFW_ALL & ~OFPFW_DL_SRC)) {
-               struct sw_flow *flow = table_mac_lookup(swt, key);
-               if (flow && do_delete(swt, flow)) {
-                       atomic_dec(&tm->n_flows);
-                       return 1;
-               }
-               return 0;
-       } else {
-               unsigned int i;
-               int count = 0;
-               for (i = 0; i <= tm->bucket_mask; i++) {
-                       struct hlist_head *bucket = &tm->buckets[i];
-                       struct hlist_node *pos;
-                       struct sw_flow *flow;
-                       hlist_for_each_entry_rcu (flow, pos, bucket, u.hnode)
-                               if (flow_del_matches(&flow->key, key, strict))
-                                       count += do_delete(swt, flow);
-               }
-               if (count)
-                       atomic_sub(count, &tm->n_flows);
-               return count;
-       }
-}
-
-static int table_mac_timeout(struct datapath *dp, struct sw_table *swt)
-{
-       struct sw_table_mac *tm = (struct sw_table_mac *) swt;
-       unsigned int i;
-       int count = 0;
-
-       for (i = 0; i <= tm->bucket_mask; i++) {
-               struct hlist_head *bucket = &tm->buckets[i];
-               struct hlist_node *pos;
-               struct sw_flow *flow;
-               hlist_for_each_entry_rcu (flow, pos, bucket, u.hnode) {
-                       if (flow_timeout(flow)) {
-                               count += do_delete(swt, flow);
-                               if (dp->config.flags & OFPC_SEND_FLOW_EXP)
-                                       dp_send_flow_expired(dp, flow);
-                       }
-               }
-       }
-       if (count)
-               atomic_sub(count, &tm->n_flows);
-       return count;
-}
-
-static void table_mac_destroy(struct sw_table *swt)
-{
-       struct sw_table_mac *tm = (struct sw_table_mac *) swt;
-       unsigned int i;
-       for (i = 0; i <= tm->bucket_mask; i++) {
-               struct hlist_head *hlist = &tm->buckets[i];
-               while (!hlist_empty(hlist)) {
-                       struct sw_flow *flow = hlist_entry(hlist->first,
-                                          struct sw_flow, u.hnode);
-                       hlist_del(&flow->u.hnode);
-                       flow_free(flow);
-                       }
-       }
-       kfree(tm->buckets);
-       kfree(tm);
-}
-
-struct swt_iterator_mac {
-       struct sw_table_mac *tm;
-       unsigned int bucket_i;
-};
-
-static struct sw_flow *next_head_flow(struct swt_iterator_mac *im)
-{
-       for (; im->bucket_i <= im->tm->bucket_mask; im->bucket_i++) {
-               struct hlist_node *first = im->tm->buckets[im->bucket_i].first;
-               if (first != NULL) {
-                       struct sw_flow *f = hlist_entry(first,
-                                                       struct sw_flow,
-                                                       u.hnode);
-                       return f;
-               }
-       }
-       return NULL;
-}
-
-static int table_mac_iterator(struct sw_table *swt,
-                                 struct swt_iterator *swt_iter)
-{
-       struct swt_iterator_mac *im;
-
-       swt_iter->private = im = kmalloc(sizeof *im, GFP_KERNEL);
-       if (im == NULL)
-               return 0;
-
-       im->tm = (struct sw_table_mac *) swt;
-
-       if (atomic_read(&im->tm->n_flows) == 0)
-               swt_iter->flow = NULL;
-       else {
-               im->bucket_i = 0;
-               swt_iter->flow = next_head_flow(im);
-       }
-
-       return 1;
-}
-
-static void table_mac_next(struct swt_iterator *swt_iter)
-{
-       struct swt_iterator_mac *im;
-       struct hlist_node *next;
-
-       if (swt_iter->flow == NULL)
-               return;
-
-       im = (struct swt_iterator_mac *) swt_iter->private;
-
-       next = swt_iter->flow->u.hnode.next;
-       if (next != NULL) {
-               swt_iter->flow = hlist_entry(next, struct sw_flow, u.hnode);
-       } else {
-               im->bucket_i++;
-               swt_iter->flow = next_head_flow(im);
-       }
-}
-
-static void table_mac_iterator_destroy(struct swt_iterator *swt_iter)
-{
-       kfree(swt_iter->private);
-}
-
-static void table_mac_stats(struct sw_table *swt, struct sw_table_stats *stats)
-{
-       struct sw_table_mac *tm = (struct sw_table_mac *) swt;
-       stats->name = "mac";
-       stats->n_flows = atomic_read(&tm->n_flows);
-       stats->max_flows = tm->max_flows;
-}
-
-struct sw_table *table_mac_create(unsigned int n_buckets,
-                                                                 unsigned int max_flows)
-{
-       struct sw_table_mac *tm;
-       struct sw_table *swt;
-
-       tm = kzalloc(sizeof *tm, GFP_KERNEL);
-       if (tm == NULL)
-               return NULL;
-
-       BUG_ON(n_buckets & (n_buckets - 1));
-
-       tm->buckets = kzalloc(n_buckets * sizeof *tm->buckets, GFP_KERNEL);
-       if (tm->buckets == NULL) {
-               printk("failed to allocate %u buckets\n", n_buckets);
-               kfree(tm);
-               return NULL;
-       }
-       tm->bucket_mask = n_buckets - 1;
-
-       swt = &tm->swt;
-       swt->lookup = table_mac_lookup;
-       swt->insert = table_mac_insert;
-       swt->delete = table_mac_delete;
-       swt->timeout = table_mac_timeout;
-       swt->destroy = table_mac_destroy;
-       swt->stats = table_mac_stats;
-
-       swt->iterator = table_mac_iterator;
-       swt->iterator_next = table_mac_next;
-       swt->iterator_destroy = table_mac_iterator_destroy;
-
-       crc32_init(&tm->crc32, 0x04C11DB7); /* Ethernet CRC. */
-       atomic_set(&tm->n_flows, 0);
-       tm->max_flows = max_flows;
-       spin_lock_init(&tm->lock);
-
-       return swt;
-}
index 9a30367..dcb72b9 100644 (file)
@@ -63,8 +63,6 @@ struct sw_table {
        void (*stats)(struct sw_table *table, struct sw_table_stats *stats);
 };
 
-struct sw_table *table_mac_create(unsigned int n_buckets,
-               unsigned int max_flows);
 struct sw_table *table_hash_create(unsigned int polynomial,
                unsigned int n_buckets);
 struct sw_table *table_hash2_create(unsigned int poly0, unsigned int buckets0,
index 8ab0d58..42687cf 100644 (file)
@@ -755,30 +755,18 @@ complex_test_destr:
 
 void run_table_t(void)
 {
-       int mac_buckets, mac_max, linear_max, hash_buckets, hash2_buckets1;
+       int linear_max, hash_buckets, hash2_buckets1;
        int hash2_buckets2, num_flows, num_iterations;
        int i;
 
        struct sw_table *swt;
 
        /* Most basic operations. */
-       simple_insert_delete(table_mac_create(2048, 65536),
-                        OFPFW_ALL & ~OFPFW_DL_SRC);
        simple_insert_delete(table_linear_create(2048), 0);
        simple_insert_delete(table_hash_create(0x04C11DB7, 2048), 0);
        simple_insert_delete(table_hash2_create(0x04C11DB7, 2048,
                                                0x1EDC6F41, 2048), 0);
 
-       /* MAC table operations. */
-       multiple_insert_destroy(table_mac_create(2048, 65536), 1024,
-                               OFPFW_ALL & ~OFPFW_DL_SRC, 0, 0);
-       multiple_insert_destroy(table_mac_create(2048, 65536), 2048,
-                               OFPFW_ALL & ~OFPFW_DL_SRC, 0, 0);
-       multiple_insert_destroy(table_mac_create(2048, 65536), 65535,
-                               OFPFW_ALL & ~OFPFW_DL_SRC, 0, 0);
-       multiple_insert_destroy(table_mac_create(2048, 65536),
-                               131072, OFPFW_ALL & ~OFPFW_DL_SRC, 65536, 65536);
-
        /* Linear table operations. */
        multiple_insert_destroy(table_linear_create(2048), 1024, 0, 0, 0);
        multiple_insert_destroy(table_linear_create(2048), 2048, 0, 0, 0);
@@ -817,8 +805,6 @@ void run_table_t(void)
        multiple_insert_destroy(table_hash2_create(0x04C11DB7, 1<<20,
                                                0x04C11DB7, 1<<20), 1<<16, 0, 0, 100);
 
-       mac_buckets = 1024;
-       mac_max = 2048;
        linear_max = 2048;
        hash_buckets = 2048;
        hash2_buckets1 = 1024;
@@ -835,7 +821,7 @@ void run_table_t(void)
        printk("  complex_add_delete_test with %d flows and %d iterations\n\n",
                                num_flows, num_iterations);
 
-       for (i = 0; i < 4; i++) {
+       for (i = 0; i < 3; i++) {
                unsigned int mask = i == 0 ?  : 0;
 
                if (unit_failed())
@@ -844,16 +830,12 @@ void run_table_t(void)
                mask = 0;
                switch (i) {
                case 0:
-                       swt = table_mac_create(mac_buckets, mac_max);
-                       mask = OFPFW_ALL & ~OFPFW_DL_SRC;
-                       break;
-               case 1:
                        swt = table_linear_create(linear_max);
                        break;
-               case 2:
+               case 1:
                        swt = table_hash_create (0x04C11DB7, hash_buckets);
                        break;
-               case 3:
+               case 2:
                        swt = table_hash2_create(0x04C11DB7, hash2_buckets1,
                                                 0x1EDC6F41, hash2_buckets2);
                        break;
@@ -867,7 +849,7 @@ void run_table_t(void)
                        return;
                }
                printk("Testing %s table with %d buckets and %d max flows...\n",
-                                       table_name(swt), mac_buckets, mac_max);
+                                       table_name(swt), hash_buckets, num_flows);
                iterator_test(swt, 0, mask);
                iterator_test(swt, num_flows, mask);
                add_test(swt, mask);
index 9db5bdd..0dc3fa0 100644 (file)
@@ -14,7 +14,6 @@ EXPORT_SYMBOL(flow_alloc);
 EXPORT_SYMBOL(flow_free);
 EXPORT_SYMBOL(flow_cache);
 
-EXPORT_SYMBOL(table_mac_create);
 EXPORT_SYMBOL(table_hash_create);
 EXPORT_SYMBOL(table_hash2_create);
 EXPORT_SYMBOL(table_linear_create);
index d9e06f2..94a4439 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <linux/autoconf.h>
+#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/version.h>
index ccd52b0..48bedbf 100644 (file)
@@ -46,6 +46,7 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <sys/socket.h>
+#include <linux/types.h>
 #include <linux/netlink.h>
 #include <linux/genetlink.h>
 #include <linux/version.h>
index 0fd739b..e749477 100644 (file)
@@ -34,6 +34,7 @@
 #ifndef OPENFLOW_NETLINK_H
 #define OPENFLOW_NETLINK_H 1
 
+#include <linux/types.h>
 #include <linux/netlink.h>
 
 #define DP_GENL_FAMILY_NAME "OpenFlow"
index 4969cea..7462b88 100644 (file)
@@ -61,7 +61,11 @@ enum ofp_port {
     OFPP_MAX = 0x100,
 
     /* Fake output "ports". */
-    OFPP_NORMAL     = 0xfffa,  /* Process with normal L2/L3 switching */
+    OFPP_TABLE      = 0xfff9,  /* Perform actions in flow table.  
+                                * NB: This can only be the destination
+                                * port for packet-out messages. 
+                                */
+    OFPP_NORMAL     = 0xfffa,  /* Process with normal L2/L3 switching. */
     OFPP_FLOOD      = 0xfffb,  /* All physical ports except input port and 
                                   those disabled by STP. */
     OFPP_ALL        = 0xfffc,  /* All physical ports except input port. */
index eb199e5..898f740 100644 (file)
@@ -150,6 +150,7 @@ nl_sock_create(int protocol, int multicast_group,
         goto error_free_pid;
     }
 
+#ifdef NETLINK_ADD_MEMBERSHIP
     /* This method of joining multicast groups is only supported by newish
      * kernels, but it allows for an arbitrary number of multicast groups. */
     if (multicast_group > 32
@@ -159,6 +160,7 @@ nl_sock_create(int protocol, int multicast_group,
                  multicast_group, strerror(errno));
         goto error_free_pid;
     }
+#endif
 
     *sockp = sock;
     return 0;