From: Ben Pfaff Date: Tue, 15 Apr 2008 16:57:38 +0000 (-0700) Subject: Merge remote branch 'repo/master' into stats X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6f8d45bf7dd4007410f42f7233243cff409d06c6;hp=5bb08bc0efb4aaf4349073e07383728cf9d2f77d;p=openvswitch Merge remote branch 'repo/master' into stats Conflicts: datapath/table-mac.c --- diff --git a/ChangeLog b/ChangeLog index 056f51a9..97aa4474 100644 --- 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 d5fa4229..3031bfe4 100644 --- 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 diff --git a/configure.ac b/configure.ac index d86e553c..581157ee 100644 --- a/configure.ac +++ b/configure.ac @@ -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 ]) + [#include +#include ]) AM_CONDITIONAL([HAVE_NETLINK], [test "$HAVE_NETLINK" = yes]) if test "$HAVE_NETLINK" = yes; then AC_DEFINE([HAVE_NETLINK], [1], diff --git a/datapath/Makefile.am b/datapath/Makefile.am index 3dda217a..64c5077a 100644 --- a/datapath/Makefile.am +++ b/datapath/Makefile.am @@ -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\ diff --git a/datapath/chain.c b/datapath/chain.c index 2f8708e0..6d3784cc 100644 --- a/datapath/chain.c +++ b/datapath/chain.c @@ -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); diff --git a/datapath/datapath.c b/datapath/datapath.c index 0a266cb4..639a4836 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -6,6 +6,7 @@ /* Functions for managing the dp interface/device. */ +#include #include #include #include @@ -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]; diff --git a/datapath/forward.c b/datapath/forward.c index ced0cac6..7e987e33 100644 --- a/datapath/forward.c +++ b/datapath/forward.c @@ -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; iactions[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) diff --git a/datapath/forward.h b/datapath/forward.h index 3e7686fa..ce4d3b14 100644 --- a/datapath/forward.h +++ b/datapath/forward.h @@ -2,6 +2,7 @@ #define FORWARD_H 1 #include +#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 *); diff --git a/datapath/linux-2.4/Makefile.in b/datapath/linux-2.4/Makefile.in index 8e4ba5ba..25a53b37 100644 --- a/datapath/linux-2.4/Makefile.in +++ b/datapath/linux-2.4/Makefile.in @@ -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 \ diff --git a/datapath/linux-2.4/compat-2.4/compat24.c b/datapath/linux-2.4/compat-2.4/compat24.c index bbacf311..f00569df 100644 --- a/datapath/linux-2.4/compat-2.4/compat24.c +++ b/datapath/linux-2.4/compat-2.4/compat24.c @@ -2,6 +2,7 @@ * Distributed under the terms of the GNU GPL version 2. */ +#include #include #include "compat24.h" diff --git a/datapath/linux-2.4/compat-2.4/genetlink.c b/datapath/linux-2.4/compat-2.4/genetlink.c index c9fc55a6..fe7812a7 100644 --- a/datapath/linux-2.4/compat-2.4/genetlink.c +++ b/datapath/linux-2.4/compat-2.4/genetlink.c @@ -6,6 +6,7 @@ * Johannes Berg */ +#include #include #include #include diff --git a/datapath/linux-2.4/compat-2.4/include-arm/asm/atomic.h b/datapath/linux-2.4/compat-2.4/include-arm/asm/atomic.h index 1a1bb450..4b770086 100644 --- a/datapath/linux-2.4/compat-2.4/include-arm/asm/atomic.h +++ b/datapath/linux-2.4/compat-2.4/include-arm/asm/atomic.h @@ -3,8 +3,6 @@ #include_next -#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; } diff --git a/datapath/linux-2.4/compat-2.4/include-mips/asm/atomic.h b/datapath/linux-2.4/compat-2.4/include-mips/asm/atomic.h index 735c6168..09802e57 100644 --- a/datapath/linux-2.4/compat-2.4/include-mips/asm/atomic.h +++ b/datapath/linux-2.4/compat-2.4/include-mips/asm/atomic.h @@ -4,8 +4,6 @@ #include_next #include -#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 */ diff --git a/datapath/linux-2.4/compat-2.4/include-mips/asm/barrier.h b/datapath/linux-2.4/compat-2.4/include-mips/asm/barrier.h index ae1d6460..8a515488 100644 --- a/datapath/linux-2.4/compat-2.4/include-mips/asm/barrier.h +++ b/datapath/linux-2.4/compat-2.4/include-mips/asm/barrier.h @@ -3,8 +3,6 @@ #include -#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 index 00000000..53b0641d --- /dev/null +++ b/datapath/linux-2.4/compat-2.4/include-mips/asm/break.h @@ -0,0 +1,33 @@ +#ifndef __ASM_MIPS_BREAK_H_WRAPPER +#define __ASM_MIPS_BREAK_H_WRAPPER 1 + +#include +#include_next + + +#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 index 00000000..93a3dffc --- /dev/null +++ b/datapath/linux-2.4/compat-2.4/include-mips/asm/page.h @@ -0,0 +1,17 @@ +#ifndef __ASM_MIPS_PAGE_H_WRAPPER +#define __ASM_MIPS_PAGE_H_WRAPPER 1 + +#include +#include_next +#include + +#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 */ diff --git a/datapath/linux-2.4/compat-2.4/include-mips/asm/system.h b/datapath/linux-2.4/compat-2.4/include-mips/asm/system.h index c1b08154..815b8530 100644 --- a/datapath/linux-2.4/compat-2.4/include-mips/asm/system.h +++ b/datapath/linux-2.4/compat-2.4/include-mips/asm/system.h @@ -3,8 +3,6 @@ #include_next -#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(); diff --git a/datapath/linux-2.4/compat-2.4/include/linux/delay.h b/datapath/linux-2.4/compat-2.4/include/linux/delay.h index a50f96c0..a144f1c3 100644 --- a/datapath/linux-2.4/compat-2.4/include/linux/delay.h +++ b/datapath/linux-2.4/compat-2.4/include/linux/delay.h @@ -6,6 +6,7 @@ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,29) #include +#include #include /* * 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 index 00000000..09f2e6d0 --- /dev/null +++ b/datapath/linux-2.4/compat-2.4/include/linux/llc.h @@ -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 + * + * 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 */ diff --git a/datapath/linux-2.4/compat-2.4/include/linux/module.h b/datapath/linux-2.4/compat-2.4/include/linux/module.h index 797a330a..8ba5b781 100644 --- a/datapath/linux-2.4/compat-2.4/include/linux/module.h +++ b/datapath/linux-2.4/compat-2.4/include/linux/module.h @@ -1,6 +1,7 @@ #ifndef __LINUX_MODULE_WRAPPER_H #define __LINUX_MODULE_WRAPPER_H 1 +#include #include_next static inline int try_module_get(struct module *module) diff --git a/datapath/linux-2.4/compat-2.4/random32.c b/datapath/linux-2.4/compat-2.4/random32.c index 3a19e73a..f3c30e19 100644 --- a/datapath/linux-2.4/compat-2.4/random32.c +++ b/datapath/linux-2.4/compat-2.4/random32.c @@ -33,8 +33,9 @@ */ -#include +#include #include +#include #include #include #include diff --git a/datapath/linux-2.6/Makefile.in b/datapath/linux-2.6/Makefile.in index 5a7cb55f..15402038 100644 --- a/datapath/linux-2.6/Makefile.in +++ b/datapath/linux-2.6/Makefile.in @@ -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 index 3d7e4733..00000000 --- a/datapath/table-mac.c +++ /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 - -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; -} diff --git a/datapath/table.h b/datapath/table.h index 9a303670..dcb72b9d 100644 --- a/datapath/table.h +++ b/datapath/table.h @@ -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, diff --git a/datapath/table_t.c b/datapath/table_t.c index 8ab0d583..42687cf2 100644 --- a/datapath/table_t.c +++ b/datapath/table_t.c @@ -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); diff --git a/datapath/unit-exports.c b/datapath/unit-exports.c index 9db5bdd3..0dc3fa0b 100644 --- a/datapath/unit-exports.c +++ b/datapath/unit-exports.c @@ -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); diff --git a/datapath/unit.c b/datapath/unit.c index d9e06f27..94a4439c 100644 --- a/datapath/unit.c +++ b/datapath/unit.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include diff --git a/include/netlink.h b/include/netlink.h index ccd52b0a..48bedbfd 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include diff --git a/include/openflow-netlink.h b/include/openflow-netlink.h index 0fd739b3..e7494777 100644 --- a/include/openflow-netlink.h +++ b/include/openflow-netlink.h @@ -34,6 +34,7 @@ #ifndef OPENFLOW_NETLINK_H #define OPENFLOW_NETLINK_H 1 +#include #include #define DP_GENL_FAMILY_NAME "OpenFlow" diff --git a/include/openflow.h b/include/openflow.h index 4969cea8..7462b884 100644 --- a/include/openflow.h +++ b/include/openflow.h @@ -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. */ diff --git a/lib/netlink.c b/lib/netlink.c index eb199e59..898f7400 100644 --- a/lib/netlink.c +++ b/lib/netlink.c @@ -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;